Added additional gate types: $_NAND_ $_NOR_ $_XNOR_ $_AOI3_ $_OAI3_ $_AOI4_ $_OAI4_
[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 <set>
24 #include <string>
25 #include <stdlib.h>
26
27 #include <kernel/rtlil.h>
28 #include <kernel/log.h>
29
30 struct CellType
31 {
32 RTLIL::IdString type;
33 std::set<RTLIL::IdString> inputs, outputs;
34 bool is_evaluable;
35 };
36
37 struct CellTypes
38 {
39 std::map<RTLIL::IdString, CellType> cell_types;
40
41 CellTypes()
42 {
43 }
44
45 CellTypes(RTLIL::Design *design)
46 {
47 setup(design);
48 }
49
50 void setup(RTLIL::Design *design = NULL)
51 {
52 if (design)
53 setup_design(design);
54
55 setup_internals();
56 setup_internals_mem();
57 setup_stdcells();
58 setup_stdcells_mem();
59 }
60
61 void setup_type(RTLIL::IdString type, const std::set<RTLIL::IdString> &inputs, const std::set<RTLIL::IdString> &outputs, bool is_evaluable = false)
62 {
63 CellType ct = {type, inputs, outputs, is_evaluable};
64 cell_types[ct.type] = ct;
65 }
66
67 void setup_module(RTLIL::Module *module)
68 {
69 std::set<RTLIL::IdString> inputs, outputs;
70 for (RTLIL::IdString wire_name : module->ports) {
71 RTLIL::Wire *wire = module->wire(wire_name);
72 if (wire->port_input)
73 inputs.insert(wire->name);
74 if (wire->port_output)
75 outputs.insert(wire->name);
76 }
77 setup_type(module->name, inputs, outputs);
78 }
79
80 void setup_design(RTLIL::Design *design)
81 {
82 for (auto module : design->modules())
83 setup_module(module);
84 }
85
86 void setup_internals()
87 {
88 std::vector<RTLIL::IdString> unary_ops = {
89 "$not", "$pos", "$bu0", "$neg",
90 "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
91 "$logic_not", "$slice", "$lut"
92 };
93
94 std::vector<RTLIL::IdString> binary_ops = {
95 "$and", "$or", "$xor", "$xnor",
96 "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
97 "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
98 "$add", "$sub", "$mul", "$div", "$mod", "$pow",
99 "$logic_and", "$logic_or", "$concat"
100 };
101
102 for (auto type : unary_ops)
103 setup_type(type, {"\\A"}, {"\\Y"}, true);
104
105 for (auto type : binary_ops)
106 setup_type(type, {"\\A", "\\B"}, {"\\Y"}, true);
107
108 for (auto type : std::vector<RTLIL::IdString>({"$mux", "$pmux"}))
109 setup_type(type, {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
110
111 setup_type("$assert", {"\\A", "\\EN"}, {}, true);
112 }
113
114 void setup_internals_mem()
115 {
116 setup_type("$sr", {"\\SET", "\\CLR"}, {"\\Q"});
117 setup_type("$dff", {"\\CLK", "\\D"}, {"\\Q"});
118 setup_type("$dffsr", {"\\CLK", "\\SET", "\\CLR", "\\D"}, {"\\Q"});
119 setup_type("$adff", {"\\CLK", "\\ARST", "\\D"}, {"\\Q"});
120 setup_type("$dlatch", {"\\EN", "\\D"}, {"\\Q"});
121 setup_type("$dlatchsr", {"\\EN", "\\SET", "\\CLR", "\\D"}, {"\\Q"});
122
123 setup_type("$memrd", {"\\CLK", "\\ADDR"}, {"\\DATA"});
124 setup_type("$memwr", {"\\CLK", "\\EN", "\\ADDR", "\\DATA"}, {});
125 setup_type("$mem", {"\\RD_CLK", "\\RD_ADDR", "\\WR_CLK", "\\WR_EN", "\\WR_ADDR", "\\WR_DATA"}, {"\\RD_DATA"});
126
127 setup_type("$fsm", {"\\CLK", "\\ARST", "\\CTRL_IN"}, {"\\CTRL_OUT"});
128 }
129
130 void setup_stdcells()
131 {
132 setup_type("$_NOT_", {"\\A"}, {"\\Y"}, true);
133 setup_type("$_AND_", {"\\A", "\\B"}, {"\\Y"}, true);
134 setup_type("$_NAND_", {"\\A", "\\B"}, {"\\Y"}, true);
135 setup_type("$_OR_", {"\\A", "\\B"}, {"\\Y"}, true);
136 setup_type("$_NOR_", {"\\A", "\\B"}, {"\\Y"}, true);
137 setup_type("$_XOR_", {"\\A", "\\B"}, {"\\Y"}, true);
138 setup_type("$_XNOR_", {"\\A", "\\B"}, {"\\Y"}, true);
139 setup_type("$_MUX_", {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
140 setup_type("$_AOI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true);
141 setup_type("$_OAI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true);
142 setup_type("$_AOI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true);
143 setup_type("$_OAI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true);
144 }
145
146 void setup_stdcells_mem()
147 {
148 std::vector<char> list_np = {'N', 'P'}, list_01 = {'0', '1'};
149
150 for (auto c1 : list_np)
151 for (auto c2 : list_np)
152 setup_type(stringf("$_SR_%c%c_", c1, c2), {"\\S", "\\R"}, {"\\Q"});
153
154 for (auto c1 : list_np)
155 setup_type(stringf("$_DFF_%c_", c1), {"\\C", "\\D"}, {"\\Q"});
156
157 for (auto c1 : list_np)
158 for (auto c2 : list_np)
159 for (auto c3 : list_01)
160 setup_type(stringf("$_DFF_%c%c%c_", c1, c2, c3), {"\\C", "\\R", "\\D"}, {"\\Q"});
161
162 for (auto c1 : list_np)
163 for (auto c2 : list_np)
164 for (auto c3 : list_np)
165 setup_type(stringf("$_DFFSR_%c%c%c_", c1, c2, c3), {"\\C", "\\S", "\\R", "\\D"}, {"\\Q"});
166
167 for (auto c1 : list_np)
168 setup_type(stringf("$_DLATCH_%c_", c1), {"\\E", "\\D"}, {"\\Q"});
169
170 for (auto c1 : list_np)
171 for (auto c2 : list_np)
172 for (auto c3 : list_np)
173 setup_type(stringf("$_DLATCHSR_%c%c%c_", c1, c2, c3), {"\\E", "\\S", "\\R", "\\D"}, {"\\Q"});
174 }
175
176 void clear()
177 {
178 cell_types.clear();
179 }
180
181 bool cell_known(RTLIL::IdString type)
182 {
183 return cell_types.count(type) != 0;
184 }
185
186 bool cell_output(RTLIL::IdString type, RTLIL::IdString port)
187 {
188 auto it = cell_types.find(type);
189 return it != cell_types.end() && it->second.outputs.count(port) != 0;
190 }
191
192 bool cell_input(RTLIL::IdString type, RTLIL::IdString port)
193 {
194 auto it = cell_types.find(type);
195 return it != cell_types.end() && it->second.inputs.count(port) != 0;
196 }
197
198 bool cell_evaluable(RTLIL::IdString type)
199 {
200 auto it = cell_types.find(type);
201 return it != cell_types.end() && it->second.is_evaluable;
202 }
203
204 static RTLIL::Const eval_not(RTLIL::Const v)
205 {
206 for (auto &bit : v.bits)
207 if (bit == RTLIL::S0) bit = RTLIL::S1;
208 else if (bit == RTLIL::S1) bit = RTLIL::S0;
209 return v;
210 }
211
212 static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
213 {
214 if (type == "$sshr" && !signed1)
215 type = "$shr";
216 if (type == "$sshl" && !signed1)
217 type = "$shl";
218
219 if (type != "$sshr" && type != "$sshl" && type != "$shr" && type != "$shl" && type != "$shift" && type != "$shiftx" &&
220 type != "$pos" && type != "$neg" && type != "$not" && type != "$bu0") {
221 if (!signed1 || !signed2)
222 signed1 = false, signed2 = false;
223 }
224
225 #define HANDLE_CELL_TYPE(_t) if (type == "$" #_t) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
226 HANDLE_CELL_TYPE(not)
227 HANDLE_CELL_TYPE(and)
228 HANDLE_CELL_TYPE(or)
229 HANDLE_CELL_TYPE(xor)
230 HANDLE_CELL_TYPE(xnor)
231 HANDLE_CELL_TYPE(reduce_and)
232 HANDLE_CELL_TYPE(reduce_or)
233 HANDLE_CELL_TYPE(reduce_xor)
234 HANDLE_CELL_TYPE(reduce_xnor)
235 HANDLE_CELL_TYPE(reduce_bool)
236 HANDLE_CELL_TYPE(logic_not)
237 HANDLE_CELL_TYPE(logic_and)
238 HANDLE_CELL_TYPE(logic_or)
239 HANDLE_CELL_TYPE(shl)
240 HANDLE_CELL_TYPE(shr)
241 HANDLE_CELL_TYPE(sshl)
242 HANDLE_CELL_TYPE(sshr)
243 HANDLE_CELL_TYPE(shift)
244 HANDLE_CELL_TYPE(shiftx)
245 HANDLE_CELL_TYPE(lt)
246 HANDLE_CELL_TYPE(le)
247 HANDLE_CELL_TYPE(eq)
248 HANDLE_CELL_TYPE(ne)
249 HANDLE_CELL_TYPE(eqx)
250 HANDLE_CELL_TYPE(nex)
251 HANDLE_CELL_TYPE(ge)
252 HANDLE_CELL_TYPE(gt)
253 HANDLE_CELL_TYPE(add)
254 HANDLE_CELL_TYPE(sub)
255 HANDLE_CELL_TYPE(mul)
256 HANDLE_CELL_TYPE(div)
257 HANDLE_CELL_TYPE(mod)
258 HANDLE_CELL_TYPE(pow)
259 HANDLE_CELL_TYPE(pos)
260 HANDLE_CELL_TYPE(bu0)
261 HANDLE_CELL_TYPE(neg)
262 #undef HANDLE_CELL_TYPE
263
264 if (type == "$_NOT_")
265 return eval_not(arg1);
266 if (type == "$_AND_")
267 return const_and(arg1, arg2, false, false, 1);
268 if (type == "$_NAND_")
269 return eval_not(const_and(arg1, arg2, false, false, 1));
270 if (type == "$_OR_")
271 return const_or(arg1, arg2, false, false, 1);
272 if (type == "$_NOR_")
273 return eval_not(const_and(arg1, arg2, false, false, 1));
274 if (type == "$_XOR_")
275 return const_xor(arg1, arg2, false, false, 1);
276 if (type == "$_XNOR_")
277 return const_xnor(arg1, arg2, false, false, 1);
278
279 log_abort();
280 }
281
282 static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2)
283 {
284 if (cell->type == "$slice") {
285 RTLIL::Const ret;
286 int width = cell->parameters.at("\\Y_WIDTH").as_int();
287 int offset = cell->parameters.at("\\OFFSET").as_int();
288 ret.bits.insert(ret.bits.end(), arg1.bits.begin()+offset, arg1.bits.begin()+offset+width);
289 return ret;
290 }
291
292 if (cell->type == "$concat") {
293 RTLIL::Const ret = arg1;
294 ret.bits.insert(ret.bits.end(), arg2.bits.begin(), arg2.bits.end());
295 return ret;
296 }
297
298 bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
299 bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
300 int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1;
301 return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len);
302 }
303
304 static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3)
305 {
306 if (cell->type.in("$mux", "$pmux", "$_MUX_")) {
307 RTLIL::Const ret = arg1;
308 for (size_t i = 0; i < arg3.bits.size(); i++)
309 if (arg3.bits[i] == RTLIL::State::S1) {
310 std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size());
311 ret = RTLIL::Const(bits);
312 }
313 return ret;
314 }
315
316 if (cell->type == "$_AOI3_")
317 return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1));
318 if (cell->type == "$_OAI3_")
319 return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1));
320
321 log_assert(arg3.bits.size() == 0);
322 return eval(cell, arg1, arg2);
323 }
324
325 static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4)
326 {
327 if (cell->type == "$_AOI4_")
328 return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
329 if (cell->type == "$_OAI4_")
330 return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
331
332 log_assert(arg4.bits.size() == 0);
333 return eval(cell, arg1, arg2, arg3);
334 }
335 };
336
337 #endif
338