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.
20 #include "kernel/celledges.h"
23 PRIVATE_NAMESPACE_BEGIN
25 void bitwise_unary_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
27 IdString A
= "\\A", Y
= "\\Y";
29 bool is_signed
= cell
->getParam("\\A_SIGNED").as_bool();
30 int a_width
= GetSize(cell
->getPort(A
));
31 int y_width
= GetSize(cell
->getPort(Y
));
33 for (int i
= 0; i
< y_width
; i
++)
36 db
->add_edge(cell
, A
, i
, Y
, i
, -1);
37 else if (is_signed
&& a_width
> 0)
38 db
->add_edge(cell
, A
, a_width
-1, Y
, i
, -1);
42 void bitwise_binary_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
44 IdString A
= "\\A", B
= "\\B", Y
= "\\Y";
46 bool is_signed
= cell
->getParam("\\A_SIGNED").as_bool();
47 int a_width
= GetSize(cell
->getPort(A
));
48 int b_width
= GetSize(cell
->getPort(B
));
49 int y_width
= GetSize(cell
->getPort(Y
));
51 if (cell
->type
== "$and" && !is_signed
) {
52 if (a_width
> b_width
)
58 for (int i
= 0; i
< y_width
; i
++)
61 db
->add_edge(cell
, A
, i
, Y
, i
, -1);
62 else if (is_signed
&& a_width
> 0)
63 db
->add_edge(cell
, A
, a_width
-1, Y
, i
, -1);
66 db
->add_edge(cell
, B
, i
, Y
, i
, -1);
67 else if (is_signed
&& b_width
> 0)
68 db
->add_edge(cell
, B
, b_width
-1, Y
, i
, -1);
72 void arith_neg_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
74 IdString A
= "\\A", Y
= "\\Y";
76 bool is_signed
= cell
->getParam("\\A_SIGNED").as_bool();
77 int a_width
= GetSize(cell
->getPort(A
));
78 int y_width
= GetSize(cell
->getPort(Y
));
80 if (is_signed
&& a_width
== 1)
81 y_width
= std::min(y_width
, 1);
83 for (int i
= 0; i
< y_width
; i
++)
84 for (int k
= 0; k
<= i
&& k
< a_width
; k
++)
85 db
->add_edge(cell
, A
, k
, Y
, i
, -1);
88 void arith_binary_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
90 IdString A
= "\\A", B
= "\\B", Y
= "\\Y";
92 bool is_signed
= cell
->getParam("\\A_SIGNED").as_bool();
93 int a_width
= GetSize(cell
->getPort(A
));
94 int b_width
= GetSize(cell
->getPort(B
));
95 int y_width
= GetSize(cell
->getPort(Y
));
97 if (!is_signed
&& cell
->type
!= "$sub") {
98 int ab_width
= std::max(a_width
, b_width
);
99 y_width
= std::min(y_width
, ab_width
+1);
102 for (int i
= 0; i
< y_width
; i
++)
104 for (int k
= 0; k
<= i
; k
++)
107 db
->add_edge(cell
, A
, k
, Y
, i
, -1);
110 db
->add_edge(cell
, B
, k
, Y
, i
, -1);
115 void reduce_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
117 IdString A
= "\\A", Y
= "\\Y";
119 int a_width
= GetSize(cell
->getPort(A
));
121 for (int i
= 0; i
< a_width
; i
++)
122 db
->add_edge(cell
, A
, i
, Y
, 0, -1);
125 void compare_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
127 IdString A
= "\\A", B
= "\\B", Y
= "\\Y";
129 int a_width
= GetSize(cell
->getPort(A
));
130 int b_width
= GetSize(cell
->getPort(B
));
132 for (int i
= 0; i
< a_width
; i
++)
133 db
->add_edge(cell
, A
, i
, Y
, 0, -1);
135 for (int i
= 0; i
< b_width
; i
++)
136 db
->add_edge(cell
, B
, i
, Y
, 0, -1);
139 void mux_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
141 IdString A
= "\\A", B
= "\\B", S
= "\\S", Y
= "\\Y";
143 int a_width
= GetSize(cell
->getPort(A
));
144 int b_width
= GetSize(cell
->getPort(B
));
145 int s_width
= GetSize(cell
->getPort(S
));
147 for (int i
= 0; i
< a_width
; i
++)
149 db
->add_edge(cell
, A
, i
, Y
, i
, -1);
151 for (int k
= i
; k
< b_width
; k
+= a_width
)
152 db
->add_edge(cell
, B
, k
, Y
, i
, -1);
154 for (int k
= 0; k
< s_width
; k
++)
155 db
->add_edge(cell
, S
, k
, Y
, i
, -1);
159 PRIVATE_NAMESPACE_END
161 bool YOSYS_NAMESPACE_PREFIX
AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell
*cell
)
163 if (cell
->type
.in("$not", "$pos")) {
164 bitwise_unary_op(this, cell
);
168 if (cell
->type
.in("$and", "$or", "$xor", "$xnor")) {
169 bitwise_binary_op(this, cell
);
173 if (cell
->type
== "$neg") {
174 arith_neg_op(this, cell
);
178 if (cell
->type
.in("$add", "$sub")) {
179 arith_binary_op(this, cell
);
183 if (cell
->type
.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", "$logic_not")) {
184 reduce_op(this, cell
);
189 // if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) {
190 // shift_op(this, cell);
194 if (cell
->type
.in("$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt")) {
195 compare_op(this, cell
);
199 if (cell
->type
.in("$mux", "$pmux")) {
204 // FIXME: $mul $div $mod $slice $concat
205 // FIXME: $lut $sop $alu $lcu $macc $fa