Added $assume cell type
[yosys.git] / kernel / celltypes.h
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #ifndef CELLTYPES_H
21 #define CELLTYPES_H
22
23 #include <kernel/yosys.h>
24
25 YOSYS_NAMESPACE_BEGIN
26
27 struct CellType
28 {
29 RTLIL::IdString type;
30 pool<RTLIL::IdString> inputs, outputs;
31 bool is_evaluable;
32 };
33
34 struct CellTypes
35 {
36 dict<RTLIL::IdString, CellType> cell_types;
37
38 CellTypes()
39 {
40 }
41
42 CellTypes(RTLIL::Design *design)
43 {
44 setup(design);
45 }
46
47 void setup(RTLIL::Design *design = NULL)
48 {
49 if (design)
50 setup_design(design);
51
52 setup_internals();
53 setup_internals_mem();
54 setup_stdcells();
55 setup_stdcells_mem();
56 }
57
58 void setup_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs, bool is_evaluable = false)
59 {
60 CellType ct = {type, inputs, outputs, is_evaluable};
61 cell_types[ct.type] = ct;
62 }
63
64 void setup_module(RTLIL::Module *module)
65 {
66 pool<RTLIL::IdString> inputs, outputs;
67 for (RTLIL::IdString wire_name : module->ports) {
68 RTLIL::Wire *wire = module->wire(wire_name);
69 if (wire->port_input)
70 inputs.insert(wire->name);
71 if (wire->port_output)
72 outputs.insert(wire->name);
73 }
74 setup_type(module->name, inputs, outputs);
75 }
76
77 void setup_design(RTLIL::Design *design)
78 {
79 for (auto module : design->modules())
80 setup_module(module);
81 }
82
83 void setup_internals()
84 {
85 std::vector<RTLIL::IdString> unary_ops = {
86 "$not", "$pos", "$neg",
87 "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
88 "$logic_not", "$slice", "$lut"
89 };
90
91 std::vector<RTLIL::IdString> binary_ops = {
92 "$and", "$or", "$xor", "$xnor",
93 "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
94 "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
95 "$add", "$sub", "$mul", "$div", "$mod", "$pow",
96 "$logic_and", "$logic_or", "$concat", "$macc"
97 };
98
99 IdString A = "\\A", B = "\\B", S = "\\S", Y = "\\Y";
100 IdString P = "\\P", G = "\\G", C = "\\C", X = "\\X";
101 IdString BI = "\\BI", CI = "\\CI", CO = "\\CO", EN = "\\EN";
102
103 for (auto type : unary_ops)
104 setup_type(type, {A}, {Y}, true);
105
106 for (auto type : binary_ops)
107 setup_type(type, {A, B}, {Y}, true);
108
109 for (auto type : std::vector<RTLIL::IdString>({"$mux", "$pmux"}))
110 setup_type(type, {A, B, S}, {Y}, true);
111
112 setup_type("$lcu", {P, G, CI}, {CO}, true);
113 setup_type("$alu", {A, B, CI, BI}, {X, Y, CO}, true);
114 setup_type("$fa", {A, B, C}, {X, Y}, true);
115
116 setup_type("$assert", {A, EN}, pool<RTLIL::IdString>(), true);
117 setup_type("$assume", {A, EN}, pool<RTLIL::IdString>(), true);
118 setup_type("$equiv", {A, B}, {Y}, true);
119 }
120
121 void setup_internals_mem()
122 {
123 IdString SET = "\\SET", CLR = "\\CLR", CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN";
124 IdString Q = "\\Q", D = "\\D", ADDR = "\\ADDR", DATA = "\\DATA";
125 IdString RD_CLK = "\\RD_CLK", RD_ADDR = "\\RD_ADDR", WR_CLK = "\\WR_CLK", WR_EN = "\\WR_EN";
126 IdString WR_ADDR = "\\WR_ADDR", WR_DATA = "\\WR_DATA", RD_DATA = "\\RD_DATA";
127 IdString CTRL_IN = "\\CTRL_IN", CTRL_OUT = "\\CTRL_OUT";
128
129 setup_type("$sr", {SET, CLR}, {Q});
130 setup_type("$dff", {CLK, D}, {Q});
131 setup_type("$dffe", {CLK, EN, D}, {Q});
132 setup_type("$dffsr", {CLK, SET, CLR, D}, {Q});
133 setup_type("$adff", {CLK, ARST, D}, {Q});
134 setup_type("$dlatch", {EN, D}, {Q});
135 setup_type("$dlatchsr", {EN, SET, CLR, D}, {Q});
136
137 setup_type("$memrd", {CLK, ADDR}, {DATA});
138 setup_type("$memwr", {CLK, EN, ADDR, DATA}, pool<RTLIL::IdString>());
139 setup_type("$meminit", {ADDR, DATA}, pool<RTLIL::IdString>());
140 setup_type("$mem", {RD_CLK, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA});
141
142 setup_type("$fsm", {CLK, ARST, CTRL_IN}, {CTRL_OUT});
143 }
144
145 void setup_stdcells()
146 {
147 IdString A = "\\A", B = "\\B", C = "\\C", D = "\\D", S = "\\S", Y = "\\Y";
148 setup_type("$_BUF_", {A}, {Y}, true);
149 setup_type("$_NOT_", {A}, {Y}, true);
150 setup_type("$_AND_", {A, B}, {Y}, true);
151 setup_type("$_NAND_", {A, B}, {Y}, true);
152 setup_type("$_OR_", {A, B}, {Y}, true);
153 setup_type("$_NOR_", {A, B}, {Y}, true);
154 setup_type("$_XOR_", {A, B}, {Y}, true);
155 setup_type("$_XNOR_", {A, B}, {Y}, true);
156 setup_type("$_MUX_", {A, B, S}, {Y}, true);
157 setup_type("$_AOI3_", {A, B, C}, {Y}, true);
158 setup_type("$_OAI3_", {A, B, C}, {Y}, true);
159 setup_type("$_AOI4_", {A, B, C, D}, {Y}, true);
160 setup_type("$_OAI4_", {A, B, C, D}, {Y}, true);
161 }
162
163 void setup_stdcells_mem()
164 {
165 IdString S = "\\S", R = "\\R", C = "\\C";
166 IdString D = "\\D", Q = "\\Q", E = "\\E";
167
168 std::vector<char> list_np = {'N', 'P'}, list_01 = {'0', '1'};
169
170 for (auto c1 : list_np)
171 for (auto c2 : list_np)
172 setup_type(stringf("$_SR_%c%c_", c1, c2), {S, R}, {Q});
173
174 for (auto c1 : list_np)
175 setup_type(stringf("$_DFF_%c_", c1), {C, D}, {Q});
176
177 for (auto c1 : list_np)
178 for (auto c2 : list_np)
179 setup_type(stringf("$_DFFE_%c%c_", c1, c2), {C, D, E}, {Q});
180
181 for (auto c1 : list_np)
182 for (auto c2 : list_np)
183 for (auto c3 : list_01)
184 setup_type(stringf("$_DFF_%c%c%c_", c1, c2, c3), {C, R, D}, {Q});
185
186 for (auto c1 : list_np)
187 for (auto c2 : list_np)
188 for (auto c3 : list_np)
189 setup_type(stringf("$_DFFSR_%c%c%c_", c1, c2, c3), {C, S, R, D}, {Q});
190
191 for (auto c1 : list_np)
192 setup_type(stringf("$_DLATCH_%c_", c1), {E, D}, {Q});
193
194 for (auto c1 : list_np)
195 for (auto c2 : list_np)
196 for (auto c3 : list_np)
197 setup_type(stringf("$_DLATCHSR_%c%c%c_", c1, c2, c3), {E, S, R, D}, {Q});
198 }
199
200 void clear()
201 {
202 cell_types.clear();
203 }
204
205 bool cell_known(RTLIL::IdString type)
206 {
207 return cell_types.count(type) != 0;
208 }
209
210 bool cell_output(RTLIL::IdString type, RTLIL::IdString port)
211 {
212 auto it = cell_types.find(type);
213 return it != cell_types.end() && it->second.outputs.count(port) != 0;
214 }
215
216 bool cell_input(RTLIL::IdString type, RTLIL::IdString port)
217 {
218 auto it = cell_types.find(type);
219 return it != cell_types.end() && it->second.inputs.count(port) != 0;
220 }
221
222 bool cell_evaluable(RTLIL::IdString type)
223 {
224 auto it = cell_types.find(type);
225 return it != cell_types.end() && it->second.is_evaluable;
226 }
227
228 static RTLIL::Const eval_not(RTLIL::Const v)
229 {
230 for (auto &bit : v.bits)
231 if (bit == RTLIL::S0) bit = RTLIL::S1;
232 else if (bit == RTLIL::S1) bit = RTLIL::S0;
233 return v;
234 }
235
236 static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
237 {
238 if (type == "$sshr" && !signed1)
239 type = "$shr";
240 if (type == "$sshl" && !signed1)
241 type = "$shl";
242
243 if (type != "$sshr" && type != "$sshl" && type != "$shr" && type != "$shl" && type != "$shift" && type != "$shiftx" &&
244 type != "$pos" && type != "$neg" && type != "$not") {
245 if (!signed1 || !signed2)
246 signed1 = false, signed2 = false;
247 }
248
249 #define HANDLE_CELL_TYPE(_t) if (type == "$" #_t) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
250 HANDLE_CELL_TYPE(not)
251 HANDLE_CELL_TYPE(and)
252 HANDLE_CELL_TYPE(or)
253 HANDLE_CELL_TYPE(xor)
254 HANDLE_CELL_TYPE(xnor)
255 HANDLE_CELL_TYPE(reduce_and)
256 HANDLE_CELL_TYPE(reduce_or)
257 HANDLE_CELL_TYPE(reduce_xor)
258 HANDLE_CELL_TYPE(reduce_xnor)
259 HANDLE_CELL_TYPE(reduce_bool)
260 HANDLE_CELL_TYPE(logic_not)
261 HANDLE_CELL_TYPE(logic_and)
262 HANDLE_CELL_TYPE(logic_or)
263 HANDLE_CELL_TYPE(shl)
264 HANDLE_CELL_TYPE(shr)
265 HANDLE_CELL_TYPE(sshl)
266 HANDLE_CELL_TYPE(sshr)
267 HANDLE_CELL_TYPE(shift)
268 HANDLE_CELL_TYPE(shiftx)
269 HANDLE_CELL_TYPE(lt)
270 HANDLE_CELL_TYPE(le)
271 HANDLE_CELL_TYPE(eq)
272 HANDLE_CELL_TYPE(ne)
273 HANDLE_CELL_TYPE(eqx)
274 HANDLE_CELL_TYPE(nex)
275 HANDLE_CELL_TYPE(ge)
276 HANDLE_CELL_TYPE(gt)
277 HANDLE_CELL_TYPE(add)
278 HANDLE_CELL_TYPE(sub)
279 HANDLE_CELL_TYPE(mul)
280 HANDLE_CELL_TYPE(div)
281 HANDLE_CELL_TYPE(mod)
282 HANDLE_CELL_TYPE(pow)
283 HANDLE_CELL_TYPE(pos)
284 HANDLE_CELL_TYPE(neg)
285 #undef HANDLE_CELL_TYPE
286
287 if (type == "$_BUF_")
288 return arg1;
289 if (type == "$_NOT_")
290 return eval_not(arg1);
291 if (type == "$_AND_")
292 return const_and(arg1, arg2, false, false, 1);
293 if (type == "$_NAND_")
294 return eval_not(const_and(arg1, arg2, false, false, 1));
295 if (type == "$_OR_")
296 return const_or(arg1, arg2, false, false, 1);
297 if (type == "$_NOR_")
298 return eval_not(const_and(arg1, arg2, false, false, 1));
299 if (type == "$_XOR_")
300 return const_xor(arg1, arg2, false, false, 1);
301 if (type == "$_XNOR_")
302 return const_xnor(arg1, arg2, false, false, 1);
303
304 log_abort();
305 }
306
307 static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2)
308 {
309 if (cell->type == "$slice") {
310 RTLIL::Const ret;
311 int width = cell->parameters.at("\\Y_WIDTH").as_int();
312 int offset = cell->parameters.at("\\OFFSET").as_int();
313 ret.bits.insert(ret.bits.end(), arg1.bits.begin()+offset, arg1.bits.begin()+offset+width);
314 return ret;
315 }
316
317 if (cell->type == "$concat") {
318 RTLIL::Const ret = arg1;
319 ret.bits.insert(ret.bits.end(), arg2.bits.begin(), arg2.bits.end());
320 return ret;
321 }
322
323 if (cell->type == "$lut")
324 {
325 int width = cell->parameters.at("\\WIDTH").as_int();
326
327 std::vector<RTLIL::State> t = cell->parameters.at("\\LUT").bits;
328 while (GetSize(t) < (1 << width))
329 t.push_back(RTLIL::S0);
330 t.resize(1 << width);
331
332 for (int i = width-1; i >= 0; i--) {
333 RTLIL::State sel = arg1.bits.at(i);
334 std::vector<RTLIL::State> new_t;
335 if (sel == RTLIL::S0)
336 new_t = std::vector<RTLIL::State>(t.begin(), t.begin() + GetSize(t)/2);
337 else if (sel == RTLIL::S1)
338 new_t = std::vector<RTLIL::State>(t.begin() + GetSize(t)/2, t.end());
339 else
340 for (int j = 0; j < GetSize(t)/2; j++)
341 new_t.push_back(t[j] == t[j + GetSize(t)/2] ? t[j] : RTLIL::Sx);
342 t.swap(new_t);
343 }
344
345 log_assert(GetSize(t) == 1);
346 return t;
347 }
348
349 bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
350 bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
351 int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1;
352 return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len);
353 }
354
355 static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3)
356 {
357 if (cell->type.in("$mux", "$pmux", "$_MUX_")) {
358 RTLIL::Const ret = arg1;
359 for (size_t i = 0; i < arg3.bits.size(); i++)
360 if (arg3.bits[i] == RTLIL::State::S1) {
361 std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size());
362 ret = RTLIL::Const(bits);
363 }
364 return ret;
365 }
366
367 if (cell->type == "$_AOI3_")
368 return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1));
369 if (cell->type == "$_OAI3_")
370 return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1));
371
372 log_assert(arg3.bits.size() == 0);
373 return eval(cell, arg1, arg2);
374 }
375
376 static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4)
377 {
378 if (cell->type == "$_AOI4_")
379 return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
380 if (cell->type == "$_OAI4_")
381 return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
382
383 log_assert(arg4.bits.size() == 0);
384 return eval(cell, arg1, arg2, arg3);
385 }
386 };
387
388 // initialized by yosys_setup()
389 extern CellTypes yosys_celltypes;
390
391 YOSYS_NAMESPACE_END
392
393 #endif
394