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
= ID::A
, Y
= ID::Y
;
29 bool is_signed
= cell
->getParam(ID(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
= ID::A
, B
= ID::B
, Y
= ID::Y
;
46 bool is_signed
= cell
->getParam(ID(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
== ID($
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
= ID::A
, Y
= ID::Y
;
76 bool is_signed
= cell
->getParam(ID(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
= ID::A
, B
= ID::B
, Y
= ID::Y
;
92 bool is_signed
= cell
->getParam(ID(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
!= ID($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
= ID::A
, Y
= ID::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
= ID::A
, B
= ID::B
, Y
= ID::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
= ID::A
, B
= ID::B
, S
= ID(S
), Y
= ID::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(ID($
not), ID($pos
))) {
164 bitwise_unary_op(this, cell
);
168 if (cell
->type
.in(ID($
and), ID($
or), ID($
xor), ID($xnor
))) {
169 bitwise_binary_op(this, cell
);
173 if (cell
->type
== ID($neg
)) {
174 arith_neg_op(this, cell
);
178 if (cell
->type
.in(ID($add
), ID($sub
))) {
179 arith_binary_op(this, cell
);
183 if (cell
->type
.in(ID($reduce_and
), ID($reduce_or
), ID($reduce_xor
), ID($reduce_xnor
), ID($reduce_bool
), ID($logic_not
))) {
184 reduce_op(this, cell
);
189 // if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
190 // shift_op(this, cell);
194 if (cell
->type
.in(ID($lt
), ID($le
), ID($eq
), ID($ne
), ID($eqx
), ID($nex
), ID($ge
), ID($gt
))) {
195 compare_op(this, cell
);
199 if (cell
->type
.in(ID($mux
), ID($pmux
))) {
204 // FIXME: $mul $div $mod $slice $concat
205 // FIXME: $lut $sop $alu $lcu $macc $fa