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 std::set
<RTLIL::IdString
> inputs
, outputs
;
36 std::map
<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 std::set
<RTLIL::IdString
> &inputs
, const std::set
<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 std::set
<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 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"
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"
99 for (auto type
: unary_ops
)
100 setup_type(type
, {"\\A"}, {"\\Y"}, true);
102 for (auto type
: binary_ops
)
103 setup_type(type
, {"\\A", "\\B"}, {"\\Y"}, true);
105 for (auto type
: std::vector
<RTLIL::IdString
>({"$mux", "$pmux"}))
106 setup_type(type
, {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
108 setup_type("$lcu", {"\\P", "\\G", "\\CI"}, {"\\CO"}, true);
109 setup_type("$alu", {"\\A", "\\B", "\\CI", "\\BI"}, {"\\X", "\\Y", "\\CO"}, true);
110 setup_type("$fa", {"\\A", "\\B", "\\C"}, {"\\X", "\\Y"}, true);
112 setup_type("$assert", {"\\A", "\\EN"}, std::set
<RTLIL::IdString
>(), true);
115 void setup_internals_mem()
117 setup_type("$sr", {"\\SET", "\\CLR"}, {"\\Q"});
118 setup_type("$dff", {"\\CLK", "\\D"}, {"\\Q"});
119 setup_type("$dffsr", {"\\CLK", "\\SET", "\\CLR", "\\D"}, {"\\Q"});
120 setup_type("$adff", {"\\CLK", "\\ARST", "\\D"}, {"\\Q"});
121 setup_type("$dlatch", {"\\EN", "\\D"}, {"\\Q"});
122 setup_type("$dlatchsr", {"\\EN", "\\SET", "\\CLR", "\\D"}, {"\\Q"});
124 setup_type("$memrd", {"\\CLK", "\\ADDR"}, {"\\DATA"});
125 setup_type("$memwr", {"\\CLK", "\\EN", "\\ADDR", "\\DATA"}, std::set
<RTLIL::IdString
>());
126 setup_type("$mem", {"\\RD_CLK", "\\RD_ADDR", "\\WR_CLK", "\\WR_EN", "\\WR_ADDR", "\\WR_DATA"}, {"\\RD_DATA"});
128 setup_type("$fsm", {"\\CLK", "\\ARST", "\\CTRL_IN"}, {"\\CTRL_OUT"});
131 void setup_stdcells()
133 setup_type("$_BUF_", {"\\A"}, {"\\Y"}, true);
134 setup_type("$_NOT_", {"\\A"}, {"\\Y"}, true);
135 setup_type("$_AND_", {"\\A", "\\B"}, {"\\Y"}, true);
136 setup_type("$_NAND_", {"\\A", "\\B"}, {"\\Y"}, true);
137 setup_type("$_OR_", {"\\A", "\\B"}, {"\\Y"}, true);
138 setup_type("$_NOR_", {"\\A", "\\B"}, {"\\Y"}, true);
139 setup_type("$_XOR_", {"\\A", "\\B"}, {"\\Y"}, true);
140 setup_type("$_XNOR_", {"\\A", "\\B"}, {"\\Y"}, true);
141 setup_type("$_MUX_", {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
142 setup_type("$_AOI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true);
143 setup_type("$_OAI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true);
144 setup_type("$_AOI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true);
145 setup_type("$_OAI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true);
148 void setup_stdcells_mem()
150 std::vector
<char> list_np
= {'N', 'P'}, list_01
= {'0', '1'};
152 for (auto c1
: list_np
)
153 for (auto c2
: list_np
)
154 setup_type(stringf("$_SR_%c%c_", c1
, c2
), {"\\S", "\\R"}, {"\\Q"});
156 for (auto c1
: list_np
)
157 setup_type(stringf("$_DFF_%c_", c1
), {"\\C", "\\D"}, {"\\Q"});
159 for (auto c1
: list_np
)
160 for (auto c2
: list_np
)
161 for (auto c3
: list_01
)
162 setup_type(stringf("$_DFF_%c%c%c_", c1
, c2
, c3
), {"\\C", "\\R", "\\D"}, {"\\Q"});
164 for (auto c1
: list_np
)
165 for (auto c2
: list_np
)
166 for (auto c3
: list_np
)
167 setup_type(stringf("$_DFFSR_%c%c%c_", c1
, c2
, c3
), {"\\C", "\\S", "\\R", "\\D"}, {"\\Q"});
169 for (auto c1
: list_np
)
170 setup_type(stringf("$_DLATCH_%c_", c1
), {"\\E", "\\D"}, {"\\Q"});
172 for (auto c1
: list_np
)
173 for (auto c2
: list_np
)
174 for (auto c3
: list_np
)
175 setup_type(stringf("$_DLATCHSR_%c%c%c_", c1
, c2
, c3
), {"\\E", "\\S", "\\R", "\\D"}, {"\\Q"});
183 bool cell_known(RTLIL::IdString type
)
185 return cell_types
.count(type
) != 0;
188 bool cell_output(RTLIL::IdString type
, RTLIL::IdString port
)
190 auto it
= cell_types
.find(type
);
191 return it
!= cell_types
.end() && it
->second
.outputs
.count(port
) != 0;
194 bool cell_input(RTLIL::IdString type
, RTLIL::IdString port
)
196 auto it
= cell_types
.find(type
);
197 return it
!= cell_types
.end() && it
->second
.inputs
.count(port
) != 0;
200 bool cell_evaluable(RTLIL::IdString type
)
202 auto it
= cell_types
.find(type
);
203 return it
!= cell_types
.end() && it
->second
.is_evaluable
;
206 static RTLIL::Const
eval_not(RTLIL::Const v
)
208 for (auto &bit
: v
.bits
)
209 if (bit
== RTLIL::S0
) bit
= RTLIL::S1
;
210 else if (bit
== RTLIL::S1
) bit
= RTLIL::S0
;
214 static RTLIL::Const
eval(RTLIL::IdString type
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, bool signed1
, bool signed2
, int result_len
)
216 if (type
== "$sshr" && !signed1
)
218 if (type
== "$sshl" && !signed1
)
221 if (type
!= "$sshr" && type
!= "$sshl" && type
!= "$shr" && type
!= "$shl" && type
!= "$shift" && type
!= "$shiftx" &&
222 type
!= "$pos" && type
!= "$neg" && type
!= "$not") {
223 if (!signed1
|| !signed2
)
224 signed1
= false, signed2
= false;
227 #define HANDLE_CELL_TYPE(_t) if (type == "$" #_t) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
228 HANDLE_CELL_TYPE(not)
229 HANDLE_CELL_TYPE(and)
231 HANDLE_CELL_TYPE(xor)
232 HANDLE_CELL_TYPE(xnor
)
233 HANDLE_CELL_TYPE(reduce_and
)
234 HANDLE_CELL_TYPE(reduce_or
)
235 HANDLE_CELL_TYPE(reduce_xor
)
236 HANDLE_CELL_TYPE(reduce_xnor
)
237 HANDLE_CELL_TYPE(reduce_bool
)
238 HANDLE_CELL_TYPE(logic_not
)
239 HANDLE_CELL_TYPE(logic_and
)
240 HANDLE_CELL_TYPE(logic_or
)
241 HANDLE_CELL_TYPE(shl
)
242 HANDLE_CELL_TYPE(shr
)
243 HANDLE_CELL_TYPE(sshl
)
244 HANDLE_CELL_TYPE(sshr
)
245 HANDLE_CELL_TYPE(shift
)
246 HANDLE_CELL_TYPE(shiftx
)
251 HANDLE_CELL_TYPE(eqx
)
252 HANDLE_CELL_TYPE(nex
)
255 HANDLE_CELL_TYPE(add
)
256 HANDLE_CELL_TYPE(sub
)
257 HANDLE_CELL_TYPE(mul
)
258 HANDLE_CELL_TYPE(div
)
259 HANDLE_CELL_TYPE(mod
)
260 HANDLE_CELL_TYPE(pow
)
261 HANDLE_CELL_TYPE(pos
)
262 HANDLE_CELL_TYPE(neg
)
263 #undef HANDLE_CELL_TYPE
265 if (type
== "$_BUF_")
267 if (type
== "$_NOT_")
268 return eval_not(arg1
);
269 if (type
== "$_AND_")
270 return const_and(arg1
, arg2
, false, false, 1);
271 if (type
== "$_NAND_")
272 return eval_not(const_and(arg1
, arg2
, false, false, 1));
274 return const_or(arg1
, arg2
, false, false, 1);
275 if (type
== "$_NOR_")
276 return eval_not(const_and(arg1
, arg2
, false, false, 1));
277 if (type
== "$_XOR_")
278 return const_xor(arg1
, arg2
, false, false, 1);
279 if (type
== "$_XNOR_")
280 return const_xnor(arg1
, arg2
, false, false, 1);
285 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
)
287 if (cell
->type
== "$slice") {
289 int width
= cell
->parameters
.at("\\Y_WIDTH").as_int();
290 int offset
= cell
->parameters
.at("\\OFFSET").as_int();
291 ret
.bits
.insert(ret
.bits
.end(), arg1
.bits
.begin()+offset
, arg1
.bits
.begin()+offset
+width
);
295 if (cell
->type
== "$concat") {
296 RTLIL::Const ret
= arg1
;
297 ret
.bits
.insert(ret
.bits
.end(), arg2
.bits
.begin(), arg2
.bits
.end());
301 if (cell
->type
== "$lut")
303 int width
= cell
->parameters
.at("\\WIDTH").as_int();
305 std::vector
<RTLIL::State
> t
= cell
->parameters
.at("\\LUT").bits
;
306 while (GetSize(t
) < (1 << width
))
307 t
.push_back(RTLIL::S0
);
308 t
.resize(1 << width
);
310 for (int i
= width
-1; i
>= 0; i
--) {
311 RTLIL::State sel
= arg1
.bits
.at(i
);
312 std::vector
<RTLIL::State
> new_t
;
313 if (sel
== RTLIL::S0
)
314 new_t
= std::vector
<RTLIL::State
>(t
.begin(), t
.begin() + GetSize(t
)/2);
315 else if (sel
== RTLIL::S1
)
316 new_t
= std::vector
<RTLIL::State
>(t
.begin() + GetSize(t
)/2, t
.end());
318 for (int j
= 0; j
< GetSize(t
)/2; j
++)
319 new_t
.push_back(t
[j
] == t
[j
+ GetSize(t
)/2] ? t
[j
] : RTLIL::Sx
);
323 log_assert(GetSize(t
) == 1);
327 bool signed_a
= cell
->parameters
.count("\\A_SIGNED") > 0 && cell
->parameters
["\\A_SIGNED"].as_bool();
328 bool signed_b
= cell
->parameters
.count("\\B_SIGNED") > 0 && cell
->parameters
["\\B_SIGNED"].as_bool();
329 int result_len
= cell
->parameters
.count("\\Y_WIDTH") > 0 ? cell
->parameters
["\\Y_WIDTH"].as_int() : -1;
330 return eval(cell
->type
, arg1
, arg2
, signed_a
, signed_b
, result_len
);
333 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, const RTLIL::Const
&arg3
)
335 if (cell
->type
.in("$mux", "$pmux", "$_MUX_")) {
336 RTLIL::Const ret
= arg1
;
337 for (size_t i
= 0; i
< arg3
.bits
.size(); i
++)
338 if (arg3
.bits
[i
] == RTLIL::State::S1
) {
339 std::vector
<RTLIL::State
> bits(arg2
.bits
.begin() + i
*arg1
.bits
.size(), arg2
.bits
.begin() + (i
+1)*arg1
.bits
.size());
340 ret
= RTLIL::Const(bits
);
345 if (cell
->type
== "$_AOI3_")
346 return eval_not(const_or(const_and(arg1
, arg2
, false, false, 1), arg3
, false, false, 1));
347 if (cell
->type
== "$_OAI3_")
348 return eval_not(const_and(const_or(arg1
, arg2
, false, false, 1), arg3
, false, false, 1));
350 log_assert(arg3
.bits
.size() == 0);
351 return eval(cell
, arg1
, arg2
);
354 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, const RTLIL::Const
&arg3
, const RTLIL::Const
&arg4
)
356 if (cell
->type
== "$_AOI4_")
357 return eval_not(const_or(const_and(arg1
, arg2
, false, false, 1), const_and(arg3
, arg4
, false, false, 1), false, false, 1));
358 if (cell
->type
== "$_OAI4_")
359 return eval_not(const_and(const_or(arg1
, arg2
, false, false, 1), const_and(arg3
, arg4
, false, false, 1), false, false, 1));
361 log_assert(arg4
.bits
.size() == 0);
362 return eval(cell
, arg1
, arg2
, arg3
);