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.
27 #include <kernel/rtlil.h>
28 #include <kernel/log.h>
33 std::set
<RTLIL::IdString
> inputs
, outputs
;
39 std::map
<RTLIL::IdString
, CellType
> cell_types
;
45 CellTypes(RTLIL::Design
*design
)
50 void setup(RTLIL::Design
*design
= NULL
)
56 setup_internals_mem();
61 void setup_type(RTLIL::IdString type
, const std::set
<RTLIL::IdString
> &inputs
, const std::set
<RTLIL::IdString
> &outputs
, bool is_evaluable
= false)
63 CellType ct
= {type
, inputs
, outputs
, is_evaluable
};
64 cell_types
[ct
.type
] = ct
;
67 void setup_module(RTLIL::Module
*module
)
69 std::set
<RTLIL::IdString
> inputs
, outputs
;
70 for (RTLIL::IdString wire_name
: module
->ports
) {
71 RTLIL::Wire
*wire
= module
->wire(wire_name
);
73 inputs
.insert(wire
->name
);
74 if (wire
->port_output
)
75 outputs
.insert(wire
->name
);
77 setup_type(module
->name
, inputs
, outputs
);
80 void setup_design(RTLIL::Design
*design
)
82 for (auto module
: design
->modules())
86 void setup_internals()
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"
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"
102 for (auto type
: unary_ops
)
103 setup_type(type
, {"\\A"}, {"\\Y"}, true);
105 for (auto type
: binary_ops
)
106 setup_type(type
, {"\\A", "\\B"}, {"\\Y"}, true);
108 for (auto type
: std::vector
<RTLIL::IdString
>({"$mux", "$pmux"}))
109 setup_type(type
, {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
111 setup_type("$assert", {"\\A", "\\EN"}, {}, true);
114 void setup_internals_mem()
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"});
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"});
127 setup_type("$fsm", {"\\CLK", "\\ARST", "\\CTRL_IN"}, {"\\CTRL_OUT"});
130 void setup_stdcells()
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);
146 void setup_stdcells_mem()
148 std::vector
<char> list_np
= {'N', 'P'}, list_01
= {'0', '1'};
150 for (auto c1
: list_np
)
151 for (auto c2
: list_np
)
152 setup_type(stringf("$_SR_%c%c_", c1
, c2
), {"\\S", "\\R"}, {"\\Q"});
154 for (auto c1
: list_np
)
155 setup_type(stringf("$_DFF_%c_", c1
), {"\\C", "\\D"}, {"\\Q"});
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"});
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"});
167 for (auto c1
: list_np
)
168 setup_type(stringf("$_DLATCH_%c_", c1
), {"\\E", "\\D"}, {"\\Q"});
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"});
181 bool cell_known(RTLIL::IdString type
)
183 return cell_types
.count(type
) != 0;
186 bool cell_output(RTLIL::IdString type
, RTLIL::IdString port
)
188 auto it
= cell_types
.find(type
);
189 return it
!= cell_types
.end() && it
->second
.outputs
.count(port
) != 0;
192 bool cell_input(RTLIL::IdString type
, RTLIL::IdString port
)
194 auto it
= cell_types
.find(type
);
195 return it
!= cell_types
.end() && it
->second
.inputs
.count(port
) != 0;
198 bool cell_evaluable(RTLIL::IdString type
)
200 auto it
= cell_types
.find(type
);
201 return it
!= cell_types
.end() && it
->second
.is_evaluable
;
204 static RTLIL::Const
eval_not(RTLIL::Const v
)
206 for (auto &bit
: v
.bits
)
207 if (bit
== RTLIL::S0
) bit
= RTLIL::S1
;
208 else if (bit
== RTLIL::S1
) bit
= RTLIL::S0
;
212 static RTLIL::Const
eval(RTLIL::IdString type
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, bool signed1
, bool signed2
, int result_len
)
214 if (type
== "$sshr" && !signed1
)
216 if (type
== "$sshl" && !signed1
)
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;
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)
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
)
249 HANDLE_CELL_TYPE(eqx
)
250 HANDLE_CELL_TYPE(nex
)
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
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));
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);
282 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
)
284 if (cell
->type
== "$slice") {
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
);
292 if (cell
->type
== "$concat") {
293 RTLIL::Const ret
= arg1
;
294 ret
.bits
.insert(ret
.bits
.end(), arg2
.bits
.begin(), arg2
.bits
.end());
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
);
304 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, const RTLIL::Const
&arg3
)
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
);
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));
321 log_assert(arg3
.bits
.size() == 0);
322 return eval(cell
, arg1
, arg2
);
325 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, const RTLIL::Const
&arg3
, const RTLIL::Const
&arg4
)
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));
332 log_assert(arg4
.bits
.size() == 0);
333 return eval(cell
, arg1
, arg2
, arg3
);