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>
32 std::set
<std::string
> cell_types
;
33 std::vector
<const RTLIL::Design
*> designs
;
39 CellTypes(const RTLIL::Design
*design
)
44 void setup(const RTLIL::Design
*design
= NULL
)
49 setup_internals_mem();
54 void setup_design(const RTLIL::Design
*design
)
56 designs
.push_back(design
);
59 void setup_internals()
61 cell_types
.insert("$not");
62 cell_types
.insert("$pos");
63 cell_types
.insert("$neg");
64 cell_types
.insert("$and");
65 cell_types
.insert("$or");
66 cell_types
.insert("$xor");
67 cell_types
.insert("$xnor");
68 cell_types
.insert("$reduce_and");
69 cell_types
.insert("$reduce_or");
70 cell_types
.insert("$reduce_xor");
71 cell_types
.insert("$reduce_xnor");
72 cell_types
.insert("$reduce_bool");
73 cell_types
.insert("$shl");
74 cell_types
.insert("$shr");
75 cell_types
.insert("$sshl");
76 cell_types
.insert("$sshr");
77 cell_types
.insert("$lt");
78 cell_types
.insert("$le");
79 cell_types
.insert("$eq");
80 cell_types
.insert("$ne");
81 cell_types
.insert("$ge");
82 cell_types
.insert("$gt");
83 cell_types
.insert("$add");
84 cell_types
.insert("$sub");
85 cell_types
.insert("$mul");
86 cell_types
.insert("$div");
87 cell_types
.insert("$mod");
88 cell_types
.insert("$pow");
89 cell_types
.insert("$logic_not");
90 cell_types
.insert("$logic_and");
91 cell_types
.insert("$logic_or");
92 cell_types
.insert("$mux");
93 cell_types
.insert("$pmux");
94 cell_types
.insert("$safe_pmux");
95 cell_types
.insert("$lut");
98 void setup_internals_mem()
100 cell_types
.insert("$dff");
101 cell_types
.insert("$adff");
102 cell_types
.insert("$memrd");
103 cell_types
.insert("$memwr");
104 cell_types
.insert("$mem");
105 cell_types
.insert("$fsm");
106 cell_types
.insert("$sr");
109 void setup_stdcells()
111 cell_types
.insert("$_INV_");
112 cell_types
.insert("$_AND_");
113 cell_types
.insert("$_OR_");
114 cell_types
.insert("$_XOR_");
115 cell_types
.insert("$_MUX_");
118 void setup_stdcells_mem()
120 cell_types
.insert("$_DFF_N_");
121 cell_types
.insert("$_DFF_P_");
122 cell_types
.insert("$_DFF_NN0_");
123 cell_types
.insert("$_DFF_NN1_");
124 cell_types
.insert("$_DFF_NP0_");
125 cell_types
.insert("$_DFF_NP1_");
126 cell_types
.insert("$_DFF_PN0_");
127 cell_types
.insert("$_DFF_PN1_");
128 cell_types
.insert("$_DFF_PP0_");
129 cell_types
.insert("$_DFF_PP1_");
138 bool cell_known(std::string type
)
140 if (cell_types
.count(type
) > 0)
142 for (auto design
: designs
)
143 if (design
->modules
.count(type
) > 0)
148 bool cell_output(std::string type
, std::string port
)
150 if (cell_types
.count(type
) == 0) {
151 for (auto design
: designs
)
152 if (design
->modules
.count(type
) > 0) {
153 if (design
->modules
.at(type
)->wires
.count(port
))
154 return design
->modules
.at(type
)->wires
.at(port
)->port_output
;
160 if (port
== "\\Y" || port
== "\\Q" || port
== "\\RD_DATA")
162 if (type
== "$memrd" && port
== "\\DATA")
164 if (type
== "$fsm" && port
== "\\CTRL_OUT")
166 if (type
== "$lut" && port
== "\\O")
171 bool cell_input(std::string type
, std::string port
)
173 if (cell_types
.count(type
) == 0) {
174 for (auto design
: designs
)
175 if (design
->modules
.count(type
) > 0) {
176 if (design
->modules
.at(type
)->wires
.count(port
))
177 return design
->modules
.at(type
)->wires
.at(port
)->port_input
;
183 if (cell_types
.count(type
) > 0)
184 return !cell_output(type
, port
);
189 static RTLIL::Const
eval(std::string type
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, bool signed1
, bool signed2
, int result_len
)
191 if (type
== "$sshr" && !signed1
)
193 if (type
== "$sshl" && !signed1
)
196 if (type
!= "$sshr" && type
!= "$sshl" && type
!= "$shr" && type
!= "$shl" &&
197 type
!= "$pos" && type
!= "$neg" && type
!= "$not") {
198 if (!signed1
|| !signed2
)
199 signed1
= false, signed2
= false;
202 #define HANDLE_CELL_TYPE(_t) if (type == "$" #_t) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
203 HANDLE_CELL_TYPE(not)
204 HANDLE_CELL_TYPE(and)
206 HANDLE_CELL_TYPE(xor)
207 HANDLE_CELL_TYPE(xnor
)
208 HANDLE_CELL_TYPE(reduce_and
)
209 HANDLE_CELL_TYPE(reduce_or
)
210 HANDLE_CELL_TYPE(reduce_xor
)
211 HANDLE_CELL_TYPE(reduce_xnor
)
212 HANDLE_CELL_TYPE(reduce_bool
)
213 HANDLE_CELL_TYPE(logic_not
)
214 HANDLE_CELL_TYPE(logic_and
)
215 HANDLE_CELL_TYPE(logic_or
)
216 HANDLE_CELL_TYPE(shl
)
217 HANDLE_CELL_TYPE(shr
)
218 HANDLE_CELL_TYPE(sshl
)
219 HANDLE_CELL_TYPE(sshr
)
226 HANDLE_CELL_TYPE(add
)
227 HANDLE_CELL_TYPE(sub
)
228 HANDLE_CELL_TYPE(mul
)
229 HANDLE_CELL_TYPE(div
)
230 HANDLE_CELL_TYPE(mod
)
231 HANDLE_CELL_TYPE(pow
)
232 HANDLE_CELL_TYPE(pos
)
233 HANDLE_CELL_TYPE(neg
)
234 #undef HANDLE_CELL_TYPE
236 if (type
== "$_INV_")
237 return const_not(arg1
, arg2
, false, false, 1);
238 if (type
== "$_AND_")
239 return const_and(arg1
, arg2
, false, false, 1);
241 return const_or(arg1
, arg2
, false, false, 1);
242 if (type
== "$_XOR_")
243 return const_xor(arg1
, arg2
, false, false, 1);
248 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
)
250 bool signed_a
= cell
->parameters
.count("\\A_SIGNED") > 0 && cell
->parameters
["\\A_SIGNED"].as_bool();
251 bool signed_b
= cell
->parameters
.count("\\B_SIGNED") > 0 && cell
->parameters
["\\B_SIGNED"].as_bool();
252 int result_len
= cell
->parameters
.count("\\Y_WIDTH") > 0 ? cell
->parameters
["\\Y_WIDTH"].as_int() : -1;
253 return eval(cell
->type
, arg1
, arg2
, signed_a
, signed_b
, result_len
);
256 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, const RTLIL::Const
&sel
)
258 if (cell
->type
== "$mux" || cell
->type
== "$pmux" || cell
->type
== "$safe_pmux" || cell
->type
== "$_MUX_") {
259 RTLIL::Const ret
= arg1
;
260 for (size_t i
= 0; i
< sel
.bits
.size(); i
++)
261 if (sel
.bits
[i
] == RTLIL::State::S1
) {
262 std::vector
<RTLIL::State
> bits(arg2
.bits
.begin() + i
*arg1
.bits
.size(), arg2
.bits
.begin() + (i
+1)*arg1
.bits
.size());
263 ret
= RTLIL::Const(bits
);
268 assert(sel
.bits
.size() == 0);
269 bool signed_a
= cell
->parameters
.count("\\A_SIGNED") > 0 && cell
->parameters
["\\A_SIGNED"].as_bool();
270 bool signed_b
= cell
->parameters
.count("\\B_SIGNED") > 0 && cell
->parameters
["\\B_SIGNED"].as_bool();
271 int result_len
= cell
->parameters
.count("\\Y_WIDTH") > 0 ? cell
->parameters
["\\Y_WIDTH"].as_int() : -1;
272 return eval(cell
->type
, arg1
, arg2
, signed_a
, signed_b
, result_len
);