2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
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 bool is_signed
= cell
->getParam(ID::A_SIGNED
).as_bool();
28 int a_width
= GetSize(cell
->getPort(ID::A
));
29 int y_width
= GetSize(cell
->getPort(ID::Y
));
31 for (int i
= 0; i
< y_width
; i
++)
34 db
->add_edge(cell
, ID::A
, i
, ID::Y
, i
, -1);
35 else if (is_signed
&& a_width
> 0)
36 db
->add_edge(cell
, ID::A
, a_width
-1, ID::Y
, i
, -1);
40 void bitwise_binary_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
42 bool is_signed
= cell
->getParam(ID::A_SIGNED
).as_bool();
43 int a_width
= GetSize(cell
->getPort(ID::A
));
44 int b_width
= GetSize(cell
->getPort(ID::B
));
45 int y_width
= GetSize(cell
->getPort(ID::Y
));
47 if (cell
->type
== ID($
and) && !is_signed
) {
48 if (a_width
> b_width
)
54 for (int i
= 0; i
< y_width
; i
++)
57 db
->add_edge(cell
, ID::A
, i
, ID::Y
, i
, -1);
58 else if (is_signed
&& a_width
> 0)
59 db
->add_edge(cell
, ID::A
, a_width
-1, ID::Y
, i
, -1);
62 db
->add_edge(cell
, ID::B
, i
, ID::Y
, i
, -1);
63 else if (is_signed
&& b_width
> 0)
64 db
->add_edge(cell
, ID::B
, b_width
-1, ID::Y
, i
, -1);
68 void arith_neg_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
70 bool is_signed
= cell
->getParam(ID::A_SIGNED
).as_bool();
71 int a_width
= GetSize(cell
->getPort(ID::A
));
72 int y_width
= GetSize(cell
->getPort(ID::Y
));
74 if (is_signed
&& a_width
== 1)
75 y_width
= std::min(y_width
, 1);
77 for (int i
= 0; i
< y_width
; i
++)
78 for (int k
= 0; k
<= i
&& k
< a_width
; k
++)
79 db
->add_edge(cell
, ID::A
, k
, ID::Y
, i
, -1);
82 void arith_binary_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
84 bool is_signed
= cell
->getParam(ID::A_SIGNED
).as_bool();
85 int a_width
= GetSize(cell
->getPort(ID::A
));
86 int b_width
= GetSize(cell
->getPort(ID::B
));
87 int y_width
= GetSize(cell
->getPort(ID::Y
));
89 if (!is_signed
&& cell
->type
!= ID($sub
)) {
90 int ab_width
= std::max(a_width
, b_width
);
91 y_width
= std::min(y_width
, ab_width
+1);
94 for (int i
= 0; i
< y_width
; i
++)
96 for (int k
= 0; k
<= i
; k
++)
99 db
->add_edge(cell
, ID::A
, k
, ID::Y
, i
, -1);
102 db
->add_edge(cell
, ID::B
, k
, ID::Y
, i
, -1);
107 void reduce_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
109 int a_width
= GetSize(cell
->getPort(ID::A
));
111 for (int i
= 0; i
< a_width
; i
++)
112 db
->add_edge(cell
, ID::A
, i
, ID::Y
, 0, -1);
115 void compare_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
117 int a_width
= GetSize(cell
->getPort(ID::A
));
118 int b_width
= GetSize(cell
->getPort(ID::B
));
120 for (int i
= 0; i
< a_width
; i
++)
121 db
->add_edge(cell
, ID::A
, i
, ID::Y
, 0, -1);
123 for (int i
= 0; i
< b_width
; i
++)
124 db
->add_edge(cell
, ID::B
, i
, ID::Y
, 0, -1);
127 void mux_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
129 int a_width
= GetSize(cell
->getPort(ID::A
));
130 int b_width
= GetSize(cell
->getPort(ID::B
));
131 int s_width
= GetSize(cell
->getPort(ID::S
));
133 for (int i
= 0; i
< a_width
; i
++)
135 db
->add_edge(cell
, ID::A
, i
, ID::Y
, i
, -1);
137 for (int k
= i
; k
< b_width
; k
+= a_width
)
138 db
->add_edge(cell
, ID::B
, k
, ID::Y
, i
, -1);
140 for (int k
= 0; k
< s_width
; k
++)
141 db
->add_edge(cell
, ID::S
, k
, ID::Y
, i
, -1);
145 void bmux_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
147 int width
= GetSize(cell
->getPort(ID::Y
));
148 int a_width
= GetSize(cell
->getPort(ID::A
));
149 int s_width
= GetSize(cell
->getPort(ID::S
));
151 for (int i
= 0; i
< width
; i
++)
153 for (int k
= i
; k
< a_width
; k
+= width
)
154 db
->add_edge(cell
, ID::A
, k
, ID::Y
, i
, -1);
156 for (int k
= 0; k
< s_width
; k
++)
157 db
->add_edge(cell
, ID::S
, k
, ID::Y
, i
, -1);
161 void demux_op(AbstractCellEdgesDatabase
*db
, RTLIL::Cell
*cell
)
163 int width
= GetSize(cell
->getPort(ID::Y
));
164 int a_width
= GetSize(cell
->getPort(ID::A
));
165 int s_width
= GetSize(cell
->getPort(ID::S
));
167 for (int i
= 0; i
< width
; i
++)
169 db
->add_edge(cell
, ID::A
, i
% a_width
, ID::Y
, i
, -1);
170 for (int k
= 0; k
< s_width
; k
++)
171 db
->add_edge(cell
, ID::S
, k
, ID::Y
, i
, -1);
175 PRIVATE_NAMESPACE_END
177 bool YOSYS_NAMESPACE_PREFIX
AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell
*cell
)
179 if (cell
->type
.in(ID($
not), ID($pos
))) {
180 bitwise_unary_op(this, cell
);
184 if (cell
->type
.in(ID($
and), ID($
or), ID($
xor), ID($xnor
))) {
185 bitwise_binary_op(this, cell
);
189 if (cell
->type
== ID($neg
)) {
190 arith_neg_op(this, cell
);
194 if (cell
->type
.in(ID($add
), ID($sub
))) {
195 arith_binary_op(this, cell
);
199 if (cell
->type
.in(ID($reduce_and
), ID($reduce_or
), ID($reduce_xor
), ID($reduce_xnor
), ID($reduce_bool
), ID($logic_not
))) {
200 reduce_op(this, cell
);
205 // if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
206 // shift_op(this, cell);
210 if (cell
->type
.in(ID($lt
), ID($le
), ID($eq
), ID($ne
), ID($eqx
), ID($nex
), ID($ge
), ID($gt
))) {
211 compare_op(this, cell
);
215 if (cell
->type
.in(ID($mux
), ID($pmux
))) {
220 if (cell
->type
== ID($bmux
)) {
225 if (cell
->type
== ID($demux
)) {
226 demux_op(this, cell
);
230 // FIXME: $mul $div $mod $divfloor $modfloor $slice $concat
231 // FIXME: $lut $sop $alu $lcu $macc $fa