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/register.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/log.h"
28 PRIVATE_NAMESPACE_BEGIN
30 static void simplemap_not(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
32 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
33 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
35 sig_a
.extend(GetSize(sig_y
), cell
->parameters
.at("\\A_SIGNED").as_bool());
37 for (int i
= 0; i
< GetSize(sig_y
); i
++) {
38 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_NOT_");
39 gate
->setPort("\\A", sig_a
[i
]);
40 gate
->setPort("\\Y", sig_y
[i
]);
44 static void simplemap_pos(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
46 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
47 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
49 sig_a
.extend_u0(GetSize(sig_y
), cell
->parameters
.at("\\A_SIGNED").as_bool());
51 module
->connect(RTLIL::SigSig(sig_y
, sig_a
));
54 static void simplemap_bitop(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
56 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
57 RTLIL::SigSpec sig_b
= cell
->getPort("\\B");
58 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
60 sig_a
.extend_u0(GetSize(sig_y
), cell
->parameters
.at("\\A_SIGNED").as_bool());
61 sig_b
.extend_u0(GetSize(sig_y
), cell
->parameters
.at("\\B_SIGNED").as_bool());
63 if (cell
->type
== "$xnor")
65 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, GetSize(sig_y
));
67 for (int i
= 0; i
< GetSize(sig_y
); i
++) {
68 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_NOT_");
69 gate
->setPort("\\A", sig_t
[i
]);
70 gate
->setPort("\\Y", sig_y
[i
]);
76 std::string gate_type
;
77 if (cell
->type
== "$and") gate_type
= "$_AND_";
78 if (cell
->type
== "$or") gate_type
= "$_OR_";
79 if (cell
->type
== "$xor") gate_type
= "$_XOR_";
80 if (cell
->type
== "$xnor") gate_type
= "$_XOR_";
81 log_assert(!gate_type
.empty());
83 for (int i
= 0; i
< GetSize(sig_y
); i
++) {
84 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
85 gate
->setPort("\\A", sig_a
[i
]);
86 gate
->setPort("\\B", sig_b
[i
]);
87 gate
->setPort("\\Y", sig_y
[i
]);
91 static void simplemap_reduce(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
93 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
94 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
96 if (sig_y
.size() == 0)
99 if (sig_a
.size() == 0) {
100 if (cell
->type
== "$reduce_and") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(1, sig_y
.size())));
101 if (cell
->type
== "$reduce_or") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.size())));
102 if (cell
->type
== "$reduce_xor") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.size())));
103 if (cell
->type
== "$reduce_xnor") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(1, sig_y
.size())));
104 if (cell
->type
== "$reduce_bool") module
->connect(RTLIL::SigSig(sig_y
, RTLIL::SigSpec(0, sig_y
.size())));
108 if (sig_y
.size() > 1) {
109 module
->connect(RTLIL::SigSig(sig_y
.extract(1, sig_y
.size()-1), RTLIL::SigSpec(0, sig_y
.size()-1)));
110 sig_y
= sig_y
.extract(0, 1);
113 std::string gate_type
;
114 if (cell
->type
== "$reduce_and") gate_type
= "$_AND_";
115 if (cell
->type
== "$reduce_or") gate_type
= "$_OR_";
116 if (cell
->type
== "$reduce_xor") gate_type
= "$_XOR_";
117 if (cell
->type
== "$reduce_xnor") gate_type
= "$_XOR_";
118 if (cell
->type
== "$reduce_bool") gate_type
= "$_OR_";
119 log_assert(!gate_type
.empty());
121 RTLIL::Cell
*last_output_cell
= NULL
;
123 while (sig_a
.size() > 1)
125 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, sig_a
.size() / 2);
127 for (int i
= 0; i
< sig_a
.size(); i
+= 2)
129 if (i
+1 == sig_a
.size()) {
130 sig_t
.append(sig_a
[i
]);
134 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
135 gate
->setPort("\\A", sig_a
[i
]);
136 gate
->setPort("\\B", sig_a
[i
+1]);
137 gate
->setPort("\\Y", sig_t
[i
/2]);
138 last_output_cell
= gate
;
144 if (cell
->type
== "$reduce_xnor") {
145 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
);
146 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_NOT_");
147 gate
->setPort("\\A", sig_a
);
148 gate
->setPort("\\Y", sig_t
);
149 last_output_cell
= gate
;
153 if (last_output_cell
== NULL
) {
154 module
->connect(RTLIL::SigSig(sig_y
, sig_a
));
156 last_output_cell
->setPort("\\Y", sig_y
);
160 static void logic_reduce(RTLIL::Module
*module
, RTLIL::SigSpec
&sig
)
162 while (sig
.size() > 1)
164 RTLIL::SigSpec sig_t
= module
->addWire(NEW_ID
, sig
.size() / 2);
166 for (int i
= 0; i
< sig
.size(); i
+= 2)
168 if (i
+1 == sig
.size()) {
169 sig_t
.append(sig
[i
]);
173 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_OR_");
174 gate
->setPort("\\A", sig
[i
]);
175 gate
->setPort("\\B", sig
[i
+1]);
176 gate
->setPort("\\Y", sig_t
[i
/2]);
183 sig
= RTLIL::SigSpec(0, 1);
186 static void simplemap_lognot(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
188 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
189 logic_reduce(module
, sig_a
);
191 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
193 if (sig_y
.size() == 0)
196 if (sig_y
.size() > 1) {
197 module
->connect(RTLIL::SigSig(sig_y
.extract(1, sig_y
.size()-1), RTLIL::SigSpec(0, sig_y
.size()-1)));
198 sig_y
= sig_y
.extract(0, 1);
201 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_NOT_");
202 gate
->setPort("\\A", sig_a
);
203 gate
->setPort("\\Y", sig_y
);
206 static void simplemap_logbin(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
208 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
209 logic_reduce(module
, sig_a
);
211 RTLIL::SigSpec sig_b
= cell
->getPort("\\B");
212 logic_reduce(module
, sig_b
);
214 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
216 if (sig_y
.size() == 0)
219 if (sig_y
.size() > 1) {
220 module
->connect(RTLIL::SigSig(sig_y
.extract(1, sig_y
.size()-1), RTLIL::SigSpec(0, sig_y
.size()-1)));
221 sig_y
= sig_y
.extract(0, 1);
224 std::string gate_type
;
225 if (cell
->type
== "$logic_and") gate_type
= "$_AND_";
226 if (cell
->type
== "$logic_or") gate_type
= "$_OR_";
227 log_assert(!gate_type
.empty());
229 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
230 gate
->setPort("\\A", sig_a
);
231 gate
->setPort("\\B", sig_b
);
232 gate
->setPort("\\Y", sig_y
);
235 static void simplemap_mux(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
237 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
238 RTLIL::SigSpec sig_b
= cell
->getPort("\\B");
239 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
241 for (int i
= 0; i
< GetSize(sig_y
); i
++) {
242 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, "$_MUX_");
243 gate
->setPort("\\A", sig_a
[i
]);
244 gate
->setPort("\\B", sig_b
[i
]);
245 gate
->setPort("\\S", cell
->getPort("\\S"));
246 gate
->setPort("\\Y", sig_y
[i
]);
250 static void simplemap_slice(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
252 int offset
= cell
->parameters
.at("\\OFFSET").as_int();
253 RTLIL::SigSpec sig_a
= cell
->getPort("\\A");
254 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
255 module
->connect(RTLIL::SigSig(sig_y
, sig_a
.extract(offset
, sig_y
.size())));
258 static void simplemap_concat(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
260 RTLIL::SigSpec sig_ab
= cell
->getPort("\\A");
261 sig_ab
.append(cell
->getPort("\\B"));
262 RTLIL::SigSpec sig_y
= cell
->getPort("\\Y");
263 module
->connect(RTLIL::SigSig(sig_y
, sig_ab
));
266 static void simplemap_sr(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
268 int width
= cell
->parameters
.at("\\WIDTH").as_int();
269 char set_pol
= cell
->parameters
.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
270 char clr_pol
= cell
->parameters
.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
272 RTLIL::SigSpec sig_s
= cell
->getPort("\\SET");
273 RTLIL::SigSpec sig_r
= cell
->getPort("\\CLR");
274 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
276 std::string gate_type
= stringf("$_SR_%c%c_", set_pol
, clr_pol
);
278 for (int i
= 0; i
< width
; i
++) {
279 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
280 gate
->setPort("\\S", sig_s
[i
]);
281 gate
->setPort("\\R", sig_r
[i
]);
282 gate
->setPort("\\Q", sig_q
[i
]);
286 static void simplemap_dff(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
288 int width
= cell
->parameters
.at("\\WIDTH").as_int();
289 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
291 RTLIL::SigSpec sig_clk
= cell
->getPort("\\CLK");
292 RTLIL::SigSpec sig_d
= cell
->getPort("\\D");
293 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
295 std::string gate_type
= stringf("$_DFF_%c_", clk_pol
);
297 for (int i
= 0; i
< width
; i
++) {
298 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
299 gate
->setPort("\\C", sig_clk
);
300 gate
->setPort("\\D", sig_d
[i
]);
301 gate
->setPort("\\Q", sig_q
[i
]);
305 static void simplemap_dffsr(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
307 int width
= cell
->parameters
.at("\\WIDTH").as_int();
308 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
309 char set_pol
= cell
->parameters
.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
310 char clr_pol
= cell
->parameters
.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
312 RTLIL::SigSpec sig_clk
= cell
->getPort("\\CLK");
313 RTLIL::SigSpec sig_s
= cell
->getPort("\\SET");
314 RTLIL::SigSpec sig_r
= cell
->getPort("\\CLR");
315 RTLIL::SigSpec sig_d
= cell
->getPort("\\D");
316 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
318 std::string gate_type
= stringf("$_DFFSR_%c%c%c_", clk_pol
, set_pol
, clr_pol
);
320 for (int i
= 0; i
< width
; i
++) {
321 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
322 gate
->setPort("\\C", sig_clk
);
323 gate
->setPort("\\S", sig_s
[i
]);
324 gate
->setPort("\\R", sig_r
[i
]);
325 gate
->setPort("\\D", sig_d
[i
]);
326 gate
->setPort("\\Q", sig_q
[i
]);
330 static void simplemap_adff(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
332 int width
= cell
->parameters
.at("\\WIDTH").as_int();
333 char clk_pol
= cell
->parameters
.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
334 char rst_pol
= cell
->parameters
.at("\\ARST_POLARITY").as_bool() ? 'P' : 'N';
336 std::vector
<RTLIL::State
> rst_val
= cell
->parameters
.at("\\ARST_VALUE").bits
;
337 while (int(rst_val
.size()) < width
)
338 rst_val
.push_back(RTLIL::State::S0
);
340 RTLIL::SigSpec sig_clk
= cell
->getPort("\\CLK");
341 RTLIL::SigSpec sig_rst
= cell
->getPort("\\ARST");
342 RTLIL::SigSpec sig_d
= cell
->getPort("\\D");
343 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
345 std::string gate_type_0
= stringf("$_DFF_%c%c0_", clk_pol
, rst_pol
);
346 std::string gate_type_1
= stringf("$_DFF_%c%c1_", clk_pol
, rst_pol
);
348 for (int i
= 0; i
< width
; i
++) {
349 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, rst_val
.at(i
) == RTLIL::State::S1
? gate_type_1
: gate_type_0
);
350 gate
->setPort("\\C", sig_clk
);
351 gate
->setPort("\\R", sig_rst
);
352 gate
->setPort("\\D", sig_d
[i
]);
353 gate
->setPort("\\Q", sig_q
[i
]);
357 static void simplemap_dlatch(RTLIL::Module
*module
, RTLIL::Cell
*cell
)
359 int width
= cell
->parameters
.at("\\WIDTH").as_int();
360 char en_pol
= cell
->parameters
.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
362 RTLIL::SigSpec sig_en
= cell
->getPort("\\EN");
363 RTLIL::SigSpec sig_d
= cell
->getPort("\\D");
364 RTLIL::SigSpec sig_q
= cell
->getPort("\\Q");
366 std::string gate_type
= stringf("$_DLATCH_%c_", en_pol
);
368 for (int i
= 0; i
< width
; i
++) {
369 RTLIL::Cell
*gate
= module
->addCell(NEW_ID
, gate_type
);
370 gate
->setPort("\\E", sig_en
);
371 gate
->setPort("\\D", sig_d
[i
]);
372 gate
->setPort("\\Q", sig_q
[i
]);
376 PRIVATE_NAMESPACE_END
377 YOSYS_NAMESPACE_BEGIN
379 extern void simplemap_get_mappers(std::map
<RTLIL::IdString
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> &mappers
);
381 void simplemap_get_mappers(std::map
<RTLIL::IdString
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> &mappers
)
383 mappers
["$not"] = simplemap_not
;
384 mappers
["$pos"] = simplemap_pos
;
385 mappers
["$and"] = simplemap_bitop
;
386 mappers
["$or"] = simplemap_bitop
;
387 mappers
["$xor"] = simplemap_bitop
;
388 mappers
["$xnor"] = simplemap_bitop
;
389 mappers
["$reduce_and"] = simplemap_reduce
;
390 mappers
["$reduce_or"] = simplemap_reduce
;
391 mappers
["$reduce_xor"] = simplemap_reduce
;
392 mappers
["$reduce_xnor"] = simplemap_reduce
;
393 mappers
["$reduce_bool"] = simplemap_reduce
;
394 mappers
["$logic_not"] = simplemap_lognot
;
395 mappers
["$logic_and"] = simplemap_logbin
;
396 mappers
["$logic_or"] = simplemap_logbin
;
397 mappers
["$mux"] = simplemap_mux
;
398 mappers
["$slice"] = simplemap_slice
;
399 mappers
["$concat"] = simplemap_concat
;
400 mappers
["$sr"] = simplemap_sr
;
401 mappers
["$dff"] = simplemap_dff
;
402 mappers
["$dffsr"] = simplemap_dffsr
;
403 mappers
["$adff"] = simplemap_adff
;
404 mappers
["$dlatch"] = simplemap_dlatch
;
408 PRIVATE_NAMESPACE_BEGIN
410 struct SimplemapPass
: public Pass
{
411 SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
414 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
416 log(" simplemap [selection]\n");
418 log("This pass maps a small selection of simple coarse-grain cells to yosys gate\n");
419 log("primitives. The following internal cell types are mapped by this pass:\n");
421 log(" $not, $pos, $and, $or, $xor, $xnor\n");
422 log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
423 log(" $logic_not, $logic_and, $logic_or, $mux\n");
424 log(" $sr, $dff, $dffsr, $adff, $dlatch\n");
427 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
429 log_header("Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
430 extra_args(args
, 1, design
);
432 std::map
<RTLIL::IdString
, void(*)(RTLIL::Module
*, RTLIL::Cell
*)> mappers
;
433 simplemap_get_mappers(mappers
);
435 for (auto mod
: design
->modules()) {
436 if (!design
->selected(mod
))
438 std::vector
<RTLIL::Cell
*> cells
= mod
->cells();
439 for (auto cell
: cells
) {
440 if (mappers
.count(cell
->type
) == 0)
442 if (!design
->selected(mod
, cell
))
444 log("Mapping %s.%s (%s).\n", log_id(mod
), log_id(cell
), log_id(cell
->type
));
445 mappers
.at(cell
->type
)(mod
, cell
);
452 PRIVATE_NAMESPACE_END