2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
23 #include "kernel/yosys.h"
30 pool
<RTLIL::IdString
> inputs
, outputs
;
36 dict
<RTLIL::IdString
, CellType
> cell_types
;
42 CellTypes(RTLIL::Design
*design
)
47 void setup(RTLIL::Design
*design
= NULL
)
53 setup_internals_mem();
58 void setup_type(RTLIL::IdString type
, const pool
<RTLIL::IdString
> &inputs
, const pool
<RTLIL::IdString
> &outputs
, bool is_evaluable
= false)
60 CellType ct
= {type
, inputs
, outputs
, is_evaluable
};
61 cell_types
[ct
.type
] = ct
;
64 void setup_module(RTLIL::Module
*module
)
66 pool
<RTLIL::IdString
> inputs
, outputs
;
67 for (RTLIL::IdString wire_name
: module
->ports
) {
68 RTLIL::Wire
*wire
= module
->wire(wire_name
);
70 inputs
.insert(wire
->name
);
71 if (wire
->port_output
)
72 outputs
.insert(wire
->name
);
74 setup_type(module
->name
, inputs
, outputs
);
77 void setup_design(RTLIL::Design
*design
)
79 for (auto module
: design
->modules())
83 void setup_internals()
85 setup_internals_eval();
87 IdString A
= "\\A", B
= "\\B", EN
= "\\EN", Y
= "\\Y";
88 IdString SRC
= "\\SRC", DST
= "\\DST", DAT
= "\\DAT";
89 IdString EN_SRC
= "\\EN_SRC", EN_DST
= "\\EN_DST";
91 setup_type("$tribuf", {A
, EN
}, {Y
}, true);
93 setup_type("$assert", {A
, EN
}, pool
<RTLIL::IdString
>(), true);
94 setup_type("$assume", {A
, EN
}, pool
<RTLIL::IdString
>(), true);
95 setup_type("$live", {A
, EN
}, pool
<RTLIL::IdString
>(), true);
96 setup_type("$fair", {A
, EN
}, pool
<RTLIL::IdString
>(), true);
97 setup_type("$cover", {A
, EN
}, pool
<RTLIL::IdString
>(), true);
98 setup_type("$initstate", pool
<RTLIL::IdString
>(), {Y
}, true);
99 setup_type("$anyconst", pool
<RTLIL::IdString
>(), {Y
}, true);
100 setup_type("$anyseq", pool
<RTLIL::IdString
>(), {Y
}, true);
101 setup_type("$allconst", pool
<RTLIL::IdString
>(), {Y
}, true);
102 setup_type("$allseq", pool
<RTLIL::IdString
>(), {Y
}, true);
103 setup_type("$equiv", {A
, B
}, {Y
}, true);
104 setup_type("$specify2", {EN
, SRC
, DST
}, pool
<RTLIL::IdString
>(), true);
105 setup_type("$specify3", {EN
, SRC
, DST
, DAT
}, pool
<RTLIL::IdString
>(), true);
106 setup_type("$specrule", {EN_SRC
, EN_DST
, SRC
, DST
}, pool
<RTLIL::IdString
>(), true);
109 void setup_internals_eval()
111 std::vector
<RTLIL::IdString
> unary_ops
= {
112 "$not", "$pos", "$neg",
113 "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
114 "$logic_not", "$slice", "$lut", "$sop"
117 std::vector
<RTLIL::IdString
> binary_ops
= {
118 "$and", "$or", "$xor", "$xnor",
119 "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
120 "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
121 "$add", "$sub", "$mul", "$div", "$mod", "$pow",
122 "$logic_and", "$logic_or", "$concat", "$macc"
124 IdString A
= "\\A", B
= "\\B", S
= "\\S", Y
= "\\Y";
125 IdString P
= "\\P", G
= "\\G", C
= "\\C", X
= "\\X";
126 IdString BI
= "\\BI", CI
= "\\CI", CO
= "\\CO", EN
= "\\EN";
128 for (auto type
: unary_ops
)
129 setup_type(type
, {A
}, {Y
}, true);
131 for (auto type
: binary_ops
)
132 setup_type(type
, {A
, B
}, {Y
}, true);
134 for (auto type
: std::vector
<RTLIL::IdString
>({"$mux", "$pmux"}))
135 setup_type(type
, {A
, B
, S
}, {Y
}, true);
137 setup_type("$lcu", {P
, G
, CI
}, {CO
}, true);
138 setup_type("$alu", {A
, B
, CI
, BI
}, {X
, Y
, CO
}, true);
139 setup_type("$fa", {A
, B
, C
}, {X
, Y
}, true);
142 void setup_internals_mem()
144 IdString SET
= "\\SET", CLR
= "\\CLR", CLK
= "\\CLK", ARST
= "\\ARST", EN
= "\\EN";
145 IdString Q
= "\\Q", D
= "\\D", ADDR
= "\\ADDR", DATA
= "\\DATA", RD_EN
= "\\RD_EN";
146 IdString RD_CLK
= "\\RD_CLK", RD_ADDR
= "\\RD_ADDR", WR_CLK
= "\\WR_CLK", WR_EN
= "\\WR_EN";
147 IdString WR_ADDR
= "\\WR_ADDR", WR_DATA
= "\\WR_DATA", RD_DATA
= "\\RD_DATA";
148 IdString CTRL_IN
= "\\CTRL_IN", CTRL_OUT
= "\\CTRL_OUT";
150 setup_type("$sr", {SET
, CLR
}, {Q
});
151 setup_type("$ff", {D
}, {Q
});
152 setup_type("$dff", {CLK
, D
}, {Q
});
153 setup_type("$dffe", {CLK
, EN
, D
}, {Q
});
154 setup_type("$dffsr", {CLK
, SET
, CLR
, D
}, {Q
});
155 setup_type("$adff", {CLK
, ARST
, D
}, {Q
});
156 setup_type("$dlatch", {EN
, D
}, {Q
});
157 setup_type("$dlatchsr", {EN
, SET
, CLR
, D
}, {Q
});
159 setup_type("$memrd", {CLK
, EN
, ADDR
}, {DATA
});
160 setup_type("$memwr", {CLK
, EN
, ADDR
, DATA
}, pool
<RTLIL::IdString
>());
161 setup_type("$meminit", {ADDR
, DATA
}, pool
<RTLIL::IdString
>());
162 setup_type("$mem", {RD_CLK
, RD_EN
, RD_ADDR
, WR_CLK
, WR_EN
, WR_ADDR
, WR_DATA
}, {RD_DATA
});
164 setup_type("$fsm", {CLK
, ARST
, CTRL_IN
}, {CTRL_OUT
});
167 void setup_stdcells()
169 setup_stdcells_eval();
171 IdString A
= "\\A", E
= "\\E", Y
= "\\Y";
173 setup_type("$_TBUF_", {A
, E
}, {Y
}, true);
176 void setup_stdcells_eval()
178 IdString A
= "\\A", B
= "\\B", C
= "\\C", D
= "\\D";
179 IdString E
= "\\E", F
= "\\F", G
= "\\G", H
= "\\H";
180 IdString I
= "\\I", J
= "\\J", K
= "\\K", L
= "\\L";
181 IdString M
= "\\M", N
= "\\N", O
= "\\O", P
= "\\P";
182 IdString S
= "\\S", T
= "\\T", U
= "\\U", V
= "\\V";
185 setup_type("$_BUF_", {A
}, {Y
}, true);
186 setup_type("$_NOT_", {A
}, {Y
}, true);
187 setup_type("$_AND_", {A
, B
}, {Y
}, true);
188 setup_type("$_NAND_", {A
, B
}, {Y
}, true);
189 setup_type("$_OR_", {A
, B
}, {Y
}, true);
190 setup_type("$_NOR_", {A
, B
}, {Y
}, true);
191 setup_type("$_XOR_", {A
, B
}, {Y
}, true);
192 setup_type("$_XNOR_", {A
, B
}, {Y
}, true);
193 setup_type("$_ANDNOT_", {A
, B
}, {Y
}, true);
194 setup_type("$_ORNOT_", {A
, B
}, {Y
}, true);
195 setup_type("$_MUX_", {A
, B
, S
}, {Y
}, true);
196 setup_type("$_NMUX_", {A
, B
, S
}, {Y
}, true);
197 setup_type("$_MUX4_", {A
, B
, C
, D
, S
, T
}, {Y
}, true);
198 setup_type("$_MUX8_", {A
, B
, C
, D
, E
, F
, G
, H
, S
, T
, U
}, {Y
}, true);
199 setup_type("$_MUX16_", {A
, B
, C
, D
, E
, F
, G
, H
, I
, J
, K
, L
, M
, N
, O
, P
, S
, T
, U
, V
}, {Y
}, true);
200 setup_type("$_AOI3_", {A
, B
, C
}, {Y
}, true);
201 setup_type("$_OAI3_", {A
, B
, C
}, {Y
}, true);
202 setup_type("$_AOI4_", {A
, B
, C
, D
}, {Y
}, true);
203 setup_type("$_OAI4_", {A
, B
, C
, D
}, {Y
}, true);
206 void setup_stdcells_mem()
208 IdString S
= "\\S", R
= "\\R", C
= "\\C";
209 IdString D
= "\\D", Q
= "\\Q", E
= "\\E";
211 std::vector
<char> list_np
= {'N', 'P'}, list_01
= {'0', '1'};
213 for (auto c1
: list_np
)
214 for (auto c2
: list_np
)
215 setup_type(stringf("$_SR_%c%c_", c1
, c2
), {S
, R
}, {Q
});
217 setup_type("$_FF_", {D
}, {Q
});
219 for (auto c1
: list_np
)
220 setup_type(stringf("$_DFF_%c_", c1
), {C
, D
}, {Q
});
222 for (auto c1
: list_np
)
223 for (auto c2
: list_np
)
224 setup_type(stringf("$_DFFE_%c%c_", c1
, c2
), {C
, D
, E
}, {Q
});
226 for (auto c1
: list_np
)
227 for (auto c2
: list_np
)
228 for (auto c3
: list_01
)
229 setup_type(stringf("$_DFF_%c%c%c_", c1
, c2
, c3
), {C
, R
, D
}, {Q
});
231 for (auto c1
: list_np
)
232 for (auto c2
: list_np
)
233 for (auto c3
: list_np
)
234 setup_type(stringf("$_DFFSR_%c%c%c_", c1
, c2
, c3
), {C
, S
, R
, D
}, {Q
});
236 for (auto c1
: list_np
)
237 setup_type(stringf("$_DLATCH_%c_", c1
), {E
, D
}, {Q
});
239 for (auto c1
: list_np
)
240 for (auto c2
: list_np
)
241 for (auto c3
: list_np
)
242 setup_type(stringf("$_DLATCHSR_%c%c%c_", c1
, c2
, c3
), {E
, S
, R
, D
}, {Q
});
250 bool cell_known(RTLIL::IdString type
) const
252 return cell_types
.count(type
) != 0;
255 bool cell_output(RTLIL::IdString type
, RTLIL::IdString port
) const
257 auto it
= cell_types
.find(type
);
258 return it
!= cell_types
.end() && it
->second
.outputs
.count(port
) != 0;
261 bool cell_input(RTLIL::IdString type
, RTLIL::IdString port
) const
263 auto it
= cell_types
.find(type
);
264 return it
!= cell_types
.end() && it
->second
.inputs
.count(port
) != 0;
267 bool cell_evaluable(RTLIL::IdString type
) const
269 auto it
= cell_types
.find(type
);
270 return it
!= cell_types
.end() && it
->second
.is_evaluable
;
273 static RTLIL::Const
eval_not(RTLIL::Const v
)
275 for (auto &bit
: v
.bits
)
276 if (bit
== RTLIL::S0
) bit
= RTLIL::S1
;
277 else if (bit
== RTLIL::S1
) bit
= RTLIL::S0
;
281 static RTLIL::Const
eval(RTLIL::IdString type
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, bool signed1
, bool signed2
, int result_len
, bool *errp
= nullptr)
283 if (type
== "$sshr" && !signed1
)
285 if (type
== "$sshl" && !signed1
)
288 if (type
!= "$sshr" && type
!= "$sshl" && type
!= "$shr" && type
!= "$shl" && type
!= "$shift" && type
!= "$shiftx" &&
289 type
!= "$pos" && type
!= "$neg" && type
!= "$not") {
290 if (!signed1
|| !signed2
)
291 signed1
= false, signed2
= false;
294 #define HANDLE_CELL_TYPE(_t) if (type == "$" #_t) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
295 HANDLE_CELL_TYPE(not)
296 HANDLE_CELL_TYPE(and)
298 HANDLE_CELL_TYPE(xor)
299 HANDLE_CELL_TYPE(xnor
)
300 HANDLE_CELL_TYPE(reduce_and
)
301 HANDLE_CELL_TYPE(reduce_or
)
302 HANDLE_CELL_TYPE(reduce_xor
)
303 HANDLE_CELL_TYPE(reduce_xnor
)
304 HANDLE_CELL_TYPE(reduce_bool
)
305 HANDLE_CELL_TYPE(logic_not
)
306 HANDLE_CELL_TYPE(logic_and
)
307 HANDLE_CELL_TYPE(logic_or
)
308 HANDLE_CELL_TYPE(shl
)
309 HANDLE_CELL_TYPE(shr
)
310 HANDLE_CELL_TYPE(sshl
)
311 HANDLE_CELL_TYPE(sshr
)
312 HANDLE_CELL_TYPE(shift
)
313 HANDLE_CELL_TYPE(shiftx
)
318 HANDLE_CELL_TYPE(eqx
)
319 HANDLE_CELL_TYPE(nex
)
322 HANDLE_CELL_TYPE(add
)
323 HANDLE_CELL_TYPE(sub
)
324 HANDLE_CELL_TYPE(mul
)
325 HANDLE_CELL_TYPE(div
)
326 HANDLE_CELL_TYPE(mod
)
327 HANDLE_CELL_TYPE(pow
)
328 HANDLE_CELL_TYPE(pos
)
329 HANDLE_CELL_TYPE(neg
)
330 #undef HANDLE_CELL_TYPE
332 if (type
== "$_BUF_")
334 if (type
== "$_NOT_")
335 return eval_not(arg1
);
336 if (type
== "$_AND_")
337 return const_and(arg1
, arg2
, false, false, 1);
338 if (type
== "$_NAND_")
339 return eval_not(const_and(arg1
, arg2
, false, false, 1));
341 return const_or(arg1
, arg2
, false, false, 1);
342 if (type
== "$_NOR_")
343 return eval_not(const_or(arg1
, arg2
, false, false, 1));
344 if (type
== "$_XOR_")
345 return const_xor(arg1
, arg2
, false, false, 1);
346 if (type
== "$_XNOR_")
347 return const_xnor(arg1
, arg2
, false, false, 1);
348 if (type
== "$_ANDNOT_")
349 return const_and(arg1
, eval_not(arg2
), false, false, 1);
350 if (type
== "$_ORNOT_")
351 return const_or(arg1
, eval_not(arg2
), false, false, 1);
353 if (errp
!= nullptr) {
361 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, bool *errp
= nullptr)
363 if (cell
->type
== "$slice") {
365 int width
= cell
->parameters
.at("\\Y_WIDTH").as_int();
366 int offset
= cell
->parameters
.at("\\OFFSET").as_int();
367 ret
.bits
.insert(ret
.bits
.end(), arg1
.bits
.begin()+offset
, arg1
.bits
.begin()+offset
+width
);
371 if (cell
->type
== "$concat") {
372 RTLIL::Const ret
= arg1
;
373 ret
.bits
.insert(ret
.bits
.end(), arg2
.bits
.begin(), arg2
.bits
.end());
377 if (cell
->type
== "$lut")
379 int width
= cell
->parameters
.at("\\WIDTH").as_int();
381 std::vector
<RTLIL::State
> t
= cell
->parameters
.at("\\LUT").bits
;
382 while (GetSize(t
) < (1 << width
))
383 t
.push_back(RTLIL::S0
);
384 t
.resize(1 << width
);
386 for (int i
= width
-1; i
>= 0; i
--) {
387 RTLIL::State sel
= arg1
.bits
.at(i
);
388 std::vector
<RTLIL::State
> new_t
;
389 if (sel
== RTLIL::S0
)
390 new_t
= std::vector
<RTLIL::State
>(t
.begin(), t
.begin() + GetSize(t
)/2);
391 else if (sel
== RTLIL::S1
)
392 new_t
= std::vector
<RTLIL::State
>(t
.begin() + GetSize(t
)/2, t
.end());
394 for (int j
= 0; j
< GetSize(t
)/2; j
++)
395 new_t
.push_back(t
[j
] == t
[j
+ GetSize(t
)/2] ? t
[j
] : RTLIL::Sx
);
399 log_assert(GetSize(t
) == 1);
403 if (cell
->type
== "$sop")
405 int width
= cell
->parameters
.at("\\WIDTH").as_int();
406 int depth
= cell
->parameters
.at("\\DEPTH").as_int();
407 std::vector
<RTLIL::State
> t
= cell
->parameters
.at("\\TABLE").bits
;
409 while (GetSize(t
) < width
*depth
*2)
410 t
.push_back(RTLIL::S0
);
412 RTLIL::State default_ret
= State::S0
;
414 for (int i
= 0; i
< depth
; i
++)
419 for (int j
= 0; j
< width
; j
++) {
420 RTLIL::State a
= arg1
.bits
.at(j
);
421 if (t
.at(2*width
*i
+ 2*j
+ 0) == State::S1
) {
422 if (a
== State::S1
) match_x
= false;
423 if (a
!= State::S0
) match
= false;
425 if (t
.at(2*width
*i
+ 2*j
+ 1) == State::S1
) {
426 if (a
== State::S0
) match_x
= false;
427 if (a
!= State::S1
) match
= false;
435 default_ret
= State::Sx
;
441 bool signed_a
= cell
->parameters
.count("\\A_SIGNED") > 0 && cell
->parameters
["\\A_SIGNED"].as_bool();
442 bool signed_b
= cell
->parameters
.count("\\B_SIGNED") > 0 && cell
->parameters
["\\B_SIGNED"].as_bool();
443 int result_len
= cell
->parameters
.count("\\Y_WIDTH") > 0 ? cell
->parameters
["\\Y_WIDTH"].as_int() : -1;
444 return eval(cell
->type
, arg1
, arg2
, signed_a
, signed_b
, result_len
, errp
);
447 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, const RTLIL::Const
&arg3
, bool *errp
= nullptr)
449 if (cell
->type
.in("$mux", "$pmux", "$_MUX_")) {
450 RTLIL::Const ret
= arg1
;
451 for (size_t i
= 0; i
< arg3
.bits
.size(); i
++)
452 if (arg3
.bits
[i
] == RTLIL::State::S1
) {
453 std::vector
<RTLIL::State
> bits(arg2
.bits
.begin() + i
*arg1
.bits
.size(), arg2
.bits
.begin() + (i
+1)*arg1
.bits
.size());
454 ret
= RTLIL::Const(bits
);
459 if (cell
->type
== "$_AOI3_")
460 return eval_not(const_or(const_and(arg1
, arg2
, false, false, 1), arg3
, false, false, 1));
461 if (cell
->type
== "$_OAI3_")
462 return eval_not(const_and(const_or(arg1
, arg2
, false, false, 1), arg3
, false, false, 1));
464 log_assert(arg3
.bits
.size() == 0);
465 return eval(cell
, arg1
, arg2
, errp
);
468 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, const RTLIL::Const
&arg3
, const RTLIL::Const
&arg4
, bool *errp
= nullptr)
470 if (cell
->type
== "$_AOI4_")
471 return eval_not(const_or(const_and(arg1
, arg2
, false, false, 1), const_and(arg3
, arg4
, false, false, 1), false, false, 1));
472 if (cell
->type
== "$_OAI4_")
473 return eval_not(const_and(const_or(arg1
, arg2
, false, false, 1), const_or(arg3
, arg4
, false, false, 1), false, false, 1));
475 log_assert(arg4
.bits
.size() == 0);
476 return eval(cell
, arg1
, arg2
, arg3
, errp
);
480 // initialized by yosys_setup()
481 extern CellTypes yosys_celltypes
;