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 pool
<RTLIL::IdString
> inputs
, outputs
;
36 dict
<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 pool
<RTLIL::IdString
> &inputs
, const pool
<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 pool
<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 setup_internals_eval();
87 IdString A
= ID::A
, B
= ID::B
, EN
= ID(EN
), Y
= ID::Y
;
88 IdString SRC
= ID(SRC
), DST
= ID(DST
), DAT
= ID(DAT
);
89 IdString EN_SRC
= ID(EN_SRC
), EN_DST
= ID(EN_DST
);
91 setup_type(ID($tribuf
), {A
, EN
}, {Y
}, true);
93 setup_type(ID($
assert), {A
, EN
}, pool
<RTLIL::IdString
>(), true);
94 setup_type(ID($assume
), {A
, EN
}, pool
<RTLIL::IdString
>(), true);
95 setup_type(ID($live
), {A
, EN
}, pool
<RTLIL::IdString
>(), true);
96 setup_type(ID($fair
), {A
, EN
}, pool
<RTLIL::IdString
>(), true);
97 setup_type(ID($cover
), {A
, EN
}, pool
<RTLIL::IdString
>(), true);
98 setup_type(ID($initstate
), pool
<RTLIL::IdString
>(), {Y
}, true);
99 setup_type(ID($anyconst
), pool
<RTLIL::IdString
>(), {Y
}, true);
100 setup_type(ID($anyseq
), pool
<RTLIL::IdString
>(), {Y
}, true);
101 setup_type(ID($allconst
), pool
<RTLIL::IdString
>(), {Y
}, true);
102 setup_type(ID($allseq
), pool
<RTLIL::IdString
>(), {Y
}, true);
103 setup_type(ID($equiv
), {A
, B
}, {Y
}, true);
104 setup_type(ID($specify2
), {EN
, SRC
, DST
}, pool
<RTLIL::IdString
>(), true);
105 setup_type(ID($specify3
), {EN
, SRC
, DST
, DAT
}, pool
<RTLIL::IdString
>(), true);
106 setup_type(ID($specrule
), {EN_SRC
, EN_DST
, SRC
, DST
}, pool
<RTLIL::IdString
>(), true);
109 void setup_internals_eval()
111 std::vector
<RTLIL::IdString
> unary_ops
= {
112 ID($
not), ID($pos
), ID($neg
),
113 ID($reduce_and
), ID($reduce_or
), ID($reduce_xor
), ID($reduce_xnor
), ID($reduce_bool
),
114 ID($logic_not
), ID($slice
), ID($lut
), ID($sop
)
117 std::vector
<RTLIL::IdString
> binary_ops
= {
118 ID($
and), ID($
or), ID($
xor), ID($xnor
),
119 ID($shl
), ID($shr
), ID($sshl
), ID($sshr
), ID($shift
), ID($shiftx
),
120 ID($lt
), ID($le
), ID($eq
), ID($ne
), ID($eqx
), ID($nex
), ID($ge
), ID($gt
),
121 ID($add
), ID($sub
), ID($mul
), ID($div
), ID($mod
), ID($pow
),
122 ID($logic_and
), ID($logic_or
), ID($concat
), ID($macc
)
124 IdString A
= ID::A
, B
= ID::B
, S
= ID(S
), Y
= ID::Y
;
125 IdString P
= ID(P
), G
= ID(G
), C
= ID(C
), X
= ID(X
);
126 IdString BI
= ID(BI
), CI
= ID(CI
), CO
= ID(CO
), EN
= ID(EN
);
128 for (auto type
: unary_ops
)
129 setup_type(type
, {A
}, {Y
}, true);
131 for (auto type
: binary_ops
)
132 setup_type(type
, {A
, B
}, {Y
}, true);
134 for (auto type
: std::vector
<RTLIL::IdString
>({ID($mux
), ID($pmux
)}))
135 setup_type(type
, {A
, B
, S
}, {Y
}, true);
137 setup_type(ID($lcu
), {P
, G
, CI
}, {CO
}, true);
138 setup_type(ID($alu
), {A
, B
, CI
, BI
}, {X
, Y
, CO
}, true);
139 setup_type(ID($fa
), {A
, B
, C
}, {X
, Y
}, true);
142 void setup_internals_ff()
144 IdString SET
= ID(SET
), CLR
= ID(CLR
), CLK
= ID(CLK
), ARST
= ID(ARST
), EN
= ID(EN
);
145 IdString Q
= ID(Q
), D
= ID(D
);
147 setup_type(ID($sr
), {SET
, CLR
}, {Q
});
148 setup_type(ID($ff
), {D
}, {Q
});
149 setup_type(ID($dff
), {CLK
, D
}, {Q
});
150 setup_type(ID($dffe
), {CLK
, EN
, D
}, {Q
});
151 setup_type(ID($dffsr
), {CLK
, SET
, CLR
, D
}, {Q
});
152 setup_type(ID($adff
), {CLK
, ARST
, D
}, {Q
});
153 setup_type(ID($dlatch
), {EN
, D
}, {Q
});
154 setup_type(ID($dlatchsr
), {EN
, SET
, CLR
, D
}, {Q
});
158 void setup_internals_mem()
160 setup_internals_ff();
162 IdString CLK
= ID(CLK
), ARST
= ID(ARST
), EN
= ID(EN
);
163 IdString ADDR
= ID(ADDR
), DATA
= ID(DATA
), RD_EN
= ID(RD_EN
);
164 IdString RD_CLK
= ID(RD_CLK
), RD_ADDR
= ID(RD_ADDR
), WR_CLK
= ID(WR_CLK
), WR_EN
= ID(WR_EN
);
165 IdString WR_ADDR
= ID(WR_ADDR
), WR_DATA
= ID(WR_DATA
), RD_DATA
= ID(RD_DATA
);
166 IdString CTRL_IN
= ID(CTRL_IN
), CTRL_OUT
= ID(CTRL_OUT
);
168 setup_type(ID($memrd
), {CLK
, EN
, ADDR
}, {DATA
});
169 setup_type(ID($memwr
), {CLK
, EN
, ADDR
, DATA
}, pool
<RTLIL::IdString
>());
170 setup_type(ID($meminit
), {ADDR
, DATA
}, pool
<RTLIL::IdString
>());
171 setup_type(ID($mem
), {RD_CLK
, RD_EN
, RD_ADDR
, WR_CLK
, WR_EN
, WR_ADDR
, WR_DATA
}, {RD_DATA
});
173 setup_type(ID($fsm
), {CLK
, ARST
, CTRL_IN
}, {CTRL_OUT
});
176 void setup_stdcells()
178 setup_stdcells_eval();
180 IdString A
= ID::A
, E
= ID(E
), Y
= ID::Y
;
182 setup_type(ID($_TBUF_
), {A
, E
}, {Y
}, true);
185 void setup_stdcells_eval()
187 IdString A
= ID::A
, B
= ID::B
, C
= ID(C
), D
= ID(D
);
188 IdString E
= ID(E
), F
= ID(F
), G
= ID(G
), H
= ID(H
);
189 IdString I
= ID(I
), J
= ID(J
), K
= ID(K
), L
= ID(L
);
190 IdString M
= ID(M
), N
= ID(N
), O
= ID(O
), P
= ID(P
);
191 IdString S
= ID(S
), T
= ID(T
), U
= ID(U
), V
= ID(V
);
194 setup_type(ID($_BUF_
), {A
}, {Y
}, true);
195 setup_type(ID($_NOT_
), {A
}, {Y
}, true);
196 setup_type(ID($_AND_
), {A
, B
}, {Y
}, true);
197 setup_type(ID($_NAND_
), {A
, B
}, {Y
}, true);
198 setup_type(ID($_OR_
), {A
, B
}, {Y
}, true);
199 setup_type(ID($_NOR_
), {A
, B
}, {Y
}, true);
200 setup_type(ID($_XOR_
), {A
, B
}, {Y
}, true);
201 setup_type(ID($_XNOR_
), {A
, B
}, {Y
}, true);
202 setup_type(ID($_ANDNOT_
), {A
, B
}, {Y
}, true);
203 setup_type(ID($_ORNOT_
), {A
, B
}, {Y
}, true);
204 setup_type(ID($_MUX_
), {A
, B
, S
}, {Y
}, true);
205 setup_type(ID($_NMUX_
), {A
, B
, S
}, {Y
}, true);
206 setup_type(ID($_MUX4_
), {A
, B
, C
, D
, S
, T
}, {Y
}, true);
207 setup_type(ID($_MUX8_
), {A
, B
, C
, D
, E
, F
, G
, H
, S
, T
, U
}, {Y
}, true);
208 setup_type(ID($_MUX16_
), {A
, B
, C
, D
, E
, F
, G
, H
, I
, J
, K
, L
, M
, N
, O
, P
, S
, T
, U
, V
}, {Y
}, true);
209 setup_type(ID($_AOI3_
), {A
, B
, C
}, {Y
}, true);
210 setup_type(ID($_OAI3_
), {A
, B
, C
}, {Y
}, true);
211 setup_type(ID($_AOI4_
), {A
, B
, C
, D
}, {Y
}, true);
212 setup_type(ID($_OAI4_
), {A
, B
, C
, D
}, {Y
}, true);
215 void setup_stdcells_mem()
217 IdString S
= ID(S
), R
= ID(R
), C
= ID(C
);
218 IdString D
= ID(D
), Q
= ID(Q
), E
= ID(E
);
220 std::vector
<char> list_np
= {'N', 'P'}, list_01
= {'0', '1'};
222 for (auto c1
: list_np
)
223 for (auto c2
: list_np
)
224 setup_type(stringf("$_SR_%c%c_", c1
, c2
), {S
, R
}, {Q
});
226 setup_type(ID($_FF_
), {D
}, {Q
});
228 for (auto c1
: list_np
)
229 setup_type(stringf("$_DFF_%c_", c1
), {C
, D
}, {Q
});
231 for (auto c1
: list_np
)
232 for (auto c2
: list_np
)
233 setup_type(stringf("$_DFFE_%c%c_", c1
, c2
), {C
, D
, E
}, {Q
});
235 for (auto c1
: list_np
)
236 for (auto c2
: list_np
)
237 for (auto c3
: list_01
)
238 setup_type(stringf("$_DFF_%c%c%c_", c1
, c2
, c3
), {C
, R
, D
}, {Q
});
240 for (auto c1
: list_np
)
241 for (auto c2
: list_np
)
242 for (auto c3
: list_np
)
243 setup_type(stringf("$_DFFSR_%c%c%c_", c1
, c2
, c3
), {C
, S
, R
, D
}, {Q
});
245 for (auto c1
: list_np
)
246 setup_type(stringf("$_DLATCH_%c_", c1
), {E
, D
}, {Q
});
248 for (auto c1
: list_np
)
249 for (auto c2
: list_np
)
250 for (auto c3
: list_np
)
251 setup_type(stringf("$_DLATCHSR_%c%c%c_", c1
, c2
, c3
), {E
, S
, R
, D
}, {Q
});
259 bool cell_known(RTLIL::IdString type
) const
261 return cell_types
.count(type
) != 0;
264 bool cell_output(RTLIL::IdString type
, RTLIL::IdString port
) const
266 auto it
= cell_types
.find(type
);
267 return it
!= cell_types
.end() && it
->second
.outputs
.count(port
) != 0;
270 bool cell_input(RTLIL::IdString type
, RTLIL::IdString port
) const
272 auto it
= cell_types
.find(type
);
273 return it
!= cell_types
.end() && it
->second
.inputs
.count(port
) != 0;
276 bool cell_evaluable(RTLIL::IdString type
) const
278 auto it
= cell_types
.find(type
);
279 return it
!= cell_types
.end() && it
->second
.is_evaluable
;
282 static RTLIL::Const
eval_not(RTLIL::Const v
)
284 for (auto &bit
: v
.bits
)
285 if (bit
== State::S0
) bit
= State::S1
;
286 else if (bit
== State::S1
) bit
= State::S0
;
290 static RTLIL::Const
eval(RTLIL::IdString type
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, bool signed1
, bool signed2
, int result_len
, bool *errp
= nullptr)
292 if (type
== ID($sshr
) && !signed1
)
294 if (type
== ID($sshl
) && !signed1
)
297 if (type
!= ID($sshr
) && type
!= ID($sshl
) && type
!= ID($shr
) && type
!= ID($shl
) && type
!= ID($shift
) && type
!= ID($shiftx
) &&
298 type
!= ID($pos
) && type
!= ID($neg
) && type
!= ID($
not)) {
299 if (!signed1
|| !signed2
)
300 signed1
= false, signed2
= false;
303 #define HANDLE_CELL_TYPE(_t) if (type == "$" #_t) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
304 HANDLE_CELL_TYPE(not)
305 HANDLE_CELL_TYPE(and)
307 HANDLE_CELL_TYPE(xor)
308 HANDLE_CELL_TYPE(xnor
)
309 HANDLE_CELL_TYPE(reduce_and
)
310 HANDLE_CELL_TYPE(reduce_or
)
311 HANDLE_CELL_TYPE(reduce_xor
)
312 HANDLE_CELL_TYPE(reduce_xnor
)
313 HANDLE_CELL_TYPE(reduce_bool
)
314 HANDLE_CELL_TYPE(logic_not
)
315 HANDLE_CELL_TYPE(logic_and
)
316 HANDLE_CELL_TYPE(logic_or
)
317 HANDLE_CELL_TYPE(shl
)
318 HANDLE_CELL_TYPE(shr
)
319 HANDLE_CELL_TYPE(sshl
)
320 HANDLE_CELL_TYPE(sshr
)
321 HANDLE_CELL_TYPE(shift
)
322 HANDLE_CELL_TYPE(shiftx
)
327 HANDLE_CELL_TYPE(eqx
)
328 HANDLE_CELL_TYPE(nex
)
331 HANDLE_CELL_TYPE(add
)
332 HANDLE_CELL_TYPE(sub
)
333 HANDLE_CELL_TYPE(mul
)
334 HANDLE_CELL_TYPE(div
)
335 HANDLE_CELL_TYPE(mod
)
336 HANDLE_CELL_TYPE(pow
)
337 HANDLE_CELL_TYPE(pos
)
338 HANDLE_CELL_TYPE(neg
)
339 #undef HANDLE_CELL_TYPE
341 if (type
== ID($_BUF_
))
343 if (type
== ID($_NOT_
))
344 return eval_not(arg1
);
345 if (type
== ID($_AND_
))
346 return const_and(arg1
, arg2
, false, false, 1);
347 if (type
== ID($_NAND_
))
348 return eval_not(const_and(arg1
, arg2
, false, false, 1));
349 if (type
== ID($_OR_
))
350 return const_or(arg1
, arg2
, false, false, 1);
351 if (type
== ID($_NOR_
))
352 return eval_not(const_or(arg1
, arg2
, false, false, 1));
353 if (type
== ID($_XOR_
))
354 return const_xor(arg1
, arg2
, false, false, 1);
355 if (type
== ID($_XNOR_
))
356 return const_xnor(arg1
, arg2
, false, false, 1);
357 if (type
== ID($_ANDNOT_
))
358 return const_and(arg1
, eval_not(arg2
), false, false, 1);
359 if (type
== ID($_ORNOT_
))
360 return const_or(arg1
, eval_not(arg2
), false, false, 1);
362 if (errp
!= nullptr) {
370 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, bool *errp
= nullptr)
372 if (cell
->type
== ID($slice
)) {
374 int width
= cell
->parameters
.at(ID(Y_WIDTH
)).as_int();
375 int offset
= cell
->parameters
.at(ID(OFFSET
)).as_int();
376 ret
.bits
.insert(ret
.bits
.end(), arg1
.bits
.begin()+offset
, arg1
.bits
.begin()+offset
+width
);
380 if (cell
->type
== ID($concat
)) {
381 RTLIL::Const ret
= arg1
;
382 ret
.bits
.insert(ret
.bits
.end(), arg2
.bits
.begin(), arg2
.bits
.end());
386 if (cell
->type
== ID($lut
))
388 int width
= cell
->parameters
.at(ID(WIDTH
)).as_int();
390 std::vector
<RTLIL::State
> t
= cell
->parameters
.at(ID(LUT
)).bits
;
391 while (GetSize(t
) < (1 << width
))
392 t
.push_back(State::S0
);
393 t
.resize(1 << width
);
395 for (int i
= width
-1; i
>= 0; i
--) {
396 RTLIL::State sel
= arg1
.bits
.at(i
);
397 std::vector
<RTLIL::State
> new_t
;
398 if (sel
== State::S0
)
399 new_t
= std::vector
<RTLIL::State
>(t
.begin(), t
.begin() + GetSize(t
)/2);
400 else if (sel
== State::S1
)
401 new_t
= std::vector
<RTLIL::State
>(t
.begin() + GetSize(t
)/2, t
.end());
403 for (int j
= 0; j
< GetSize(t
)/2; j
++)
404 new_t
.push_back(t
[j
] == t
[j
+ GetSize(t
)/2] ? t
[j
] : RTLIL::Sx
);
408 log_assert(GetSize(t
) == 1);
412 if (cell
->type
== ID($sop
))
414 int width
= cell
->parameters
.at(ID(WIDTH
)).as_int();
415 int depth
= cell
->parameters
.at(ID(DEPTH
)).as_int();
416 std::vector
<RTLIL::State
> t
= cell
->parameters
.at(ID(TABLE
)).bits
;
418 while (GetSize(t
) < width
*depth
*2)
419 t
.push_back(State::S0
);
421 RTLIL::State default_ret
= State::S0
;
423 for (int i
= 0; i
< depth
; i
++)
428 for (int j
= 0; j
< width
; j
++) {
429 RTLIL::State a
= arg1
.bits
.at(j
);
430 if (t
.at(2*width
*i
+ 2*j
+ 0) == State::S1
) {
431 if (a
== State::S1
) match_x
= false;
432 if (a
!= State::S0
) match
= false;
434 if (t
.at(2*width
*i
+ 2*j
+ 1) == State::S1
) {
435 if (a
== State::S0
) match_x
= false;
436 if (a
!= State::S1
) match
= false;
444 default_ret
= State::Sx
;
450 bool signed_a
= cell
->parameters
.count(ID(A_SIGNED
)) > 0 && cell
->parameters
[ID(A_SIGNED
)].as_bool();
451 bool signed_b
= cell
->parameters
.count(ID(B_SIGNED
)) > 0 && cell
->parameters
[ID(B_SIGNED
)].as_bool();
452 int result_len
= cell
->parameters
.count(ID(Y_WIDTH
)) > 0 ? cell
->parameters
[ID(Y_WIDTH
)].as_int() : -1;
453 return eval(cell
->type
, arg1
, arg2
, signed_a
, signed_b
, result_len
, errp
);
456 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, const RTLIL::Const
&arg3
, bool *errp
= nullptr)
458 if (cell
->type
.in(ID($mux
), ID($pmux
), ID($_MUX_
))) {
459 RTLIL::Const ret
= arg1
;
460 for (size_t i
= 0; i
< arg3
.bits
.size(); i
++)
461 if (arg3
.bits
[i
] == RTLIL::State::S1
) {
462 std::vector
<RTLIL::State
> bits(arg2
.bits
.begin() + i
*arg1
.bits
.size(), arg2
.bits
.begin() + (i
+1)*arg1
.bits
.size());
463 ret
= RTLIL::Const(bits
);
468 if (cell
->type
== ID($_AOI3_
))
469 return eval_not(const_or(const_and(arg1
, arg2
, false, false, 1), arg3
, false, false, 1));
470 if (cell
->type
== ID($_OAI3_
))
471 return eval_not(const_and(const_or(arg1
, arg2
, false, false, 1), arg3
, false, false, 1));
473 log_assert(arg3
.bits
.size() == 0);
474 return eval(cell
, arg1
, arg2
, errp
);
477 static RTLIL::Const
eval(RTLIL::Cell
*cell
, const RTLIL::Const
&arg1
, const RTLIL::Const
&arg2
, const RTLIL::Const
&arg3
, const RTLIL::Const
&arg4
, bool *errp
= nullptr)
479 if (cell
->type
== ID($_AOI4_
))
480 return eval_not(const_or(const_and(arg1
, arg2
, false, false, 1), const_and(arg3
, arg4
, false, false, 1), false, false, 1));
481 if (cell
->type
== ID($_OAI4_
))
482 return eval_not(const_and(const_or(arg1
, arg2
, false, false, 1), const_or(arg3
, arg4
, false, false, 1), false, false, 1));
484 log_assert(arg4
.bits
.size() == 0);
485 return eval(cell
, arg1
, arg2
, arg3
, errp
);
489 // initialized by yosys_setup()
490 extern CellTypes yosys_celltypes
;