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");
97 void setup_internals_mem()
99 cell_types
.insert("$dff");
100 cell_types
.insert("$adff");
101 cell_types
.insert("$memrd");
102 cell_types
.insert("$memwr");
103 cell_types
.insert("$mem");
104 cell_types
.insert("$fsm");
105 cell_types
.insert("$sr");
108 void setup_stdcells()
110 cell_types
.insert("$_INV_");
111 cell_types
.insert("$_AND_");
112 cell_types
.insert("$_OR_");
113 cell_types
.insert("$_XOR_");
114 cell_types
.insert("$_MUX_");
117 void setup_stdcells_mem()
119 cell_types
.insert("$_DFF_N_");
120 cell_types
.insert("$_DFF_P_");
121 cell_types
.insert("$_DFF_NN0_");
122 cell_types
.insert("$_DFF_NN1_");
123 cell_types
.insert("$_DFF_NP0_");
124 cell_types
.insert("$_DFF_NP1_");
125 cell_types
.insert("$_DFF_PN0_");
126 cell_types
.insert("$_DFF_PN1_");
127 cell_types
.insert("$_DFF_PP0_");
128 cell_types
.insert("$_DFF_PP1_");
137 bool cell_known(std::string type
)
139 if (cell_types
.count(type
) > 0)
141 for (auto design
: designs
)
142 if (design
->modules
.count(type
) > 0)
147 bool cell_output(std::string type
, std::string port
)
149 if (cell_types
.count(type
) == 0) {
150 for (auto design
: designs
)
151 if (design
->modules
.count(type
) > 0) {
152 if (design
->modules
.at(type
)->wires
.count(port
))
153 return design
->modules
.at(type
)->wires
.at(port
)->port_output
;
159 if (port
== "\\Y" || port
== "\\Q" || port
== "\\RD_DATA")
161 if (type
== "$memrd" && port
== "\\DATA")
163 if (type
== "$fsm" && port
== "\\CTRL_OUT")
168 bool cell_input(std::string type
, std::string port
)
170 if (cell_types
.count(type
) == 0) {
171 for (auto design
: designs
)
172 if (design
->modules
.count(type
) > 0) {
173 if (design
->modules
.at(type
)->wires
.count(port
))
174 return design
->modules
.at(type
)->wires
.at(port
)->port_input
;
180 if (cell_types
.count(type
) > 0)
181 return !cell_output(type
, port
);
186 static RTLIL::Const
eval(std::string type
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, bool signed1
, bool signed2
, int result_len
)
188 if (type
== "$sshr" && !signed1
)
190 if (type
== "$sshl" && !signed1
)
193 if (!signed1
|| !signed2
)
194 signed1
= false, signed2
= false;
196 #define HANDLE_CELL_TYPE(_t) if (type == "$" #_t) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
197 HANDLE_CELL_TYPE(not)
198 HANDLE_CELL_TYPE(and)
200 HANDLE_CELL_TYPE(xor)
201 HANDLE_CELL_TYPE(xnor
)
202 HANDLE_CELL_TYPE(reduce_and
)
203 HANDLE_CELL_TYPE(reduce_or
)
204 HANDLE_CELL_TYPE(reduce_xor
)
205 HANDLE_CELL_TYPE(reduce_xnor
)
206 HANDLE_CELL_TYPE(reduce_bool
)
207 HANDLE_CELL_TYPE(logic_not
)
208 HANDLE_CELL_TYPE(logic_and
)
209 HANDLE_CELL_TYPE(logic_or
)
210 HANDLE_CELL_TYPE(shl
)
211 HANDLE_CELL_TYPE(shr
)
212 HANDLE_CELL_TYPE(sshl
)
213 HANDLE_CELL_TYPE(sshr
)
220 HANDLE_CELL_TYPE(add
)
221 HANDLE_CELL_TYPE(sub
)
222 HANDLE_CELL_TYPE(mul
)
223 HANDLE_CELL_TYPE(div
)
224 HANDLE_CELL_TYPE(mod
)
225 HANDLE_CELL_TYPE(pow
)
226 HANDLE_CELL_TYPE(pos
)
227 HANDLE_CELL_TYPE(neg
)
228 #undef HANDLE_CELL_TYPE
230 if (type
== "$_INV_")
231 return const_not(arg1
, arg2
, false, false, 1);
232 if (type
== "$_AND_")
233 return const_and(arg1
, arg2
, false, false, 1);
235 return const_or(arg1
, arg2
, false, false, 1);
236 if (type
== "$_XOR_")
237 return const_xor(arg1
, arg2
, false, false, 1);
242 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
)
244 bool signed_a
= cell
->parameters
.count("\\A_SIGNED") > 0 && cell
->parameters
["\\A_SIGNED"].as_bool();
245 bool signed_b
= cell
->parameters
.count("\\B_SIGNED") > 0 && cell
->parameters
["\\B_SIGNED"].as_bool();
246 int result_len
= cell
->parameters
.count("\\Y_WIDTH") > 0 ? cell
->parameters
["\\Y_WIDTH"].as_int() : -1;
247 return eval(cell
->type
, arg1
, arg2
, signed_a
, signed_b
, result_len
);
250 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, const RTLIL::Const
&sel
)
252 if (cell
->type
== "$mux" || cell
->type
== "$pmux" || cell
->type
== "$safe_pmux" || cell
->type
== "$_MUX_") {
253 RTLIL::Const ret
= arg1
;
254 for (size_t i
= 0; i
< sel
.bits
.size(); i
++)
255 if (sel
.bits
[i
] == RTLIL::State::S1
) {
256 std::vector
<RTLIL::State
> bits(arg2
.bits
.begin() + i
*arg1
.bits
.size(), arg2
.bits
.begin() + (i
+1)*arg1
.bits
.size());
257 ret
= RTLIL::Const(bits
);
262 assert(sel
.bits
.size() == 0);
263 bool signed_a
= cell
->parameters
.count("\\A_SIGNED") > 0 && cell
->parameters
["\\A_SIGNED"].as_bool();
264 bool signed_b
= cell
->parameters
.count("\\B_SIGNED") > 0 && cell
->parameters
["\\B_SIGNED"].as_bool();
265 int result_len
= cell
->parameters
.count("\\Y_WIDTH") > 0 ? cell
->parameters
["\\Y_WIDTH"].as_int() : -1;
266 return eval(cell
->type
, arg1
, arg2
, signed_a
, signed_b
, result_len
);