2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * 2019 Eddie Hung <eddie@fpgeh.com>
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include "kernel/register.h"
22 #include "kernel/sigtools.h"
23 #include "kernel/utils.h"
24 #include "kernel/celltypes.h"
25 #include "kernel/timinginfo.h"
28 PRIVATE_NAMESPACE_BEGIN
32 inline std::string
remap_name(RTLIL::IdString abc9_name
)
34 return stringf("$abc$%d$%s", map_autoidx
, abc9_name
.c_str()+1);
37 void check(RTLIL::Design
*design
, bool dff_mode
)
39 dict
<IdString
,IdString
> box_lookup
;
40 for (auto m
: design
->modules()) {
41 auto flop
= m
->get_bool_attribute(ID::abc9_flop
);
42 auto it
= m
->attributes
.find(ID::abc9_box_id
);
44 if (it
== m
->attributes
.end())
46 auto id
= it
->second
.as_int();
47 auto r
= box_lookup
.insert(std::make_pair(stringf("$__boxid%d", id
), m
->name
));
49 log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n",
50 log_id(m
), id
, log_id(r
.first
->second
));
53 // Make carry in the last PI, and carry out the last PO
54 // since ABC requires it this way
55 IdString carry_in
, carry_out
;
56 for (const auto &port_name
: m
->ports
) {
57 auto w
= m
->wire(port_name
);
59 if (w
->get_bool_attribute(ID::abc9_carry
)) {
61 if (carry_in
!= IdString())
62 log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", log_id(m
));
66 if (carry_out
!= IdString())
67 log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", log_id(m
));
68 carry_out
= port_name
;
73 if (carry_in
!= IdString() && carry_out
== IdString())
74 log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", log_id(m
));
75 if (carry_in
== IdString() && carry_out
!= IdString())
76 log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", log_id(m
));
80 for (auto port_name
: m
->ports
) {
81 auto wire
= m
->wire(port_name
);
82 if (wire
->port_output
) num_outputs
++;
85 log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", log_id(m
), num_outputs
);
90 static pool
<IdString
> unsupported
{
91 ID($adff
), ID($dlatch
), ID($dlatchsr
), ID($sr
),
92 ID($_DFF_NN0_
), ID($_DFF_NN1_
), ID($_DFF_NP0_
), ID($_DFF_NP1_
),
93 ID($_DFF_PN0_
), ID($_DFF_PN1_
), ID($_DFF_PP0_
), ID($_DFF_PP1_
),
94 ID($_DLATCH_N_
), ID($_DLATCH_P_
),
95 ID($_DLATCHSR_NNN_
), ID($_DLATCHSR_NNP_
), ID($_DLATCHSR_NPN_
), ID($_DLATCHSR_NPP_
),
96 ID($_DLATCHSR_PNN_
), ID($_DLATCHSR_PNP_
), ID($_DLATCHSR_PPN_
), ID($_DLATCHSR_PPP_
),
97 ID($_SR_NN_
), ID($_SR_NP_
), ID($_SR_PN_
), ID($_SR_PP_
)
99 pool
<IdString
> processed
;
100 for (auto module
: design
->selected_modules())
101 for (auto cell
: module
->cells()) {
102 auto inst_module
= design
->module(cell
->type
);
105 if (!inst_module
->get_blackbox_attribute())
107 IdString derived_type
;
108 Module
*derived_module
;
109 if (cell
->parameters
.empty()) {
110 derived_type
= cell
->type
;
111 derived_module
= inst_module
;
114 derived_type
= inst_module
->derive(design
, cell
->parameters
);
115 derived_module
= design
->module(derived_type
);
116 log_assert(derived_module
);
118 if (!derived_module
->get_bool_attribute(ID::abc9_flop
))
120 if (derived_module
->get_blackbox_attribute(true /* ignore_wb */))
121 log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", log_id(derived_type
));
123 if (derived_module
->has_processes())
124 Pass::call_on_module(design
, derived_module
, "proc");
127 for (auto derived_cell
: derived_module
->cells()) {
128 if (derived_cell
->type
.in(ID($dff
), ID($_DFF_N_
), ID($_DFF_P_
))) {
130 log_error("Module '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module
));
133 SigBit Q
= derived_cell
->getPort(ID::Q
);
134 log_assert(GetSize(Q
.wire
) == 1);
136 if (!Q
.wire
->port_output
)
137 log_error("Module '%s' contains a %s cell where its 'Q' port does not drive a module output!\n", log_id(derived_module
), log_id(derived_cell
->type
));
139 Const init
= Q
.wire
->attributes
.at(ID::init
, State::Sx
);
140 log_assert(GetSize(init
) == 1);
142 else if (unsupported
.count(derived_cell
->type
))
143 log_error("Module '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module
), log_id(derived_cell
->type
));
149 void prep_hier(RTLIL::Design
*design
, bool dff_mode
)
151 auto r
= saved_designs
.emplace("$abc9_unmap", nullptr);
153 r
.first
->second
= new Design
;
154 Design
*unmap_design
= r
.first
->second
;
156 static const pool
<IdString
> seq_types
{
157 ID($dff
), ID($dffsr
), ID($adff
),
158 ID($dlatch
), ID($dlatchsr
), ID($sr
),
160 ID($_DFF_N_
), ID($_DFF_P_
),
161 ID($_DFFSR_NNN_
), ID($_DFFSR_NNP_
), ID($_DFFSR_NPN_
), ID($_DFFSR_NPP_
),
162 ID($_DFFSR_PNN_
), ID($_DFFSR_PNP_
), ID($_DFFSR_PPN_
), ID($_DFFSR_PPP_
),
163 ID($_DFF_N_
), ID($_DFF_NN0_
), ID($_DFF_NN1_
), ID($_DFF_NP0_
), ID($_DFF_NP1_
),
164 ID($_DFF_P_
), ID($_DFF_PN0_
), ID($_DFF_PN1_
), ID($_DFF_PP0_
), ID($_DFF_PP1_
),
165 ID($_DLATCH_N_
), ID($_DLATCH_P_
),
166 ID($_DLATCHSR_NNN_
), ID($_DLATCHSR_NNP_
), ID($_DLATCHSR_NPN_
), ID($_DLATCHSR_NPP_
),
167 ID($_DLATCHSR_PNN_
), ID($_DLATCHSR_PNP_
), ID($_DLATCHSR_PPN_
), ID($_DLATCHSR_PPP_
),
168 ID($_SR_NN_
), ID($_SR_NP_
), ID($_SR_PN_
), ID($_SR_PP_
)
171 for (auto module
: design
->selected_modules())
172 for (auto cell
: module
->cells()) {
173 auto inst_module
= design
->module(cell
->type
);
176 if (!inst_module
->get_blackbox_attribute())
178 IdString derived_type
;
179 Module
*derived_module
;
180 if (cell
->parameters
.empty()) {
181 derived_type
= cell
->type
;
182 derived_module
= inst_module
;
185 derived_type
= inst_module
->derive(design
, cell
->parameters
);
186 derived_module
= design
->module(derived_type
);
188 if (derived_module
->get_blackbox_attribute(true /* ignore_wb */))
191 if (derived_module
->get_bool_attribute(ID::abc9_flop
)) {
196 if (!derived_module
->get_bool_attribute(ID::abc9_box
) && !derived_module
->get_bool_attribute(ID::abc9_bypass
))
200 if (!unmap_design
->module(derived_type
)) {
201 if (derived_module
->has_processes())
202 Pass::call_on_module(design
, derived_module
, "proc");
204 if (derived_module
->get_bool_attribute(ID::abc9_flop
)) {
205 for (auto derived_cell
: derived_module
->cells())
206 if (derived_cell
->type
.in(ID($dff
), ID($_DFF_N_
), ID($_DFF_P_
))) {
207 SigBit Q
= derived_cell
->getPort(ID::Q
);
208 Const init
= Q
.wire
->attributes
.at(ID::init
, State::Sx
);
209 log_assert(GetSize(init
) == 1);
211 // Block sequential synthesis on cells with (* init *) != 1'b0
212 // because ABC9 doesn't support them
213 if (init
!= State::S0
) {
214 log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module
), log_id(derived_cell
->type
));
215 derived_module
->set_bool_attribute(ID::abc9_flop
, false);
220 else if (derived_module
->get_bool_attribute(ID::abc9_box
)) {
221 for (auto derived_cell
: derived_module
->cells())
222 if (seq_types
.count(derived_cell
->type
)) {
223 derived_module
->set_bool_attribute(ID::abc9_box
, false);
224 derived_module
->set_bool_attribute(ID::abc9_bypass
);
229 if (derived_type
!= cell
->type
) {
230 auto unmap_module
= unmap_design
->addModule(derived_type
);
231 for (auto port
: derived_module
->ports
) {
232 auto w
= unmap_module
->addWire(port
, derived_module
->wire(port
));
233 // Do not propagate (* init *) values into the box,
234 // in fact, remove it from outside too
235 if (w
->port_output
&& w
->attributes
.erase(ID::init
)) {
236 auto r
= unmap_module
->addWire(stringf("\\_TECHMAP_REMOVEINIT_%s_", log_id(port
)));
237 unmap_module
->connect(r
, State::S1
);
240 unmap_module
->ports
= derived_module
->ports
;
241 unmap_module
->check();
243 auto replace_cell
= unmap_module
->addCell(ID::_TECHMAP_REPLACE_
, cell
->type
);
244 for (const auto &conn
: cell
->connections()) {
245 auto w
= unmap_module
->wire(conn
.first
);
247 replace_cell
->setPort(conn
.first
, w
);
249 replace_cell
->parameters
= cell
->parameters
;
253 cell
->type
= derived_type
;
254 cell
->parameters
.clear();
258 void prep_bypass(RTLIL::Design
*design
)
260 auto r
= saved_designs
.emplace("$abc9_map", nullptr);
262 r
.first
->second
= new Design
;
263 Design
*map_design
= r
.first
->second
;
265 r
= saved_designs
.emplace("$abc9_unmap", nullptr);
267 r
.first
->second
= new Design
;
268 Design
*unmap_design
= r
.first
->second
;
270 pool
<IdString
> processed
;
271 for (auto module
: design
->selected_modules())
272 for (auto cell
: module
->cells()) {
273 if (!processed
.insert(cell
->type
).second
)
275 auto inst_module
= design
->module(cell
->type
);
278 if (!inst_module
->get_bool_attribute(ID::abc9_bypass
))
280 log_assert(!inst_module
->get_blackbox_attribute(true /* ignore_wb */));
281 log_assert(cell
->parameters
.empty());
284 // The idea is to create two techmap designs, one which maps:
286 // box u0 (.i(i), .o(o));
291 // box u0 (.i(i), .o($abc9_byp$o));
292 // box_$abc9_byp (.i(i), .$abc9_byp$o($abc9_byp$o), .o(o));
294 // the purpose being to move the (* abc9_box *) status from 'box'
295 // (which is stateful) to 'box_$abc9_byp' (which becomes a new
296 // combinatorial black- (not white-) box with all state elements
297 // removed). This has the effect of preserving any combinatorial
298 // paths through an otherwise sequential primitive -- e.g. LUTRAMs.
300 // The unmap design performs the reverse:
303 // box u0 (.i(i), .o($abc9_byp$o));
304 // box_$abc9_byp (.i(i), .$abc9_byp$o($abc9_byp$o), .o(o));
309 // box u0 (.i(i), .o($abc9_byp$o));
310 // assign o = $abc9_byp$o;
313 // Copy inst_module into map_design, with the same interface
314 // and duplicate $abc9$* wires for its output ports
315 auto map_module
= map_design
->addModule(cell
->type
);
316 for (auto port_name
: inst_module
->ports
) {
317 auto w
= map_module
->addWire(port_name
, inst_module
->wire(port_name
));
319 w
->attributes
.erase(ID::init
);
321 map_module
->ports
= inst_module
->ports
;
323 map_module
->set_bool_attribute(ID::whitebox
);
325 // Create the bypass module in the user design, which has the same
326 // interface as the derived module but with additional input
327 // ports driven by the outputs of the replaced cell
328 auto bypass_module
= design
->addModule(cell
->type
.str() + "_$abc9_byp");
329 for (auto port_name
: inst_module
->ports
) {
330 auto port
= inst_module
->wire(port_name
);
331 if (!port
->port_output
)
333 auto dst
= bypass_module
->addWire(port_name
, port
);
334 auto src
= bypass_module
->addWire("$abc9byp$" + port_name
.str(), GetSize(port
));
335 src
->port_input
= true;
336 // For these new input ports driven by the replaced
337 // cell, then create a new simple-path specify entry:
338 // (input => output) = 0
339 auto specify
= bypass_module
->addCell(NEW_ID
, ID($specify2
));
340 specify
->setPort(ID::EN
, State::S1
);
341 specify
->setPort(ID::SRC
, src
);
342 specify
->setPort(ID::DST
, dst
);
343 specify
->setParam(ID::FULL
, 0);
344 specify
->setParam(ID::SRC_WIDTH
, GetSize(src
));
345 specify
->setParam(ID::DST_WIDTH
, GetSize(dst
));
346 specify
->setParam(ID::SRC_DST_PEN
, 0);
347 specify
->setParam(ID::SRC_DST_POL
, 0);
348 specify
->setParam(ID::T_RISE_MIN
, 0);
349 specify
->setParam(ID::T_RISE_TYP
, 0);
350 specify
->setParam(ID::T_RISE_MAX
, 0);
351 specify
->setParam(ID::T_FALL_MIN
, 0);
352 specify
->setParam(ID::T_FALL_TYP
, 0);
353 specify
->setParam(ID::T_FALL_MAX
, 0);
355 bypass_module
->set_bool_attribute(ID::blackbox
);
356 bypass_module
->set_bool_attribute(ID::abc9_box
);
358 // Copy any 'simple' (combinatorial) specify paths from
359 // the derived module into the bypass module, if EN
360 // is not false and SRC/DST are driven only by
361 // module ports; create new input port if one doesn't
363 for (auto cell
: inst_module
->cells()) {
364 if (cell
->type
!= ID($specify2
))
366 auto EN
= cell
->getPort(ID::EN
).as_bit();
368 if (!EN
.wire
&& EN
!= State::S1
)
370 auto SRC
= cell
->getPort(ID::SRC
);
371 for (const auto &c
: SRC
.chunks())
372 if (c
.wire
&& !c
.wire
->port_input
) {
378 auto DST
= cell
->getPort(ID::DST
);
379 for (const auto &c
: DST
.chunks())
380 if (c
.wire
&& !c
.wire
->port_output
) {
386 auto rw
= [bypass_module
](RTLIL::SigSpec
&sig
)
389 for (auto c
: sig
.chunks()) {
391 auto port
= bypass_module
->wire(c
.wire
->name
);
393 port
= bypass_module
->addWire(c
.wire
->name
, c
.wire
);
396 new_sig
.append(std::move(c
));
398 sig
= std::move(new_sig
);
400 auto specify
= bypass_module
->addCell(NEW_ID
, cell
);
401 specify
->rewrite_sigspecs(rw
);
403 bypass_module
->fixup_ports();
405 // Create an _TECHMAP_REPLACE_ cell identical to the original cell,
406 // and a bypass cell that has the same inputs/outputs as the
407 // original cell, but with additional inputs taken from the
409 auto replace_cell
= map_module
->addCell(ID::_TECHMAP_REPLACE_
, cell
->type
);
410 auto bypass_cell
= map_module
->addCell(NEW_ID
, cell
->type
.str() + "_$abc9_byp");
411 for (const auto &conn
: cell
->connections()) {
412 auto port
= map_module
->wire(conn
.first
);
413 if (cell
->input(conn
.first
)) {
414 replace_cell
->setPort(conn
.first
, port
);
415 if (bypass_module
->wire(conn
.first
))
416 bypass_cell
->setPort(conn
.first
, port
);
418 if (cell
->output(conn
.first
)) {
419 bypass_cell
->setPort(conn
.first
, port
);
420 auto n
= "$abc9byp$" + conn
.first
.str();
421 auto w
= map_module
->addWire(n
, GetSize(conn
.second
));
422 replace_cell
->setPort(conn
.first
, w
);
423 bypass_cell
->setPort(n
, w
);
428 // Lastly, create a new module in the unmap_design that shorts
429 // out the bypass cell back to leave the replace cell behind
430 // driving the outputs
431 auto unmap_module
= unmap_design
->addModule(cell
->type
.str() + "_$abc9_byp");
432 for (auto port_name
: inst_module
->ports
) {
433 auto w
= unmap_module
->addWire(port_name
, inst_module
->wire(port_name
));
434 if (w
->port_output
) {
435 w
->attributes
.erase(ID::init
);
436 auto w2
= unmap_module
->addWire("$abc9byp$" + port_name
.str(), GetSize(w
));
437 w2
->port_input
= true;
438 unmap_module
->connect(w
, w2
);
441 unmap_module
->fixup_ports();
445 void prep_dff(RTLIL::Design
*design
)
447 auto r
= design
->selection_vars
.insert(std::make_pair(ID($abc9_flops
), RTLIL::Selection(false)));
448 auto &modules_sel
= r
.first
->second
;
450 for (auto module
: design
->selected_modules())
451 for (auto cell
: module
->cells()) {
452 if (modules_sel
.selected_whole_module(cell
->type
))
454 auto inst_module
= design
->module(cell
->type
);
457 if (!inst_module
->get_bool_attribute(ID::abc9_flop
))
459 log_assert(!inst_module
->get_blackbox_attribute(true /* ignore_wb */));
460 log_assert(cell
->parameters
.empty());
461 modules_sel
.select(inst_module
);
465 void prep_dff_submod(RTLIL::Design
*design
)
467 for (auto module
: design
->modules()) {
468 vector
<Cell
*> specify_cells
;
470 Cell
* dff_cell
= nullptr;
472 if (!module
->get_bool_attribute(ID::abc9_flop
))
475 for (auto cell
: module
->cells())
476 if (cell
->type
.in(ID($_DFF_N_
), ID($_DFF_P_
))) {
477 log_assert(!dff_cell
);
479 Q
= cell
->getPort(ID::Q
);
480 log_assert(GetSize(Q
.wire
) == 1);
482 else if (cell
->type
.in(ID($specify3
), ID($specrule
)))
483 specify_cells
.emplace_back(cell
);
484 log_assert(dff_cell
);
486 // Add an always-enabled CE mux that drives $_DFF_[NP]_.D so that:
487 // (a) flop box will have an output
488 // (b) $_DFF_[NP]_.Q will be present as an input
489 SigBit D
= module
->addWire(NEW_ID
);
490 module
->addMuxGate(NEW_ID
, dff_cell
->getPort(ID::D
), Q
, State::S0
, D
);
491 dff_cell
->setPort(ID::D
, D
);
493 // Rewrite $specify cells that end with $_DFF_[NP]_.Q
494 // to $_DFF_[NP]_.D since it will be moved into
496 for (auto cell
: specify_cells
) {
497 auto DST
= cell
->getPort(ID::DST
);
499 cell
->setPort(ID::DST
, DST
);
502 design
->scratchpad_set_bool("abc9_ops.prep_dff_submod.did_something", true);
506 void prep_dff_unmap(RTLIL::Design
*design
)
508 Design
*unmap_design
= saved_designs
.at("$abc9_unmap");
510 for (auto module
: design
->modules()) {
511 if (!module
->get_bool_attribute(ID::abc9_flop
) || module
->get_bool_attribute(ID::abc9_box
))
514 // Make sure the box module has all the same ports present on flop cell
515 auto replace_cell
= module
->cell(ID::_TECHMAP_REPLACE_
);
516 log_assert(replace_cell
);
517 auto box_module
= design
->module(module
->name
.str() + "_$abc9_flop");
518 log_assert(box_module
);
519 for (auto port_name
: module
->ports
) {
520 auto port
= module
->wire(port_name
);
521 auto box_port
= box_module
->wire(port_name
);
523 // Do not propagate init -- already captured by box
524 box_port
->attributes
.erase(ID::init
);
527 log_assert(port
->port_input
);
528 box_module
->addWire(port_name
, port
);
529 replace_cell
->setPort(port_name
, port
);
531 box_module
->fixup_ports();
533 auto unmap_module
= unmap_design
->addModule(box_module
->name
);
534 replace_cell
= unmap_module
->addCell(ID::_TECHMAP_REPLACE_
, module
->name
);
535 for (auto port_name
: box_module
->ports
) {
536 auto w
= unmap_module
->addWire(port_name
, box_module
->wire(port_name
));
537 if (module
->wire(port_name
))
538 replace_cell
->setPort(port_name
, w
);
540 unmap_module
->ports
= box_module
->ports
;
541 unmap_module
->check();
545 void mark_scc(RTLIL::Module
*module
)
547 // For every unique SCC found, (arbitrarily) find the first
548 // cell in the component, and replace its output connections
549 // with a new wire driven by the old connection but with a
550 // special (* abc9_keep *) attribute set (which is used by
551 // write_xaiger to break this wire into PI and POs)
552 pool
<RTLIL::Const
> ids_seen
;
553 for (auto cell
: module
->cells()) {
554 auto it
= cell
->attributes
.find(ID::abc9_scc_id
);
555 if (it
== cell
->attributes
.end())
557 auto id
= it
->second
;
558 auto r
= ids_seen
.insert(id
);
559 cell
->attributes
.erase(it
);
562 for (auto &c
: cell
->connections_
) {
563 if (c
.second
.is_fully_const()) continue;
564 if (cell
->output(c
.first
)) {
565 Wire
*w
= module
->addWire(NEW_ID
, GetSize(c
.second
));
566 w
->set_bool_attribute(ID::abc9_keep
);
567 module
->connect(w
, c
.second
);
574 void prep_delays(RTLIL::Design
*design
, bool dff_mode
)
578 // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes
579 // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations
580 std::vector
<Cell
*> cells
;
581 for (auto module
: design
->selected_modules()) {
582 if (module
->processes
.size() > 0) {
583 log("Skipping module %s as it contains processes.\n", log_id(module
));
587 for (auto cell
: module
->cells()) {
588 if (cell
->type
.in(ID($_AND_
), ID($_NOT_
), ID($_DFF_N_
), ID($_DFF_P_
)))
590 log_assert(!cell
->type
.begins_with("$paramod$__ABC9_DELAY\\DELAY="));
592 RTLIL::Module
* inst_module
= design
->module(cell
->type
);
595 if (!inst_module
->get_blackbox_attribute())
597 if (!cell
->parameters
.empty())
600 if (inst_module
->get_bool_attribute(ID::abc9_box
))
602 if (inst_module
->get_bool_attribute(ID::abc9_bypass
))
605 if (dff_mode
&& inst_module
->get_bool_attribute(ID::abc9_flop
)) {
606 continue; // do not add $__ABC9_DELAY boxes to flops
607 // as delays will be captured in the flop box
610 if (!timing
.count(cell
->type
))
611 timing
.setup_module(inst_module
);
613 cells
.emplace_back(cell
);
617 // Insert $__ABC9_DELAY cells on all cells that instantiate blackboxes
618 // (or bypassed white-boxes with required times)
619 dict
<int, IdString
> box_cache
;
620 Module
*delay_module
= design
->module(ID($__ABC9_DELAY
));
621 log_assert(delay_module
);
622 for (auto cell
: cells
) {
623 auto module
= cell
->module
;
624 auto inst_module
= design
->module(cell
->type
);
625 log_assert(inst_module
);
627 auto &t
= timing
.at(cell
->type
).required
;
628 for (auto &conn
: cell
->connections_
) {
629 auto port_wire
= inst_module
->wire(conn
.first
);
631 log_error("Port %s in cell %s (type %s) from module %s does not actually exist",
632 log_id(conn
.first
), log_id(cell
), log_id(cell
->type
), log_id(module
));
633 if (!port_wire
->port_input
)
635 if (conn
.second
.is_fully_const())
638 SigSpec O
= module
->addWire(NEW_ID
, GetSize(conn
.second
));
639 for (int i
= 0; i
< GetSize(conn
.second
); i
++) {
640 auto d
= t
.at(TimingInfo::NameBit(conn
.first
,i
), 0);
646 static std::set
<std::tuple
<IdString
,IdString
,int>> seen
;
647 if (seen
.emplace(cell
->type
, conn
.first
, i
).second
) log("%s.%s[%d] abc9_required = %d\n",
648 log_id(cell
->type
), log_id(conn
.first
), i
, d
);
651 auto r
= box_cache
.insert(d
);
653 r
.first
->second
= delay_module
->derive(design
, {{ID::DELAY
, d
}});
654 log_assert(r
.first
->second
.begins_with("$paramod$__ABC9_DELAY\\DELAY="));
656 auto box
= module
->addCell(NEW_ID
, r
.first
->second
);
657 box
->setPort(ID::I
, conn
.second
[i
]);
658 box
->setPort(ID::O
, O
[i
]);
659 conn
.second
[i
] = O
[i
];
665 void prep_xaiger(RTLIL::Module
*module
, bool dff
)
667 auto design
= module
->design
;
670 SigMap
sigmap(module
);
672 dict
<SigBit
, pool
<IdString
>> bit_drivers
, bit_users
;
673 TopoSort
<IdString
, RTLIL::sort_by_id_str
> toposort
;
674 dict
<IdString
, std::vector
<IdString
>> box_ports
;
676 for (auto cell
: module
->cells()) {
677 if (cell
->type
.in(ID($_DFF_N_
), ID($_DFF_P_
)))
679 if (cell
->has_keep_attr())
682 auto inst_module
= design
->module(cell
->type
);
683 bool abc9_flop
= inst_module
&& inst_module
->get_bool_attribute(ID::abc9_flop
);
684 if (abc9_flop
&& !dff
)
687 if (inst_module
&& inst_module
->get_bool_attribute(ID::abc9_box
)) {
688 auto r
= box_ports
.insert(cell
->type
);
690 // Make carry in the last PI, and carry out the last PO
691 // since ABC requires it this way
692 IdString carry_in
, carry_out
;
693 for (const auto &port_name
: inst_module
->ports
) {
694 auto w
= inst_module
->wire(port_name
);
696 if (w
->get_bool_attribute(ID::abc9_carry
)) {
697 log_assert(w
->port_input
!= w
->port_output
);
699 carry_in
= port_name
;
700 else if (w
->port_output
)
701 carry_out
= port_name
;
704 r
.first
->second
.push_back(port_name
);
706 if (carry_in
!= IdString()) {
707 r
.first
->second
.push_back(carry_in
);
708 r
.first
->second
.push_back(carry_out
);
712 else if (!yosys_celltypes
.cell_known(cell
->type
))
715 // TODO: Speed up toposort -- we care about box ordering only
716 for (auto conn
: cell
->connections()) {
717 if (cell
->input(conn
.first
))
718 for (auto bit
: sigmap(conn
.second
))
719 bit_users
[bit
].insert(cell
->name
);
721 if (cell
->output(conn
.first
) && !abc9_flop
)
722 for (const auto &chunk
: conn
.second
.chunks())
723 if (!chunk
.wire
->get_bool_attribute(ID::abc9_keep
))
724 for (auto b
: sigmap(SigSpec(chunk
)))
725 bit_drivers
[b
].insert(cell
->name
);
727 toposort
.node(cell
->name
);
730 if (box_ports
.empty())
733 for (auto &it
: bit_users
)
734 if (bit_drivers
.count(it
.first
))
735 for (auto driver_cell
: bit_drivers
.at(it
.first
))
736 for (auto user_cell
: it
.second
)
737 toposort
.edge(driver_cell
, user_cell
);
740 toposort
.analyze_loops
= true;
742 bool no_loops
YS_ATTRIBUTE(unused
) = toposort
.sort();
746 for (auto &it
: toposort
.loops
) {
747 log(" loop %d\n", i
++);
748 for (auto cell_name
: it
) {
749 auto cell
= module
->cell(cell_name
);
751 log("\t%s (%s @ %s)\n", log_id(cell
), log_id(cell
->type
), cell
->get_src_attribute().c_str());
756 log_assert(no_loops
);
758 auto r
= saved_designs
.emplace("$abc9_holes", nullptr);
760 r
.first
->second
= new Design
;
761 RTLIL::Design
*holes_design
= r
.first
->second
;
762 log_assert(holes_design
);
763 RTLIL::Module
*holes_module
= holes_design
->addModule(module
->name
);
764 log_assert(holes_module
);
766 dict
<IdString
, Cell
*> cell_cache
;
769 int port_id
= 1, box_count
= 0;
770 for (auto cell_name
: toposort
.sorted
) {
771 RTLIL::Cell
*cell
= module
->cell(cell_name
);
774 RTLIL::Module
* box_module
= design
->module(cell
->type
);
777 if (!box_module
->get_bool_attribute(ID::abc9_box
))
779 log_assert(cell
->parameters
.empty());
780 log_assert(box_module
->get_blackbox_attribute());
782 cell
->attributes
[ID::abc9_box_seq
] = box_count
++;
784 auto r
= cell_cache
.insert(cell
->type
);
785 auto &holes_cell
= r
.first
->second
;
787 if (box_module
->get_bool_attribute(ID::whitebox
)) {
788 holes_cell
= holes_module
->addCell(cell
->name
, cell
->type
);
790 if (box_module
->has_processes())
791 Pass::call_on_module(design
, box_module
, "proc");
794 for (auto port_name
: box_ports
.at(cell
->type
)) {
795 RTLIL::Wire
*w
= box_module
->wire(port_name
);
797 log_assert(!w
->port_input
|| !w
->port_output
);
798 auto &conn
= holes_cell
->connections_
[port_name
];
800 for (int i
= 0; i
< GetSize(w
); i
++) {
802 RTLIL::Wire
*holes_wire
= holes_module
->wire(stringf("\\i%d", box_inputs
));
804 holes_wire
= holes_module
->addWire(stringf("\\i%d", box_inputs
));
805 holes_wire
->port_input
= true;
806 holes_wire
->port_id
= port_id
++;
807 holes_module
->ports
.push_back(holes_wire
->name
);
809 conn
.append(holes_wire
);
812 else if (w
->port_output
)
813 conn
= holes_module
->addWire(stringf("%s.%s", cell
->type
.c_str(), log_id(port_name
)), GetSize(w
));
816 else // box_module is a blackbox
817 log_assert(holes_cell
== nullptr);
820 for (auto port_name
: box_ports
.at(cell
->type
)) {
821 RTLIL::Wire
*w
= box_module
->wire(port_name
);
825 Wire
*holes_wire
= holes_module
->addWire(stringf("$abc%s.%s", cell
->name
.c_str(), log_id(port_name
)), GetSize(w
));
826 holes_wire
->port_output
= true;
827 holes_wire
->port_id
= port_id
++;
828 holes_module
->ports
.push_back(holes_wire
->name
);
829 if (holes_cell
) // whitebox
830 holes_module
->connect(holes_wire
, holes_cell
->getPort(port_name
));
832 holes_module
->connect(holes_wire
, Const(State::S0
, GetSize(w
)));
837 void prep_lut(RTLIL::Design
*design
, int maxlut
)
844 std::vector
<int> delays
;
846 std::map
<int,t_lut
> table
;
847 for (auto module
: design
->modules()) {
848 auto it
= module
->attributes
.find(ID::abc9_lut
);
849 if (it
== module
->attributes
.end())
852 auto &t
= timing
.setup_module(module
);
854 TimingInfo::NameBit o
;
855 std::vector
<int> delays
;
856 for (const auto &i
: t
.comb
) {
857 auto &d
= i
.first
.second
;
858 if (o
== TimingInfo::NameBit())
861 log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", log_id(module
));
862 delays
.push_back(i
.second
);
865 if (GetSize(delays
) == 0)
866 log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", log_id(module
));
867 if (maxlut
&& GetSize(delays
) > maxlut
)
869 // ABC requires non-decreasing LUT input delays
870 std::sort(delays
.begin(), delays
.end());
872 int K
= GetSize(delays
);
873 auto entry
= t_lut
{module
->name
, it
->second
.as_int(), std::move(delays
)};
874 auto r
= table
.emplace(K
, entry
);
876 if (r
.first
->second
.area
!= entry
.area
)
877 log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", log_id(module
), log_id(r
.first
->second
.name
));
878 if (r
.first
->second
.delays
!= entry
.delays
)
879 log_error("Modules '%s' and '%s' have conflicting specify entries.\n", log_id(module
), log_id(r
.first
->second
.name
));
884 log_error("Design does not contain any modules with (* abc9_lut *).\n");
886 std::stringstream ss
;
887 const auto &front
= *table
.begin();
888 // If the first entry does not start from a 1-input LUT,
889 // (as ABC requires) crop the first entry to do so
890 for (int i
= 1; i
< front
.first
; i
++) {
891 ss
<< "# $__ABC9_LUT" << i
<< std::endl
;
892 ss
<< i
<< " " << front
.second
.area
;
893 for (int j
= 0; j
< i
; j
++)
894 ss
<< " " << front
.second
.delays
[j
];
897 for (const auto &i
: table
) {
898 ss
<< "# " << log_id(i
.second
.name
) << std::endl
;
899 ss
<< i
.first
<< " " << i
.second
.area
;
900 for (const auto &j
: i
.second
.delays
)
904 design
->scratchpad_set_string("abc9_ops.lut_library", ss
.str());
907 void write_lut(RTLIL::Module
*module
, const std::string
&dst
) {
908 std::ofstream
ofs(dst
);
909 log_assert(ofs
.is_open());
910 ofs
<< module
->design
->scratchpad_get_string("abc9_ops.lut_library");
914 void prep_box(RTLIL::Design
*design
)
918 std::stringstream ss
;
920 for (auto module
: design
->modules()) {
921 auto it
= module
->attributes
.find(ID::abc9_box_id
);
922 if (it
== module
->attributes
.end())
924 abc9_box_id
= std::max(abc9_box_id
, it
->second
.as_int());
927 dict
<IdString
,std::vector
<IdString
>> box_ports
;
928 for (auto module
: design
->modules()) {
929 auto it
= module
->attributes
.find(ID::abc9_box
);
930 if (it
== module
->attributes
.end())
932 bool box
= it
->second
.as_bool();
933 module
->attributes
.erase(it
);
937 auto r
= module
->attributes
.insert(ID::abc9_box_id
);
940 r
.first
->second
= abc9_box_id
++;
942 if (module
->get_bool_attribute(ID::abc9_flop
)) {
943 int num_inputs
= 0, num_outputs
= 0;
944 for (auto port_name
: module
->ports
) {
945 auto wire
= module
->wire(port_name
);
946 log_assert(GetSize(wire
) == 1);
947 if (wire
->port_input
) num_inputs
++;
948 if (wire
->port_output
) num_outputs
++;
950 log_assert(num_outputs
== 1);
952 ss
<< log_id(module
) << " " << r
.first
->second
.as_int();
953 log_assert(module
->get_bool_attribute(ID::whitebox
));
955 ss
<< " " << num_inputs
<< " " << num_outputs
<< std::endl
;
959 for (auto port_name
: module
->ports
) {
960 auto wire
= module
->wire(port_name
);
961 if (!wire
->port_input
)
971 auto &t
= timing
.setup_module(module
).required
;
973 log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", log_id(module
));
976 for (auto port_name
: module
->ports
) {
977 auto wire
= module
->wire(port_name
);
978 if (!wire
->port_input
)
984 log_assert(GetSize(wire
) == 1);
985 auto it
= t
.find(TimingInfo::NameBit(port_name
,0));
987 // Assume no connectivity if no setup time
994 static std::set
<std::pair
<IdString
,IdString
>> seen
;
995 if (seen
.emplace(module
->name
, port_name
).second
) log("%s.%s abc9_required = %d\n", log_id(module
),
996 log_id(port_name
), it
->second
);
1001 ss
<< " # $_DFF_[NP]_.D" << std::endl
;
1005 auto r2
= box_ports
.insert(module
->name
);
1007 // Make carry in the last PI, and carry out the last PO
1008 // since ABC requires it this way
1009 IdString carry_in
, carry_out
;
1010 for (const auto &port_name
: module
->ports
) {
1011 auto w
= module
->wire(port_name
);
1013 if (w
->get_bool_attribute(ID::abc9_carry
)) {
1014 log_assert(w
->port_input
!= w
->port_output
);
1016 carry_in
= port_name
;
1017 else if (w
->port_output
)
1018 carry_out
= port_name
;
1021 r2
.first
->second
.push_back(port_name
);
1024 if (carry_in
!= IdString()) {
1025 r2
.first
->second
.push_back(carry_in
);
1026 r2
.first
->second
.push_back(carry_out
);
1030 std::vector
<SigBit
> inputs
, outputs
;
1031 for (auto port_name
: r2
.first
->second
) {
1032 auto wire
= module
->wire(port_name
);
1033 if (wire
->port_input
)
1034 for (int i
= 0; i
< GetSize(wire
); i
++)
1035 inputs
.emplace_back(wire
, i
);
1036 if (wire
->port_output
)
1037 for (int i
= 0; i
< GetSize(wire
); i
++)
1038 outputs
.emplace_back(wire
, i
);
1041 ss
<< log_id(module
) << " " << module
->attributes
.at(ID::abc9_box_id
).as_int();
1042 ss
<< " " << (module
->get_bool_attribute(ID::whitebox
) ? "1" : "0");
1043 ss
<< " " << GetSize(inputs
) << " " << GetSize(outputs
) << std::endl
;
1047 for (const auto &i
: inputs
) {
1052 if (GetSize(i
.wire
) == 1)
1053 ss
<< log_id(i
.wire
);
1055 ss
<< log_id(i
.wire
) << "[" << i
.offset
<< "]";
1059 auto &t
= timing
.setup_module(module
);
1061 log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", log_id(module
));
1063 for (const auto &o
: outputs
) {
1065 for (const auto &i
: inputs
) {
1070 auto jt
= t
.comb
.find(TimingInfo::BitBit(i
,o
));
1071 if (jt
== t
.comb
.end())
1077 if (GetSize(o
.wire
) == 1)
1078 ss
<< log_id(o
.wire
);
1080 ss
<< log_id(o
.wire
) << "[" << o
.offset
<< "]";
1087 // ABC expects at least one box
1088 if (ss
.tellp() == 0)
1089 ss
<< "(dummy) 1 0 0 0";
1091 design
->scratchpad_set_string("abc9_ops.box_library", ss
.str());
1094 void write_box(RTLIL::Module
*module
, const std::string
&dst
) {
1095 std::ofstream
ofs(dst
);
1096 log_assert(ofs
.is_open());
1097 ofs
<< module
->design
->scratchpad_get_string("abc9_ops.box_library");
1101 void reintegrate(RTLIL::Module
*module
, bool dff_mode
)
1103 auto design
= module
->design
;
1106 map_autoidx
= autoidx
++;
1108 RTLIL::Module
*mapped_mod
= design
->module(stringf("%s$abc9", module
->name
.c_str()));
1109 if (mapped_mod
== NULL
)
1110 log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module
));
1112 for (auto w
: mapped_mod
->wires()) {
1113 auto nw
= module
->addWire(remap_name(w
->name
), GetSize(w
));
1114 nw
->start_offset
= w
->start_offset
;
1115 // Remove all (* init *) since they only existon $_DFF_[NP]_
1116 w
->attributes
.erase(ID::init
);
1119 dict
<IdString
,std::vector
<IdString
>> box_ports
;
1121 for (auto m
: design
->modules()) {
1122 if (!m
->attributes
.count(ID::abc9_box_id
))
1125 auto r
= box_ports
.insert(m
->name
);
1129 // Make carry in the last PI, and carry out the last PO
1130 // since ABC requires it this way
1131 IdString carry_in
, carry_out
;
1132 for (const auto &port_name
: m
->ports
) {
1133 auto w
= m
->wire(port_name
);
1135 if (w
->get_bool_attribute(ID::abc9_carry
)) {
1136 log_assert(w
->port_input
!= w
->port_output
);
1138 carry_in
= port_name
;
1139 else if (w
->port_output
)
1140 carry_out
= port_name
;
1143 r
.first
->second
.push_back(port_name
);
1146 if (carry_in
!= IdString()) {
1147 r
.first
->second
.push_back(carry_in
);
1148 r
.first
->second
.push_back(carry_out
);
1152 std::vector
<Cell
*> boxes
;
1153 for (auto cell
: module
->cells().to_vector()) {
1154 if (cell
->has_keep_attr())
1157 // Short out $_DFF_[NP]_ cells since the flop box already has
1158 // all the information we need to reconstruct cell
1159 if (dff_mode
&& cell
->type
.in(ID($_DFF_N_
), ID($_DFF_P_
)) && !cell
->get_bool_attribute(ID::abc9_keep
)) {
1160 module
->connect(cell
->getPort(ID::Q
), cell
->getPort(ID::D
));
1161 module
->remove(cell
);
1163 else if (cell
->type
.in(ID($_AND_
), ID($_NOT_
)))
1164 module
->remove(cell
);
1165 else if (cell
->attributes
.erase(ID::abc9_box_seq
))
1166 boxes
.emplace_back(cell
);
1169 dict
<SigBit
, pool
<IdString
>> bit_drivers
, bit_users
;
1170 TopoSort
<IdString
, RTLIL::sort_by_id_str
> toposort
;
1171 dict
<RTLIL::Cell
*,RTLIL::Cell
*> not2drivers
;
1172 dict
<SigBit
, std::vector
<RTLIL::Cell
*>> bit2sinks
;
1174 std::map
<IdString
, int> cell_stats
;
1175 for (auto mapped_cell
: mapped_mod
->cells())
1177 // Short out $_FF_ cells since the flop box already has
1178 // all the information we need to reconstruct cell
1179 if (dff_mode
&& mapped_cell
->type
== ID($_FF_
)) {
1180 SigBit D
= mapped_cell
->getPort(ID::D
);
1181 SigBit Q
= mapped_cell
->getPort(ID::Q
);
1183 D
.wire
= module
->wires_
.at(remap_name(D
.wire
->name
));
1184 Q
.wire
= module
->wires_
.at(remap_name(Q
.wire
->name
));
1185 module
->connect(Q
, D
);
1189 // TODO: Speed up toposort -- we care about NOT ordering only
1190 toposort
.node(mapped_cell
->name
);
1192 if (mapped_cell
->type
== ID($_NOT_
)) {
1193 RTLIL::SigBit a_bit
= mapped_cell
->getPort(ID::A
);
1194 RTLIL::SigBit y_bit
= mapped_cell
->getPort(ID::Y
);
1195 bit_users
[a_bit
].insert(mapped_cell
->name
);
1196 // Ignore inouts for topo ordering
1197 if (y_bit
.wire
&& !(y_bit
.wire
->port_input
&& y_bit
.wire
->port_output
))
1198 bit_drivers
[y_bit
].insert(mapped_cell
->name
);
1201 mapped_cell
->setPort(ID::Y
, module
->addWire(NEW_ID
));
1202 RTLIL::Wire
*wire
= module
->wire(remap_name(y_bit
.wire
->name
));
1204 module
->connect(RTLIL::SigBit(wire
, y_bit
.offset
), State::S1
);
1207 RTLIL::Cell
* driver_lut
= nullptr;
1208 // ABC can return NOT gates that drive POs
1209 if (!a_bit
.wire
->port_input
) {
1210 // If it's not a NOT gate that that comes from a PI directly,
1211 // find the driver LUT and clone that to guarantee that we won't
1212 // increase the max logic depth
1213 // (TODO: Optimise by not cloning unless will increase depth)
1214 RTLIL::IdString driver_name
;
1215 if (GetSize(a_bit
.wire
) == 1)
1216 driver_name
= stringf("$lut%s", a_bit
.wire
->name
.c_str());
1218 driver_name
= stringf("$lut%s[%d]", a_bit
.wire
->name
.c_str(), a_bit
.offset
);
1219 driver_lut
= mapped_mod
->cell(driver_name
);
1223 // If a driver couldn't be found (could be from PI or box CI)
1224 // then implement using a LUT
1225 RTLIL::Cell
*cell
= module
->addLut(remap_name(stringf("$lut%s", mapped_cell
->name
.c_str())),
1226 RTLIL::SigBit(module
->wires_
.at(remap_name(a_bit
.wire
->name
)), a_bit
.offset
),
1227 RTLIL::SigBit(module
->wires_
.at(remap_name(y_bit
.wire
->name
)), y_bit
.offset
),
1228 RTLIL::Const::from_string("01"));
1229 bit2sinks
[cell
->getPort(ID::A
)].push_back(cell
);
1230 cell_stats
[ID($lut
)]++;
1233 not2drivers
[mapped_cell
] = driver_lut
;
1238 if (mapped_cell
->type
== ID($lut
)) {
1239 RTLIL::Cell
*cell
= module
->addCell(remap_name(mapped_cell
->name
), mapped_cell
->type
);
1240 cell
->parameters
= mapped_cell
->parameters
;
1241 cell
->attributes
= mapped_cell
->attributes
;
1243 for (auto &mapped_conn
: mapped_cell
->connections()) {
1244 RTLIL::SigSpec newsig
;
1245 for (auto c
: mapped_conn
.second
.chunks()) {
1248 //log_assert(c.width == 1);
1250 c
.wire
= module
->wires_
.at(remap_name(c
.wire
->name
));
1253 cell
->setPort(mapped_conn
.first
, newsig
);
1255 if (cell
->input(mapped_conn
.first
)) {
1256 for (auto i
: newsig
)
1257 bit2sinks
[i
].push_back(cell
);
1258 for (auto i
: mapped_conn
.second
)
1259 bit_users
[i
].insert(mapped_cell
->name
);
1261 if (cell
->output(mapped_conn
.first
))
1262 for (auto i
: mapped_conn
.second
)
1263 // Ignore inouts for topo ordering
1264 if (i
.wire
&& !(i
.wire
->port_input
&& i
.wire
->port_output
))
1265 bit_drivers
[i
].insert(mapped_cell
->name
);
1269 RTLIL::Cell
*existing_cell
= module
->cell(mapped_cell
->name
);
1271 log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell
));
1273 if (existing_cell
->type
.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) {
1274 SigBit I
= mapped_cell
->getPort(ID(i
));
1275 SigBit O
= mapped_cell
->getPort(ID(o
));
1277 I
.wire
= module
->wires_
.at(remap_name(I
.wire
->name
));
1279 O
.wire
= module
->wires_
.at(remap_name(O
.wire
->name
));
1280 module
->connect(O
, I
);
1284 RTLIL::Module
* box_module
= design
->module(existing_cell
->type
);
1285 log_assert(existing_cell
->parameters
.empty());
1286 log_assert(mapped_cell
->type
== stringf("$__boxid%d", box_module
->attributes
.at(ID::abc9_box_id
).as_int()));
1287 mapped_cell
->type
= existing_cell
->type
;
1289 RTLIL::Cell
*cell
= module
->addCell(remap_name(mapped_cell
->name
), mapped_cell
->type
);
1290 cell
->parameters
= existing_cell
->parameters
;
1291 cell
->attributes
= existing_cell
->attributes
;
1292 module
->swap_names(cell
, existing_cell
);
1294 auto jt
= mapped_cell
->connections_
.find(ID(i
));
1295 log_assert(jt
!= mapped_cell
->connections_
.end());
1296 SigSpec inputs
= std::move(jt
->second
);
1297 mapped_cell
->connections_
.erase(jt
);
1298 jt
= mapped_cell
->connections_
.find(ID(o
));
1299 log_assert(jt
!= mapped_cell
->connections_
.end());
1300 SigSpec outputs
= std::move(jt
->second
);
1301 mapped_cell
->connections_
.erase(jt
);
1303 auto abc9_flop
= box_module
->get_bool_attribute(ID::abc9_flop
);
1305 for (const auto &i
: inputs
)
1306 bit_users
[i
].insert(mapped_cell
->name
);
1307 for (const auto &i
: outputs
)
1308 // Ignore inouts for topo ordering
1309 if (i
.wire
&& !(i
.wire
->port_input
&& i
.wire
->port_output
))
1310 bit_drivers
[i
].insert(mapped_cell
->name
);
1313 int input_count
= 0, output_count
= 0;
1314 for (const auto &port_name
: box_ports
.at(existing_cell
->type
)) {
1315 RTLIL::Wire
*w
= box_module
->wire(port_name
);
1319 if (w
->port_input
) {
1320 sig
= inputs
.extract(input_count
, GetSize(w
));
1321 input_count
+= GetSize(w
);
1323 if (w
->port_output
) {
1324 sig
= outputs
.extract(output_count
, GetSize(w
));
1325 output_count
+= GetSize(w
);
1329 for (auto c
: sig
.chunks()) {
1332 //log_assert(c.width == 1);
1334 c
.wire
= module
->wires_
.at(remap_name(c
.wire
->name
));
1337 cell
->setPort(port_name
, newsig
);
1339 if (w
->port_input
&& !abc9_flop
)
1340 for (const auto &i
: newsig
)
1341 bit2sinks
[i
].push_back(cell
);
1345 cell_stats
[mapped_cell
->type
]++;
1348 for (auto cell
: boxes
)
1349 module
->remove(cell
);
1351 // Copy connections (and rename) from mapped_mod to module
1352 for (auto conn
: mapped_mod
->connections()) {
1353 if (!conn
.first
.is_fully_const()) {
1354 auto chunks
= conn
.first
.chunks();
1355 for (auto &c
: chunks
)
1356 c
.wire
= module
->wires_
.at(remap_name(c
.wire
->name
));
1357 conn
.first
= std::move(chunks
);
1359 if (!conn
.second
.is_fully_const()) {
1360 auto chunks
= conn
.second
.chunks();
1361 for (auto &c
: chunks
)
1363 c
.wire
= module
->wires_
.at(remap_name(c
.wire
->name
));
1364 conn
.second
= std::move(chunks
);
1366 module
->connect(conn
);
1369 for (auto &it
: cell_stats
)
1370 log("ABC RESULTS: %15s cells: %8d\n", it
.first
.c_str(), it
.second
);
1371 int in_wires
= 0, out_wires
= 0;
1373 // Stitch in mapped_mod's inputs/outputs into module
1374 for (auto port
: mapped_mod
->ports
) {
1375 RTLIL::Wire
*mapped_wire
= mapped_mod
->wire(port
);
1376 RTLIL::Wire
*wire
= module
->wire(port
);
1378 wire
->attributes
.erase(ID::abc9_keep
);
1380 RTLIL::Wire
*remap_wire
= module
->wire(remap_name(port
));
1381 RTLIL::SigSpec
signal(wire
, remap_wire
->start_offset
-wire
->start_offset
, GetSize(remap_wire
));
1382 log_assert(GetSize(signal
) >= GetSize(remap_wire
));
1385 if (mapped_wire
->port_output
) {
1386 conn
.first
= signal
;
1387 conn
.second
= remap_wire
;
1389 module
->connect(conn
);
1391 else if (mapped_wire
->port_input
) {
1392 conn
.first
= remap_wire
;
1393 conn
.second
= signal
;
1395 module
->connect(conn
);
1399 // ABC9 will return $_NOT_ gates in its mapping (since they are
1400 // treated as being "free"), in particular driving primary
1401 // outputs (real primary outputs, or cells treated as blackboxes)
1402 // or driving box inputs.
1403 // Instead of just mapping those $_NOT_ gates into 2-input $lut-s
1404 // at an area and delay cost, see if it is possible to push
1405 // this $_NOT_ into the driving LUT, or into all sink LUTs.
1406 // When this is not possible, (i.e. this signal drives two primary
1407 // outputs, only one of which is complemented) and when the driver
1408 // is a LUT, then clone the LUT so that it can be inverted without
1409 // increasing depth/delay.
1410 for (auto &it
: bit_users
)
1411 if (bit_drivers
.count(it
.first
))
1412 for (auto driver_cell
: bit_drivers
.at(it
.first
))
1413 for (auto user_cell
: it
.second
)
1414 toposort
.edge(driver_cell
, user_cell
);
1415 bool no_loops
YS_ATTRIBUTE(unused
) = toposort
.sort();
1416 log_assert(no_loops
);
1418 for (auto ii
= toposort
.sorted
.rbegin(); ii
!= toposort
.sorted
.rend(); ii
++) {
1419 RTLIL::Cell
*not_cell
= mapped_mod
->cell(*ii
);
1420 log_assert(not_cell
);
1421 if (not_cell
->type
!= ID($_NOT_
))
1423 auto it
= not2drivers
.find(not_cell
);
1424 if (it
== not2drivers
.end())
1426 RTLIL::Cell
*driver_lut
= it
->second
;
1427 RTLIL::SigBit a_bit
= not_cell
->getPort(ID::A
);
1428 RTLIL::SigBit y_bit
= not_cell
->getPort(ID::Y
);
1429 RTLIL::Const driver_mask
;
1431 a_bit
.wire
= module
->wires_
.at(remap_name(a_bit
.wire
->name
));
1432 y_bit
.wire
= module
->wires_
.at(remap_name(y_bit
.wire
->name
));
1434 auto jt
= bit2sinks
.find(a_bit
);
1435 if (jt
== bit2sinks
.end())
1438 for (auto sink_cell
: jt
->second
)
1439 if (sink_cell
->type
!= ID($lut
))
1442 // Push downstream LUTs past inverter
1443 for (auto sink_cell
: jt
->second
) {
1444 SigSpec A
= sink_cell
->getPort(ID::A
);
1445 RTLIL::Const mask
= sink_cell
->getParam(ID::LUT
);
1447 for (; index
< GetSize(A
); index
++)
1448 if (A
[index
] == a_bit
)
1450 log_assert(index
< GetSize(A
));
1452 while (i
< GetSize(mask
)) {
1453 for (int j
= 0; j
< (1 << index
); j
++)
1454 std::swap(mask
[i
+j
], mask
[i
+j
+(1 << index
)]);
1455 i
+= 1 << (index
+1);
1458 sink_cell
->setPort(ID::A
, A
);
1459 sink_cell
->setParam(ID::LUT
, mask
);
1462 // Since we have rewritten all sinks (which we know
1463 // to be only LUTs) to be after the inverter, we can
1464 // go ahead and clone the LUT with the expectation
1465 // that the original driving LUT will become dangling
1466 // and get cleaned away
1468 driver_mask
= driver_lut
->getParam(ID::LUT
);
1469 for (auto &b
: driver_mask
.bits
) {
1470 if (b
== RTLIL::State::S0
) b
= RTLIL::State::S1
;
1471 else if (b
== RTLIL::State::S1
) b
= RTLIL::State::S0
;
1473 auto cell
= module
->addLut(NEW_ID
,
1474 driver_lut
->getPort(ID::A
),
1477 for (auto &bit
: cell
->connections_
.at(ID::A
)) {
1478 bit
.wire
= module
->wires_
.at(remap_name(bit
.wire
->name
));
1479 bit2sinks
[bit
].push_back(cell
);
1483 //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);
1484 log("ABC RESULTS: input signals: %8d\n", in_wires
);
1485 log("ABC RESULTS: output signals: %8d\n", out_wires
);
1487 design
->remove(mapped_mod
);
1490 struct Abc9OpsPass
: public Pass
{
1491 Abc9OpsPass() : Pass("abc9_ops", "helper functions for ABC9") { }
1492 void help() YS_OVERRIDE
1494 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
1496 log(" abc9_ops [options] [selection]\n");
1498 log("This pass contains a set of supporting operations for use during ABC technology\n");
1499 log("mapping, and is expected to be called in conjunction with other operations from\n");
1500 log("the `abc9' script pass. Only fully-selected modules are supported.\n");
1503 log(" check that the design is valid, e.g. (* abc9_box_id *) values are unique,\n");
1504 log(" (* abc9_carry *) is only given for one input/output port, etc.\n");
1506 log(" -prep_hier\n");
1507 log(" derive all used (* abc9_box *) or (* abc9_flop *) (if -dff option)\n");
1508 log(" whitebox modules. with (* abc9_flop *) modules, only those containing\n");
1509 log(" $dff/$_DFF_[NP]_ cells with zero initial state -- due to an ABC limitation\n");
1510 log(" -- will be derived.\n");
1512 log(" -prep_bypass\n");
1513 log(" create techmap rules in the '$abc9_map' and '$abc9_unmap' designs for\n");
1514 log(" bypassing sequential (* abc9_box *) modules using a combinatorial box\n");
1515 log(" (named *_$abc9_byp). bypassing is necessary if sequential elements (e.g.\n");
1516 log(" $dff, $mem, etc.) are discovered inside so that any combinatorial paths\n");
1517 log(" will be correctly captured. this bypass box will only contain ports that\n");
1518 log(" are referenced by a simple path declaration ($specify2 cell) inside a\n");
1519 log(" specify block.\n");
1521 log(" -prep_dff\n");
1522 log(" select all (* abc9_flop *) modules instantiated in the design and store\n");
1523 log(" in the named selection '$abc9_flops'.\n");
1525 log(" -prep_dff_submod\n");
1526 log(" within (* abc9_flop *) modules, rewrite all edge-sensitive path\n");
1527 log(" declarations and $setup() timing checks ($specify3 and $specrule cells)\n");
1528 log(" that share a 'DST' port with the $_DFF_[NP]_.Q port from this 'Q' port to\n");
1529 log(" the DFF's 'D' port. this is to prepare such specify cells to be moved\n");
1530 log(" into the flop box.\n");
1532 log(" -prep_dff_unmap\n");
1533 log(" populate the '$abc9_unmap' design with techmap rules for mapping *_$abc9_flop\n");
1534 log(" cells back into their derived cell types (where the rules created by\n");
1535 log(" -prep_hier will then map back to the original cell with parameters).\n");
1537 log(" -prep_delays\n");
1538 log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n");
1539 log(" certain required times.\n");
1541 log(" -mark_scc\n");
1542 log(" for an arbitrarily chosen cell in each unique SCC of each selected module\n");
1543 log(" (tagged with an (* abc9_scc_id = <int> *) attribute), temporarily mark all\n");
1544 log(" wires driven by this cell's outputs with a (* keep *) attribute in order\n");
1545 log(" to break the SCC. this temporary attribute will be removed on -reintegrate.\n");
1547 log(" -prep_xaiger\n");
1548 log(" prepare the design for XAIGER output. this includes computing the\n");
1549 log(" topological ordering of ABC9 boxes, as well as preparing the '$abc9_holes'\n");
1550 log(" design that contains the logic behaviour of ABC9 whiteboxes.\n");
1553 log(" consider flop cells (those instantiating modules marked with (* abc9_flop *))\n");
1554 log(" during -prep_{delays,xaiger,box}.\n");
1556 log(" -prep_lut <maxlut>\n");
1557 log(" pre-compute the lut library by analysing all modules marked with\n");
1558 log(" (* abc9_lut=<area> *).\n");
1560 log(" -write_lut <dst>\n");
1561 log(" write the pre-computed lut library to <dst>.\n");
1563 log(" -prep_box\n");
1564 log(" pre-compute the box library by analysing all modules marked with\n");
1565 log(" (* abc9_box *).\n");
1567 log(" -write_box <dst>\n");
1568 log(" write the pre-computed box library to <dst>.\n");
1570 log(" -reintegrate\n");
1571 log(" for each selected module, re-intergrate the module '<module-name>$abc9'\n");
1572 log(" by first recovering ABC9 boxes, and then stitching in the remaining primary\n");
1573 log(" inputs and outputs.\n");
1576 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
1578 log_header(design
, "Executing ABC9_OPS pass (helper functions for ABC9).\n");
1580 bool check_mode
= false;
1581 bool prep_delays_mode
= false;
1582 bool mark_scc_mode
= false;
1583 bool prep_hier_mode
= false;
1584 bool prep_bypass_mode
= false;
1585 bool prep_dff_mode
= false, prep_dff_submod_mode
= false, prep_dff_unmap_mode
= false;
1586 bool prep_xaiger_mode
= false;
1587 bool prep_lut_mode
= false;
1588 bool prep_box_mode
= false;
1589 bool reintegrate_mode
= false;
1590 bool dff_mode
= false;
1591 std::string write_lut_dst
;
1593 std::string write_box_dst
;
1597 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
1598 std::string arg
= args
[argidx
];
1599 if (arg
== "-check") {
1604 if (arg
== "-mark_scc") {
1605 mark_scc_mode
= true;
1609 if (arg
== "-prep_hier") {
1610 prep_hier_mode
= true;
1614 if (arg
== "-prep_bypass") {
1615 prep_bypass_mode
= true;
1619 if (arg
== "-prep_dff") {
1620 prep_dff_mode
= true;
1624 if (arg
== "-prep_dff_submod") {
1625 prep_dff_submod_mode
= true;
1629 if (arg
== "-prep_dff_unmap") {
1630 prep_dff_unmap_mode
= true;
1634 if (arg
== "-prep_xaiger") {
1635 prep_xaiger_mode
= true;
1639 if (arg
== "-prep_delays") {
1640 prep_delays_mode
= true;
1644 if (arg
== "-prep_lut" && argidx
+1 < args
.size()) {
1645 prep_lut_mode
= true;
1646 maxlut
= atoi(args
[++argidx
].c_str());
1650 if (arg
== "-write_lut" && argidx
+1 < args
.size()) {
1651 write_lut_dst
= args
[++argidx
];
1652 rewrite_filename(write_lut_dst
);
1656 if (arg
== "-prep_box") {
1657 prep_box_mode
= true;
1661 if (arg
== "-write_box" && argidx
+1 < args
.size()) {
1662 write_box_dst
= args
[++argidx
];
1663 rewrite_filename(write_box_dst
);
1667 if (arg
== "-reintegrate") {
1668 reintegrate_mode
= true;
1672 if (arg
== "-dff") {
1678 extra_args(args
, argidx
, design
);
1681 log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n");
1683 if (dff_mode
&& !check_mode
&& !prep_hier_mode
&& !prep_delays_mode
&& !prep_xaiger_mode
&& !reintegrate_mode
)
1684 log_cmd_error("'-dff' option is only relevant for -prep_{hier,delay,xaiger} or -reintegrate.\n");
1687 check(design
, dff_mode
);
1689 prep_hier(design
, dff_mode
);
1690 if (prep_bypass_mode
)
1691 prep_bypass(design
);
1694 if (prep_dff_submod_mode
)
1695 prep_dff_submod(design
);
1696 if (prep_dff_unmap_mode
)
1697 prep_dff_unmap(design
);
1698 if (prep_delays_mode
)
1699 prep_delays(design
, dff_mode
);
1701 prep_lut(design
, maxlut
);
1705 for (auto mod
: design
->selected_modules()) {
1706 if (mod
->processes
.size() > 0) {
1707 log("Skipping module %s as it contains processes.\n", log_id(mod
));
1711 if (!design
->selected_whole_module(mod
))
1712 log_error("Can't handle partially selected module %s!\n", log_id(mod
));
1714 if (!write_lut_dst
.empty())
1715 write_lut(mod
, write_lut_dst
);
1716 if (!write_box_dst
.empty())
1717 write_box(mod
, write_box_dst
);
1720 if (prep_xaiger_mode
)
1721 prep_xaiger(mod
, dff_mode
);
1722 if (reintegrate_mode
)
1723 reintegrate(mod
, dff_mode
);
1728 PRIVATE_NAMESPACE_END