Added library support to celltypes class and show pass
[yosys.git] / kernel / celltypes.h
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
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.
9 *
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.
17 *
18 */
19
20 #ifndef CELLTYPES_H
21 #define CELLTYPES_H
22
23 #include <set>
24 #include <string>
25 #include <stdlib.h>
26
27 struct CellTypes
28 {
29 std::set<std::string> cell_types;
30 std::vector<const RTLIL::Design*> designs;
31
32 void setup_internals()
33 {
34 cell_types.insert("$not");
35 cell_types.insert("$pos");
36 cell_types.insert("$neg");
37 cell_types.insert("$and");
38 cell_types.insert("$or");
39 cell_types.insert("$xor");
40 cell_types.insert("$xnor");
41 cell_types.insert("$reduce_and");
42 cell_types.insert("$reduce_or");
43 cell_types.insert("$reduce_xor");
44 cell_types.insert("$reduce_xnor");
45 cell_types.insert("$reduce_bool");
46 cell_types.insert("$shl");
47 cell_types.insert("$shr");
48 cell_types.insert("$sshl");
49 cell_types.insert("$sshr");
50 cell_types.insert("$lt");
51 cell_types.insert("$le");
52 cell_types.insert("$eq");
53 cell_types.insert("$ne");
54 cell_types.insert("$ge");
55 cell_types.insert("$gt");
56 cell_types.insert("$add");
57 cell_types.insert("$sub");
58 cell_types.insert("$mul");
59 cell_types.insert("$div");
60 cell_types.insert("$mod");
61 cell_types.insert("$pow");
62 cell_types.insert("$logic_not");
63 cell_types.insert("$logic_and");
64 cell_types.insert("$logic_or");
65 cell_types.insert("$mux");
66 cell_types.insert("$pmux");
67 cell_types.insert("$safe_pmux");
68 }
69
70 void setup_internals_mem()
71 {
72 cell_types.insert("$dff");
73 cell_types.insert("$adff");
74 cell_types.insert("$memrd");
75 cell_types.insert("$memwr");
76 cell_types.insert("$mem");
77 cell_types.insert("$fsm");
78 }
79
80 void setup_stdcells()
81 {
82 cell_types.insert("$_INV_");
83 cell_types.insert("$_AND_");
84 cell_types.insert("$_OR_");
85 cell_types.insert("$_XOR_");
86 cell_types.insert("$_MUX_");
87 }
88
89 void setup_stdcells_mem()
90 {
91 cell_types.insert("$_DFF_N_");
92 cell_types.insert("$_DFF_P_");
93 cell_types.insert("$_DFF_NN0_");
94 cell_types.insert("$_DFF_NN1_");
95 cell_types.insert("$_DFF_NP0_");
96 cell_types.insert("$_DFF_NP1_");
97 cell_types.insert("$_DFF_PN0_");
98 cell_types.insert("$_DFF_PN1_");
99 cell_types.insert("$_DFF_PP0_");
100 cell_types.insert("$_DFF_PP1_");
101 }
102
103 void setup_design(const RTLIL::Design *design)
104 {
105 designs.push_back(design);
106 }
107
108 void clear()
109 {
110 cell_types.clear();
111 designs.clear();
112 }
113
114 bool cell_known(std::string type)
115 {
116 if (cell_types.count(type) > 0)
117 return true;
118 for (auto design : designs)
119 if (design->modules.count(type) > 0)
120 return true;
121 return false;
122 }
123
124 bool cell_output(std::string type, std::string port)
125 {
126 if (cell_types.count(type) == 0) {
127 for (auto design : designs)
128 if (design->modules.count(type) > 0) {
129 if (design->modules.at(type)->wires.count(port))
130 return design->modules.at(type)->wires.at(port)->port_output;
131 return false;
132 }
133 return false;
134 }
135
136 if (port == "\\Y" || port == "\\Q" || port == "\\RD_DATA")
137 return true;
138 if (type == "$memrd" && port == "\\DATA")
139 return true;
140 if (type == "$fsm" && port == "\\CTRL_OUT")
141 return true;
142 return false;
143 }
144
145 bool cell_input(std::string type, std::string port)
146 {
147 if (cell_types.count(type) == 0) {
148 for (auto design : designs)
149 if (design->modules.count(type) > 0) {
150 if (design->modules.at(type)->wires.count(port))
151 return design->modules.at(type)->wires.at(port)->port_input;
152 return false;
153 }
154 return false;
155 }
156
157 if (cell_types.count(type) > 0)
158 return !cell_output(type, port);
159
160 return false;
161 }
162
163 static RTLIL::Const eval(std::string type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
164 {
165 #define HANDLE_CELL_TYPE(_t) if (type == "$" #_t) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
166 HANDLE_CELL_TYPE(not)
167 HANDLE_CELL_TYPE(and)
168 HANDLE_CELL_TYPE(or)
169 HANDLE_CELL_TYPE(xor)
170 HANDLE_CELL_TYPE(xnor)
171 HANDLE_CELL_TYPE(reduce_and)
172 HANDLE_CELL_TYPE(reduce_or)
173 HANDLE_CELL_TYPE(reduce_xor)
174 HANDLE_CELL_TYPE(reduce_xnor)
175 HANDLE_CELL_TYPE(reduce_bool)
176 HANDLE_CELL_TYPE(logic_not)
177 HANDLE_CELL_TYPE(logic_and)
178 HANDLE_CELL_TYPE(logic_or)
179 HANDLE_CELL_TYPE(shl)
180 HANDLE_CELL_TYPE(shr)
181 HANDLE_CELL_TYPE(sshl)
182 HANDLE_CELL_TYPE(sshr)
183 HANDLE_CELL_TYPE(lt)
184 HANDLE_CELL_TYPE(le)
185 HANDLE_CELL_TYPE(eq)
186 HANDLE_CELL_TYPE(ne)
187 HANDLE_CELL_TYPE(ge)
188 HANDLE_CELL_TYPE(gt)
189 HANDLE_CELL_TYPE(add)
190 HANDLE_CELL_TYPE(sub)
191 HANDLE_CELL_TYPE(mul)
192 HANDLE_CELL_TYPE(div)
193 HANDLE_CELL_TYPE(mod)
194 HANDLE_CELL_TYPE(pow)
195 HANDLE_CELL_TYPE(pos)
196 HANDLE_CELL_TYPE(neg)
197 #undef HANDLE_CELL_TYPE
198
199 if (type == "$_INV_")
200 return const_not(arg1, arg2, false, false, 1);
201 if (type == "$_AND_")
202 return const_and(arg1, arg2, false, false, 1);
203 if (type == "$_OR_")
204 return const_or(arg1, arg2, false, false, 1);
205 if (type == "$_XOR_")
206 return const_xor(arg1, arg2, false, false, 1);
207
208 assert(!"Called CellType.eval() with unsupported cell type!");
209 abort();
210 }
211
212 static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2)
213 {
214 bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
215 bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
216 int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1;
217 return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len);
218 }
219
220 static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &sel)
221 {
222 if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$safe_pmux" || cell->type == "$_MUX_") {
223 RTLIL::Const ret = arg1;
224 for (size_t i = 0; i < sel.bits.size(); i++)
225 if (sel.bits[i] == RTLIL::State::S1) {
226 std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size());
227 ret = RTLIL::Const(bits);
228 }
229 return ret;
230 }
231
232 assert(sel.bits.size() == 0);
233 bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
234 bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
235 int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1;
236 return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len);
237 }
238 };
239
240 #endif
241