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"
26 #define ABC9_FLOPS_BASE_ID 8000
27 #define ABC9_DELAY_BASE_ID 9000
30 PRIVATE_NAMESPACE_BEGIN
34 inline std::string
remap_name(RTLIL::IdString abc9_name
)
36 return stringf("$abc$%d$%s", map_autoidx
, abc9_name
.c_str()+1);
39 void check(RTLIL::Design
*design
)
41 dict
<IdString
,IdString
> box_lookup
;
42 for (auto m
: design
->modules()) {
43 if (m
->name
.begins_with("$paramod"))
46 auto flop
= m
->get_bool_attribute(ID(abc9_flop
));
47 auto it
= m
->attributes
.find(ID(abc9_box_id
));
49 if (it
== m
->attributes
.end())
51 auto id
= it
->second
.as_int();
52 auto r
= box_lookup
.insert(std::make_pair(stringf("$__boxid%d", id
), m
->name
));
54 log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n",
55 log_id(m
), id
, log_id(r
.first
->second
));
58 // Make carry in the last PI, and carry out the last PO
59 // since ABC requires it this way
60 IdString carry_in
, carry_out
;
61 for (const auto &port_name
: m
->ports
) {
62 auto w
= m
->wire(port_name
);
64 if (w
->get_bool_attribute("\\abc9_carry")) {
66 if (carry_in
!= IdString())
67 log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", log_id(m
));
71 if (carry_out
!= IdString())
72 log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", log_id(m
));
73 carry_out
= port_name
;
77 auto it
= w
->attributes
.find("\\abc9_arrival");
78 if (it
!= w
->attributes
.end()) {
80 if (it
->second
.flags
== 0) {
81 if (it
->second
.as_int() < 0)
82 log_error("%s.%s has negative arrival value %d!\n", log_id(m
), log_id(port_name
),
87 for (const auto &tok
: split_tokens(it
->second
.decode_string())) {
88 if (tok
.find_first_not_of("0123456789") != std::string::npos
)
89 log_error("%s.%s has non-integer arrival value '%s'!\n", log_id(m
), log_id(port_name
),
91 if (atoi(tok
.c_str()) < 0)
92 log_error("%s.%s has negative arrival value %s!\n", log_id(m
), log_id(port_name
),
96 if (count
> 1 && count
!= GetSize(w
))
97 log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(m
), log_id(port_name
),
98 GetSize(w
), log_signal(it
->second
), count
);
101 it
= w
->attributes
.find("\\abc9_required");
102 if (it
!= w
->attributes
.end()) {
104 if (it
->second
.flags
== 0) {
105 if (it
->second
.as_int() < 0)
106 log_error("%s.%s has negative required value %d!\n", log_id(m
), log_id(port_name
),
107 it
->second
.as_int());
111 for (const auto &tok
: split_tokens(it
->second
.decode_string())) {
112 if (tok
.find_first_not_of("0123456789") != std::string::npos
)
113 log_error("%s.%s has non-integer required value '%s'!\n", log_id(m
), log_id(port_name
),
115 if (atoi(tok
.c_str()) < 0)
116 log_error("%s.%s has negative required value %s!\n", log_id(m
), log_id(port_name
),
120 if (count
> 1 && count
!= GetSize(w
))
121 log_error("%s.%s is %d bits wide but abc9_required = %s has %d value(s)!\n", log_id(m
), log_id(port_name
),
122 GetSize(w
), log_signal(it
->second
), count
);
126 if (carry_in
!= IdString() && carry_out
== IdString())
127 log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", log_id(m
));
128 if (carry_in
== IdString() && carry_out
!= IdString())
129 log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", log_id(m
));
133 for (auto port_name
: m
->ports
) {
134 auto wire
= m
->wire(port_name
);
135 if (wire
->port_output
) num_outputs
++;
137 if (num_outputs
!= 1)
138 log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", log_id(m
), num_outputs
);
143 void mark_scc(RTLIL::Module
*module
)
145 // For every unique SCC found, (arbitrarily) find the first
146 // cell in the component, and convert all wires driven by
147 // its output ports into a new PO, and drive its previous
148 // sinks with a new PI
149 pool
<RTLIL::Const
> ids_seen
;
150 for (auto cell
: module
->cells()) {
151 auto it
= cell
->attributes
.find(ID(abc9_scc_id
));
152 if (it
== cell
->attributes
.end())
154 auto id
= it
->second
;
155 auto r
= ids_seen
.insert(id
);
156 cell
->attributes
.erase(it
);
159 for (auto &c
: cell
->connections_
) {
160 if (c
.second
.is_fully_const()) continue;
161 if (cell
->output(c
.first
)) {
162 SigBit b
= c
.second
.as_bit();
164 w
->set_bool_attribute(ID::keep
);
165 w
->attributes
[ID(abc9_scc_id
)] = id
.as_int();
170 module
->fixup_ports();
173 void prep_dff(RTLIL::Module
*module
)
175 auto design
= module
->design
;
178 SigMap
assign_map(module
);
180 typedef SigSpec clkdomain_t
;
181 dict
<clkdomain_t
, int> clk_to_mergeability
;
183 for (auto cell
: module
->cells()) {
184 if (cell
->type
!= "$__ABC9_FF_")
187 Wire
*abc9_clock_wire
= module
->wire(stringf("%s.clock", cell
->name
.c_str()));
188 if (abc9_clock_wire
== NULL
)
189 log_error("'%s.clock' is not a wire present in module '%s'.\n", cell
->name
.c_str(), log_id(module
));
190 SigSpec abc9_clock
= assign_map(abc9_clock_wire
);
192 clkdomain_t
key(abc9_clock
);
194 auto r
= clk_to_mergeability
.insert(std::make_pair(abc9_clock
, clk_to_mergeability
.size() + 1));
195 auto r2
= cell
->attributes
.insert(ID(abc9_mergeability
));;
196 log_assert(r2
.second
);
197 r2
.first
->second
= r
.first
->second
;
200 RTLIL::Module
*holes_module
= design
->module(stringf("%s$holes", module
->name
.c_str()));
202 SigMap
sigmap(holes_module
);
204 dict
<SigSpec
, SigSpec
> replace
;
205 for (auto cell
: holes_module
->cells().to_vector()) {
206 if (!cell
->type
.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
207 "$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_"))
209 SigBit D
= cell
->getPort("\\D");
210 SigBit Q
= cell
->getPort("\\Q");
211 // Emulate async control embedded inside $_DFF_* cell with mux in front of D
212 if (cell
->type
.in("$_DFF_NN0_", "$_DFF_PN0_"))
213 D
= holes_module
->MuxGate(NEW_ID
, State::S0
, D
, cell
->getPort("\\R"));
214 else if (cell
->type
.in("$_DFF_NN1_", "$_DFF_PN1_"))
215 D
= holes_module
->MuxGate(NEW_ID
, State::S1
, D
, cell
->getPort("\\R"));
216 else if (cell
->type
.in("$_DFF_NP0_", "$_DFF_PP0_"))
217 D
= holes_module
->MuxGate(NEW_ID
, D
, State::S0
, cell
->getPort("\\R"));
218 else if (cell
->type
.in("$_DFF_NP1_", "$_DFF_PP1_"))
219 D
= holes_module
->MuxGate(NEW_ID
, D
, State::S1
, cell
->getPort("\\R"));
220 // Remove the $_DFF_* cell from what needs to be a combinatorial box
221 holes_module
->remove(cell
);
223 if (GetSize(Q
.wire
) == 1)
224 port
= holes_module
->wire(stringf("$abc%s", Q
.wire
->name
.c_str()));
226 port
= holes_module
->wire(stringf("$abc%s[%d]", Q
.wire
->name
.c_str(), Q
.offset
));
228 // Prepare to replace "assign <port> = $_DFF_*.Q;" with "assign <port> = $_DFF_*.D;"
229 // in order to extract just the combinatorial control logic that feeds the box
230 // (i.e. clock enable, synchronous reset, etc.)
231 replace
.insert(std::make_pair(Q
,D
));
232 // Since `flatten` above would have created wires named "<cell>.Q",
233 // extract the pre-techmap cell name
234 auto pos
= Q
.wire
->name
.str().rfind(".");
235 log_assert(pos
!= std::string::npos
);
236 IdString driver
= Q
.wire
->name
.substr(0, pos
);
237 // And drive the signal that was previously driven by "DFF.Q" (typically
238 // used to implement clock-enable functionality) with the "<cell>.$abc9_currQ"
239 // wire (which itself is driven an by input port) we inserted above
240 Wire
*currQ
= holes_module
->wire(stringf("%s.abc9_ff.Q", driver
.c_str()));
242 holes_module
->connect(Q
, currQ
);
245 for (auto &conn
: holes_module
->connections_
)
246 conn
.second
= replace
.at(sigmap(conn
.second
), conn
.second
);
250 void prep_xaiger(RTLIL::Module
*module
, bool dff
)
252 auto design
= module
->design
;
255 SigMap
sigmap(module
);
257 dict
<SigBit
, pool
<IdString
>> bit_drivers
, bit_users
;
258 TopoSort
<IdString
, RTLIL::sort_by_id_str
> toposort
;
259 dict
<IdString
, std::vector
<IdString
>> box_ports
;
261 for (auto cell
: module
->cells()) {
262 if (cell
->type
== "$__ABC9_FF_")
264 if (cell
->has_keep_attr())
267 auto inst_module
= module
->design
->module(cell
->type
);
268 bool abc9_flop
= inst_module
&& inst_module
->get_bool_attribute("\\abc9_flop");
269 if (abc9_flop
&& !dff
)
272 if ((inst_module
&& inst_module
->attributes
.count("\\abc9_box_id")) || abc9_flop
) {
273 auto r
= box_ports
.insert(cell
->type
);
275 // Make carry in the last PI, and carry out the last PO
276 // since ABC requires it this way
277 IdString carry_in
, carry_out
;
278 for (const auto &port_name
: inst_module
->ports
) {
279 auto w
= inst_module
->wire(port_name
);
281 if (w
->get_bool_attribute("\\abc9_carry")) {
282 log_assert(w
->port_input
!= w
->port_output
);
284 carry_in
= port_name
;
285 else if (w
->port_output
)
286 carry_out
= port_name
;
289 r
.first
->second
.push_back(port_name
);
291 if (carry_in
!= IdString()) {
292 r
.first
->second
.push_back(carry_in
);
293 r
.first
->second
.push_back(carry_out
);
297 else if (!yosys_celltypes
.cell_known(cell
->type
))
300 // TODO: Speed up toposort -- we care about box ordering only
301 for (auto conn
: cell
->connections()) {
302 if (cell
->input(conn
.first
))
303 for (auto bit
: sigmap(conn
.second
))
304 bit_users
[bit
].insert(cell
->name
);
306 if (cell
->output(conn
.first
) && !abc9_flop
)
307 for (auto bit
: sigmap(conn
.second
))
308 bit_drivers
[bit
].insert(cell
->name
);
310 toposort
.node(cell
->name
);
313 if (box_ports
.empty())
316 for (auto &it
: bit_users
)
317 if (bit_drivers
.count(it
.first
))
318 for (auto driver_cell
: bit_drivers
.at(it
.first
))
319 for (auto user_cell
: it
.second
)
320 toposort
.edge(driver_cell
, user_cell
);
323 toposort
.analyze_loops
= true;
325 bool no_loops
YS_ATTRIBUTE(unused
) = toposort
.sort();
329 for (auto &it
: toposort
.loops
) {
330 log(" loop %d\n", i
++);
331 for (auto cell_name
: it
) {
332 auto cell
= module
->cell(cell_name
);
334 log("\t%s (%s @ %s)\n", log_id(cell
), log_id(cell
->type
), cell
->get_src_attribute().c_str());
339 log_assert(no_loops
);
341 RTLIL::Module
*holes_module
= design
->addModule(stringf("%s$holes", module
->name
.c_str()));
342 log_assert(holes_module
);
343 holes_module
->set_bool_attribute("\\abc9_holes");
345 dict
<IdString
, Cell
*> cell_cache
;
347 int port_id
= 1, box_count
= 0;
348 for (auto cell_name
: toposort
.sorted
) {
349 RTLIL::Cell
*cell
= module
->cell(cell_name
);
352 RTLIL::Module
* box_module
= design
->module(cell
->type
);
353 if (!box_module
|| (!box_module
->attributes
.count("\\abc9_box_id") && !box_module
->get_bool_attribute("\\abc9_flop")))
356 cell
->attributes
["\\abc9_box_seq"] = box_count
++;
358 IdString derived_type
= box_module
->derive(design
, cell
->parameters
);
359 box_module
= design
->module(derived_type
);
361 auto r
= cell_cache
.insert(derived_type
);
362 auto &holes_cell
= r
.first
->second
;
364 if (box_module
->has_processes())
365 Pass::call_on_module(design
, box_module
, "proc");
367 if (box_module
->get_bool_attribute("\\whitebox")) {
368 holes_cell
= holes_module
->addCell(cell
->name
, derived_type
);
370 if (box_module
->has_processes())
371 Pass::call_on_module(design
, box_module
, "proc");
374 for (auto port_name
: box_ports
.at(cell
->type
)) {
375 RTLIL::Wire
*w
= box_module
->wire(port_name
);
377 log_assert(!w
->port_input
|| !w
->port_output
);
378 auto &conn
= holes_cell
->connections_
[port_name
];
380 for (int i
= 0; i
< GetSize(w
); i
++) {
382 RTLIL::Wire
*holes_wire
= holes_module
->wire(stringf("\\i%d", box_inputs
));
384 holes_wire
= holes_module
->addWire(stringf("\\i%d", box_inputs
));
385 holes_wire
->port_input
= true;
386 holes_wire
->port_id
= port_id
++;
387 holes_module
->ports
.push_back(holes_wire
->name
);
389 conn
.append(holes_wire
);
392 else if (w
->port_output
)
393 conn
= holes_module
->addWire(stringf("%s.%s", derived_type
.c_str(), log_id(port_name
)), GetSize(w
));
396 // For flops only, create an extra 1-bit input that drives a new wire
397 // called "<cell>.abc9_ff.Q" that is used below
398 if (box_module
->get_bool_attribute("\\abc9_flop")) {
400 Wire
*holes_wire
= holes_module
->wire(stringf("\\i%d", box_inputs
));
402 holes_wire
= holes_module
->addWire(stringf("\\i%d", box_inputs
));
403 holes_wire
->port_input
= true;
404 holes_wire
->port_id
= port_id
++;
405 holes_module
->ports
.push_back(holes_wire
->name
);
407 Wire
*Q
= holes_module
->addWire(stringf("%s.abc9_ff.Q", cell
->name
.c_str()));
408 holes_module
->connect(Q
, holes_wire
);
411 else // box_module is a blackbox
412 log_assert(holes_cell
== nullptr);
415 for (auto port_name
: box_ports
.at(cell
->type
)) {
416 RTLIL::Wire
*w
= box_module
->wire(port_name
);
420 Wire
*holes_wire
= holes_module
->addWire(stringf("$abc%s.%s", cell
->name
.c_str(), log_id(port_name
)), GetSize(w
));
421 holes_wire
->port_output
= true;
422 holes_wire
->port_id
= port_id
++;
423 holes_module
->ports
.push_back(holes_wire
->name
);
424 if (holes_cell
) // whitebox
425 holes_module
->connect(holes_wire
, holes_cell
->getPort(port_name
));
427 holes_module
->connect(holes_wire
, Const(State::S0
, GetSize(w
)));
432 void prep_delays(RTLIL::Design
*design
)
434 std::set
<int> delays
;
436 std::vector
<Cell
*> cells
;
437 dict
<IdString
,dict
<IdString
,std::vector
<int>>> requireds_cache
;
438 for (auto module
: design
->selected_modules()) {
439 if (module
->processes
.size() > 0) {
440 log("Skipping module %s as it contains processes.\n", log_id(module
));
445 for (auto cell
: module
->cells()) {
446 if (cell
->type
.in(ID($_AND_
), ID($_NOT_
), ID($__ABC9_FF_
), ID($__ABC9_DELAY
)))
449 RTLIL::Module
* inst_module
= module
->design
->module(cell
->type
);
452 if (!inst_module
->get_blackbox_attribute())
454 if (inst_module
->get_bool_attribute(ID(abc9_flop
))) {
455 IdString derived_type
= inst_module
->derive(design
, cell
->parameters
);
456 inst_module
= design
->module(derived_type
);
457 log_assert(inst_module
);
458 flops
.insert(inst_module
);
459 continue; // because all flop required times
460 // will be captured in the flop box
462 if (inst_module
->attributes
.count(ID(abc9_box_id
)))
464 cells
.emplace_back(cell
);
467 for (auto cell
: cells
) {
468 RTLIL::Module
* inst_module
= module
->design
->module(cell
->type
);
469 log_assert(inst_module
);
470 auto &cell_requireds
= requireds_cache
[cell
->type
];
471 for (auto &conn
: cell
->connections_
) {
472 auto port_wire
= inst_module
->wire(conn
.first
);
473 if (!port_wire
->port_input
)
476 auto r
= cell_requireds
.insert(conn
.first
);
477 auto &requireds
= r
.first
->second
;
479 auto it
= port_wire
->attributes
.find("\\abc9_required");
480 if (it
== port_wire
->attributes
.end())
482 if (it
->second
.flags
== 0) {
483 int delay
= it
->second
.as_int();
484 delays
.insert(delay
);
485 requireds
.emplace_back(delay
);
488 for (const auto &tok
: split_tokens(it
->second
.decode_string())) {
489 int delay
= atoi(tok
.c_str());
490 delays
.insert(delay
);
491 requireds
.push_back(delay
);
495 if (requireds
.empty())
498 SigSpec O
= module
->addWire(NEW_ID
, GetSize(conn
.second
));
499 auto it
= requireds
.begin();
500 for (int i
= 0; i
< GetSize(conn
.second
); ++i
) {
503 static std::set
<std::pair
<IdString
,IdString
>> seen
;
504 if (seen
.emplace(cell
->type
, conn
.first
).second
) log("%s.%s abc9_required = %d\n", log_id(cell
->type
), log_id(conn
.first
), requireds
[i
]);
507 auto box
= module
->addCell(NEW_ID
, ID($__ABC9_DELAY
));
508 box
->setPort(ID(I
), conn
.second
[i
]);
509 box
->setPort(ID(O
), O
[i
]);
510 box
->setParam(ID(DELAY
), *it
);
511 if (requireds
.size() > 1)
513 conn
.second
[i
] = O
[i
];
519 int flops_id
= ABC9_FLOPS_BASE_ID
;
520 std::stringstream ss
;
521 for (auto flop_module
: flops
) {
522 int num_inputs
= 0, num_outputs
= 0;
523 for (auto port_name
: flop_module
->ports
) {
524 auto wire
= flop_module
->wire(port_name
);
525 if (wire
->port_input
) num_inputs
++;
526 if (wire
->port_output
) num_outputs
++;
528 log_assert(num_outputs
== 1);
530 auto r
= flop_module
->attributes
.insert(ID(abc9_box_id
));
532 r
.first
->second
= flops_id
++;
534 ss
<< log_id(flop_module
) << " " << r
.first
->second
.as_int();
535 ss
<< " 1 " << num_inputs
+1 << " " << num_outputs
<< std::endl
;
537 for (auto port_name
: flop_module
->ports
) {
538 auto wire
= flop_module
->wire(port_name
);
539 if (!wire
->port_input
)
545 ss
<< wire
->attributes
.at("\\abc9_required", 0).as_int();
547 // Last input is 'abc9_ff.Q'
548 ss
<< " 0" << std::endl
<< std::endl
;
550 design
->scratchpad_set_string("abc9_ops.box_library.flops", ss
.str());
553 for (const int d
: delays
) {
554 ss
<< "$__ABC9_DELAY@" << d
<< " " << ABC9_DELAY_BASE_ID
+ d
<< " 0 1 1" << std::endl
;
555 ss
<< d
<< std::endl
;
557 design
->scratchpad_set_string("abc9_ops.box_library.delays", ss
.str());
560 void prep_lut(RTLIL::Design
*design
, int maxlut
)
562 std::stringstream ss
;
563 std::vector
<std::pair
<int, std::string
>> table
;
564 for (auto module
: design
->modules()) {
565 auto it
= module
->attributes
.find(ID(abc9_lut
));
566 if (it
== module
->attributes
.end())
569 std::vector
<int> specify
;
570 for (auto cell
: module
->cells()) {
571 if (cell
->type
!= ID($specify2
))
573 log_assert(cell
->getParam(ID(SRC_WIDTH
)) == 1);
574 log_assert(cell
->getParam(ID(DST_WIDTH
)) == 1);
575 SigBit s
= cell
->getPort(ID(SRC
));
576 SigBit d
= cell
->getPort(ID(DST
));
577 log_assert(s
.wire
->port_input
);
578 log_assert(d
.wire
->port_output
);
583 int rise_max
= cell
->getParam(ID(T_RISE_MAX
)).as_int();
584 int fall_max
= cell
->getParam(ID(T_FALL_MAX
)).as_int();
585 specify
.push_back(std::max(rise_max
,fall_max
));
587 if (maxlut
&& GetSize(specify
) > maxlut
)
589 std::sort(specify
.begin(), specify
.end());
591 ss
<< "# " << module
->name
.str() << std::endl
;
592 ss
<< GetSize(specify
) << " " << it
->second
.as_int();
593 for (auto i
: specify
)
596 table
.emplace_back(GetSize(specify
), ss
.str());
598 // ABC expects ascending size
599 std::sort(table
.begin(), table
.end());
601 for (auto &i
: table
)
603 design
->scratchpad_set_string("abc9_ops.lut_library", ss
.str());
606 void write_lut(RTLIL::Module
*module
, const std::string
&dst
) {
607 std::ofstream
ofs(dst
);
608 log_assert(ofs
.is_open());
609 ofs
<< module
->design
->scratchpad_get_string("abc9_ops.lut_library");
613 void prep_box(RTLIL::Design
*design
, const std::string
&src
)
615 std::stringstream ss
;
617 // Since ABC can only accept one box file, we have to copy
618 // over the existing box file
619 if (src
!= "(null)") {
620 std::ifstream
ifs(src
);
621 log_assert(ifs
.is_open());
622 ss
<< ifs
.rdbuf() << std::endl
;
626 ss
<< design
->scratchpad_get_string("abc9_ops.box_library.flops", ss
.str());
627 ss
<< design
->scratchpad_get_string("abc9_ops.box_library.delays", ss
.str());
628 design
->scratchpad_set_string("abc9_ops.box_library", ss
.str());
631 void write_box(RTLIL::Module
*module
, const std::string
&dst
) {
632 std::ofstream
ofs(dst
);
633 log_assert(ofs
.is_open());
634 ofs
<< module
->design
->scratchpad_get_string("abc9_ops.box_library");
635 // ABC expects at least one box
636 if (ofs
.tellp() == 0)
637 ofs
<< "(dummy) 1 0 0 0";
641 void reintegrate(RTLIL::Module
*module
)
643 auto design
= module
->design
;
646 map_autoidx
= autoidx
++;
648 RTLIL::Module
*mapped_mod
= design
->module(stringf("%s$abc9", module
->name
.c_str()));
649 if (mapped_mod
== NULL
)
650 log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module
));
652 for (auto w
: mapped_mod
->wires())
653 module
->addWire(remap_name(w
->name
), GetSize(w
));
655 dict
<IdString
,std::vector
<IdString
>> box_ports
;
657 for (auto m
: design
->modules()) {
658 if (!m
->attributes
.count(ID(abc9_box_id
)))
661 auto r
= box_ports
.insert(m
->name
);
665 // Make carry in the last PI, and carry out the last PO
666 // since ABC requires it this way
667 IdString carry_in
, carry_out
;
668 for (const auto &port_name
: m
->ports
) {
669 auto w
= m
->wire(port_name
);
671 if (w
->get_bool_attribute("\\abc9_carry")) {
672 log_assert(w
->port_input
!= w
->port_output
);
674 carry_in
= port_name
;
675 else if (w
->port_output
)
676 carry_out
= port_name
;
679 r
.first
->second
.push_back(port_name
);
682 if (carry_in
!= IdString()) {
683 r
.first
->second
.push_back(carry_in
);
684 r
.first
->second
.push_back(carry_out
);
688 std::vector
<Cell
*> boxes
;
689 for (auto cell
: module
->cells().to_vector()) {
690 if (cell
->has_keep_attr())
692 if (cell
->type
.in(ID($_AND_
), ID($_NOT_
), ID($__ABC9_FF_
)))
693 module
->remove(cell
);
694 else if (cell
->attributes
.erase("\\abc9_box_seq"))
695 boxes
.emplace_back(cell
);
698 dict
<SigBit
, pool
<IdString
>> bit_drivers
, bit_users
;
699 TopoSort
<IdString
, RTLIL::sort_by_id_str
> toposort
;
700 dict
<RTLIL::Cell
*,RTLIL::Cell
*> not2drivers
;
701 dict
<SigBit
, std::vector
<RTLIL::Cell
*>> bit2sinks
;
703 std::map
<IdString
, int> cell_stats
;
704 for (auto mapped_cell
: mapped_mod
->cells())
706 // TODO: Speed up toposort -- we care about NOT ordering only
707 toposort
.node(mapped_cell
->name
);
709 if (mapped_cell
->type
== ID($_NOT_
)) {
710 RTLIL::SigBit a_bit
= mapped_cell
->getPort(ID::A
);
711 RTLIL::SigBit y_bit
= mapped_cell
->getPort(ID::Y
);
712 bit_users
[a_bit
].insert(mapped_cell
->name
);
713 // Ignore inouts for topo ordering
714 if (y_bit
.wire
&& !(y_bit
.wire
->port_input
&& y_bit
.wire
->port_output
))
715 bit_drivers
[y_bit
].insert(mapped_cell
->name
);
718 mapped_cell
->setPort(ID::Y
, module
->addWire(NEW_ID
));
719 RTLIL::Wire
*wire
= module
->wire(remap_name(y_bit
.wire
->name
));
721 module
->connect(RTLIL::SigBit(wire
, y_bit
.offset
), State::S1
);
724 RTLIL::Cell
* driver_lut
= nullptr;
725 // ABC can return NOT gates that drive POs
726 if (!a_bit
.wire
->port_input
) {
727 // If it's not a NOT gate that that comes from a PI directly,
728 // find the driver LUT and clone that to guarantee that we won't
729 // increase the max logic depth
730 // (TODO: Optimise by not cloning unless will increase depth)
731 RTLIL::IdString driver_name
;
732 if (GetSize(a_bit
.wire
) == 1)
733 driver_name
= stringf("$lut%s", a_bit
.wire
->name
.c_str());
735 driver_name
= stringf("$lut%s[%d]", a_bit
.wire
->name
.c_str(), a_bit
.offset
);
736 driver_lut
= mapped_mod
->cell(driver_name
);
740 // If a driver couldn't be found (could be from PI or box CI)
741 // then implement using a LUT
742 RTLIL::Cell
*cell
= module
->addLut(remap_name(stringf("$lut%s", mapped_cell
->name
.c_str())),
743 RTLIL::SigBit(module
->wires_
.at(remap_name(a_bit
.wire
->name
)), a_bit
.offset
),
744 RTLIL::SigBit(module
->wires_
.at(remap_name(y_bit
.wire
->name
)), y_bit
.offset
),
745 RTLIL::Const::from_string("01"));
746 bit2sinks
[cell
->getPort(ID::A
)].push_back(cell
);
747 cell_stats
[ID($lut
)]++;
750 not2drivers
[mapped_cell
] = driver_lut
;
755 if (mapped_cell
->type
.in(ID($lut
), ID($__ABC9_FF_
))) {
756 RTLIL::Cell
*cell
= module
->addCell(remap_name(mapped_cell
->name
), mapped_cell
->type
);
757 cell
->parameters
= mapped_cell
->parameters
;
758 cell
->attributes
= mapped_cell
->attributes
;
760 for (auto &mapped_conn
: mapped_cell
->connections()) {
761 RTLIL::SigSpec newsig
;
762 for (auto c
: mapped_conn
.second
.chunks()) {
765 //log_assert(c.width == 1);
767 c
.wire
= module
->wires_
.at(remap_name(c
.wire
->name
));
770 cell
->setPort(mapped_conn
.first
, newsig
);
772 if (cell
->input(mapped_conn
.first
)) {
773 for (auto i
: newsig
)
774 bit2sinks
[i
].push_back(cell
);
775 for (auto i
: mapped_conn
.second
)
776 bit_users
[i
].insert(mapped_cell
->name
);
778 if (cell
->output(mapped_conn
.first
))
779 for (auto i
: mapped_conn
.second
)
780 // Ignore inouts for topo ordering
781 if (i
.wire
&& !(i
.wire
->port_input
&& i
.wire
->port_output
))
782 bit_drivers
[i
].insert(mapped_cell
->name
);
786 RTLIL::Cell
*existing_cell
= module
->cell(mapped_cell
->name
);
788 log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell
));
790 if (existing_cell
->type
== ID($__ABC9_DELAY
)) {
791 SigBit I
= mapped_cell
->getPort(ID(i
));
792 SigBit O
= mapped_cell
->getPort(ID(o
));
794 I
.wire
= module
->wires_
.at(remap_name(I
.wire
->name
));
796 O
.wire
= module
->wires_
.at(remap_name(O
.wire
->name
));
797 module
->connect(O
, I
);
801 RTLIL::Module
* box_module
= design
->module(existing_cell
->type
);
802 IdString derived_type
= box_module
->derive(design
, existing_cell
->parameters
);
803 RTLIL::Module
* derived_module
= design
->module(derived_type
);
804 log_assert(derived_module
);
805 log_assert(mapped_cell
->type
== stringf("$__boxid%d", derived_module
->attributes
.at("\\abc9_box_id").as_int()));
806 mapped_cell
->type
= existing_cell
->type
;
808 RTLIL::Cell
*cell
= module
->addCell(remap_name(mapped_cell
->name
), mapped_cell
->type
);
809 cell
->parameters
= existing_cell
->parameters
;
810 cell
->attributes
= existing_cell
->attributes
;
811 module
->swap_names(cell
, existing_cell
);
813 auto jt
= mapped_cell
->connections_
.find("\\i");
814 log_assert(jt
!= mapped_cell
->connections_
.end());
815 SigSpec inputs
= std::move(jt
->second
);
816 mapped_cell
->connections_
.erase(jt
);
817 jt
= mapped_cell
->connections_
.find("\\o");
818 log_assert(jt
!= mapped_cell
->connections_
.end());
819 SigSpec outputs
= std::move(jt
->second
);
820 mapped_cell
->connections_
.erase(jt
);
822 auto abc9_flop
= box_module
->attributes
.count("\\abc9_flop");
824 for (const auto &i
: inputs
)
825 bit_users
[i
].insert(mapped_cell
->name
);
826 for (const auto &i
: outputs
)
827 // Ignore inouts for topo ordering
828 if (i
.wire
&& !(i
.wire
->port_input
&& i
.wire
->port_output
))
829 bit_drivers
[i
].insert(mapped_cell
->name
);
832 int input_count
= 0, output_count
= 0;
833 for (const auto &port_name
: box_ports
.at(derived_type
)) {
834 RTLIL::Wire
*w
= box_module
->wire(port_name
);
839 sig
= inputs
.extract(input_count
, GetSize(w
));
840 input_count
+= GetSize(w
);
842 if (w
->port_output
) {
843 sig
= outputs
.extract(output_count
, GetSize(w
));
844 output_count
+= GetSize(w
);
848 for (auto c
: sig
.chunks()) {
851 //log_assert(c.width == 1);
853 c
.wire
= module
->wires_
.at(remap_name(c
.wire
->name
));
856 cell
->setPort(port_name
, newsig
);
858 if (w
->port_input
&& !abc9_flop
)
859 for (const auto &i
: newsig
)
860 bit2sinks
[i
].push_back(cell
);
864 cell_stats
[mapped_cell
->type
]++;
867 for (auto cell
: boxes
)
868 module
->remove(cell
);
870 // Copy connections (and rename) from mapped_mod to module
871 for (auto conn
: mapped_mod
->connections()) {
872 if (!conn
.first
.is_fully_const()) {
873 auto chunks
= conn
.first
.chunks();
874 for (auto &c
: chunks
)
875 c
.wire
= module
->wires_
.at(remap_name(c
.wire
->name
));
876 conn
.first
= std::move(chunks
);
878 if (!conn
.second
.is_fully_const()) {
879 auto chunks
= conn
.second
.chunks();
880 for (auto &c
: chunks
)
882 c
.wire
= module
->wires_
.at(remap_name(c
.wire
->name
));
883 conn
.second
= std::move(chunks
);
885 module
->connect(conn
);
888 for (auto &it
: cell_stats
)
889 log("ABC RESULTS: %15s cells: %8d\n", it
.first
.c_str(), it
.second
);
890 int in_wires
= 0, out_wires
= 0;
892 // Stitch in mapped_mod's inputs/outputs into module
893 for (auto port
: mapped_mod
->ports
) {
894 RTLIL::Wire
*mapped_wire
= mapped_mod
->wire(port
);
895 RTLIL::Wire
*wire
= module
->wire(port
);
897 if (wire
->attributes
.erase(ID(abc9_scc_id
))) {
898 auto r
YS_ATTRIBUTE(unused
) = wire
->attributes
.erase(ID::keep
);
901 RTLIL::Wire
*remap_wire
= module
->wire(remap_name(port
));
902 RTLIL::SigSpec
signal(wire
, 0, GetSize(remap_wire
));
903 log_assert(GetSize(signal
) >= GetSize(remap_wire
));
906 if (mapped_wire
->port_output
) {
908 conn
.second
= remap_wire
;
910 module
->connect(conn
);
912 else if (mapped_wire
->port_input
) {
913 conn
.first
= remap_wire
;
914 conn
.second
= signal
;
916 module
->connect(conn
);
920 // ABC9 will return $_NOT_ gates in its mapping (since they are
921 // treated as being "free"), in particular driving primary
922 // outputs (real primary outputs, or cells treated as blackboxes)
923 // or driving box inputs.
924 // Instead of just mapping those $_NOT_ gates into 2-input $lut-s
925 // at an area and delay cost, see if it is possible to push
926 // this $_NOT_ into the driving LUT, or into all sink LUTs.
927 // When this is not possible, (i.e. this signal drives two primary
928 // outputs, only one of which is complemented) and when the driver
929 // is a LUT, then clone the LUT so that it can be inverted without
930 // increasing depth/delay.
931 for (auto &it
: bit_users
)
932 if (bit_drivers
.count(it
.first
))
933 for (auto driver_cell
: bit_drivers
.at(it
.first
))
934 for (auto user_cell
: it
.second
)
935 toposort
.edge(driver_cell
, user_cell
);
936 bool no_loops
YS_ATTRIBUTE(unused
) = toposort
.sort();
937 log_assert(no_loops
);
939 for (auto ii
= toposort
.sorted
.rbegin(); ii
!= toposort
.sorted
.rend(); ii
++) {
940 RTLIL::Cell
*not_cell
= mapped_mod
->cell(*ii
);
941 log_assert(not_cell
);
942 if (not_cell
->type
!= ID($_NOT_
))
944 auto it
= not2drivers
.find(not_cell
);
945 if (it
== not2drivers
.end())
947 RTLIL::Cell
*driver_lut
= it
->second
;
948 RTLIL::SigBit a_bit
= not_cell
->getPort(ID::A
);
949 RTLIL::SigBit y_bit
= not_cell
->getPort(ID::Y
);
950 RTLIL::Const driver_mask
;
952 a_bit
.wire
= module
->wires_
.at(remap_name(a_bit
.wire
->name
));
953 y_bit
.wire
= module
->wires_
.at(remap_name(y_bit
.wire
->name
));
955 auto jt
= bit2sinks
.find(a_bit
);
956 if (jt
== bit2sinks
.end())
959 for (auto sink_cell
: jt
->second
)
960 if (sink_cell
->type
!= ID($lut
))
963 // Push downstream LUTs past inverter
964 for (auto sink_cell
: jt
->second
) {
965 SigSpec A
= sink_cell
->getPort(ID::A
);
966 RTLIL::Const mask
= sink_cell
->getParam(ID(LUT
));
968 for (; index
< GetSize(A
); index
++)
969 if (A
[index
] == a_bit
)
971 log_assert(index
< GetSize(A
));
973 while (i
< GetSize(mask
)) {
974 for (int j
= 0; j
< (1 << index
); j
++)
975 std::swap(mask
[i
+j
], mask
[i
+j
+(1 << index
)]);
979 sink_cell
->setPort(ID::A
, A
);
980 sink_cell
->setParam(ID(LUT
), mask
);
983 // Since we have rewritten all sinks (which we know
984 // to be only LUTs) to be after the inverter, we can
985 // go ahead and clone the LUT with the expectation
986 // that the original driving LUT will become dangling
987 // and get cleaned away
989 driver_mask
= driver_lut
->getParam(ID(LUT
));
990 for (auto &b
: driver_mask
.bits
) {
991 if (b
== RTLIL::State::S0
) b
= RTLIL::State::S1
;
992 else if (b
== RTLIL::State::S1
) b
= RTLIL::State::S0
;
994 auto cell
= module
->addLut(NEW_ID
,
995 driver_lut
->getPort(ID::A
),
998 for (auto &bit
: cell
->connections_
.at(ID::A
)) {
999 bit
.wire
= module
->wires_
.at(remap_name(bit
.wire
->name
));
1000 bit2sinks
[bit
].push_back(cell
);
1004 //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);
1005 log("ABC RESULTS: input signals: %8d\n", in_wires
);
1006 log("ABC RESULTS: output signals: %8d\n", out_wires
);
1008 design
->remove(mapped_mod
);
1011 struct Abc9OpsPass
: public Pass
{
1012 Abc9OpsPass() : Pass("abc9_ops", "helper functions for ABC9") { }
1013 void help() YS_OVERRIDE
1015 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
1017 log(" abc9_ops [options] [selection]\n");
1019 log("This pass contains a set of supporting operations for use during ABC technology\n");
1020 log("mapping, and is expected to be called in conjunction with other operations from\n");
1021 log("the `abc9' script pass. Only fully-selected modules are supported.\n");
1024 log(" check that the design is valid, e.g. (* abc9_box_id *) values are unique,\n");
1025 log(" (* abc9_carry *) is only given for one input/output port, etc.\n");
1027 log(" -prep_delays\n");
1028 log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n");
1029 log(" certain delays, e.g. (* abc9_required *) values.\n");
1031 log(" -mark_scc\n");
1032 log(" for an arbitrarily chosen cell in each unique SCC of each selected module\n");
1033 log(" (tagged with an (* abc9_scc_id = <int> *) attribute), temporarily mark all\n");
1034 log(" wires driven by this cell's outputs with a (* keep *) attribute in order\n");
1035 log(" to break the SCC. this temporary attribute will be removed on -reintegrate.\n");
1037 log(" -prep_xaiger\n");
1038 log(" prepare the design for XAIGER output. this includes computing the\n");
1039 log(" topological ordering of ABC9 boxes, as well as preparing the\n");
1040 log(" '<module-name>$holes' module that contains the logic behaviour of ABC9\n");
1041 log(" whiteboxes.\n");
1044 log(" consider flop cells (those instantiating modules marked with (* abc9_flop *)\n");
1045 log(" during -prep_xaiger.\n");
1047 log(" -prep_dff\n");
1048 log(" compute the clock domain and initial value of each flop in the design.\n");
1049 log(" process the '$holes' module to support clock-enable functionality.\n");
1051 log(" -prep_lut <maxlut>\n");
1052 log(" pre-compute the lut library.\n");
1054 log(" -write_lut <dst>\n");
1055 log(" write the pre-computed lut library to <dst>.\n");
1057 log(" -prep_box <src>\n");
1058 log(" pre-compute the box library. copy the existing box file from <src> (skip\n");
1059 log(" if '(null)').\n");
1061 log(" -write_box <dst>\n");
1062 log(" write the pre-computed box library to <dst>.\n");
1064 log(" -reintegrate\n");
1065 log(" for each selected module, re-intergrate the module '<module-name>$abc9'\n");
1066 log(" by first recovering ABC9 boxes, and then stitching in the remaining primary\n");
1067 log(" inputs and outputs.\n");
1070 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
1072 log_header(design
, "Executing ABC9_OPS pass (helper functions for ABC9).\n");
1074 bool check_mode
= false;
1075 bool prep_delays_mode
= false;
1076 bool mark_scc_mode
= false;
1077 bool prep_dff_mode
= false;
1078 bool prep_xaiger_mode
= false;
1079 bool prep_lut_mode
= false;
1080 bool reintegrate_mode
= false;
1081 bool dff_mode
= false;
1082 std::string write_lut_dst
;
1084 std::string prep_box_src
, write_box_dst
;
1087 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
1088 std::string arg
= args
[argidx
];
1089 if (arg
== "-check") {
1093 if (arg
== "-mark_scc") {
1094 mark_scc_mode
= true;
1097 if (arg
== "-prep_dff") {
1098 prep_dff_mode
= true;
1101 if (arg
== "-prep_xaiger") {
1102 prep_xaiger_mode
= true;
1105 if (arg
== "-prep_delays") {
1106 prep_delays_mode
= true;
1109 if (arg
== "-prep_lut" && argidx
+1 < args
.size()) {
1110 prep_lut_mode
= true;
1111 maxlut
= atoi(args
[++argidx
].c_str());
1114 if (arg
== "-maxlut" && argidx
+1 < args
.size()) {
1117 if (arg
== "-write_lut" && argidx
+1 < args
.size()) {
1118 write_lut_dst
= args
[++argidx
];
1119 rewrite_filename(write_lut_dst
);
1122 if (arg
== "-prep_box" && argidx
+1 < args
.size()) {
1123 prep_box_src
= args
[++argidx
];
1124 rewrite_filename(prep_box_src
);
1127 if (arg
== "-write_box" && argidx
+1 < args
.size()) {
1128 write_box_dst
= args
[++argidx
];
1129 rewrite_filename(write_box_dst
);
1132 if (arg
== "-reintegrate") {
1133 reintegrate_mode
= true;
1136 if (arg
== "-dff") {
1142 extra_args(args
, argidx
, design
);
1144 if (!(check_mode
|| mark_scc_mode
|| prep_delays_mode
|| prep_xaiger_mode
|| prep_dff_mode
|| prep_lut_mode
|| !prep_box_src
.empty() || !write_lut_dst
.empty() || !write_box_dst
.empty() || reintegrate_mode
))
1145 log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff,lut,box}, -write_{lut,box}, -reintegrate must be specified.\n");
1147 if (dff_mode
&& !prep_xaiger_mode
)
1148 log_cmd_error("'-dff' option is only relevant for -prep_xaiger.\n");
1152 if (prep_delays_mode
)
1153 prep_delays(design
);
1155 prep_lut(design
, maxlut
);
1156 if (!prep_box_src
.empty())
1157 prep_box(design
, prep_box_src
);
1159 for (auto mod
: design
->selected_modules()) {
1160 if (mod
->get_bool_attribute("\\abc9_holes"))
1163 if (mod
->processes
.size() > 0) {
1164 log("Skipping module %s as it contains processes.\n", log_id(mod
));
1168 if (!design
->selected_whole_module(mod
))
1169 log_error("Can't handle partially selected module %s!\n", log_id(mod
));
1171 if (!write_lut_dst
.empty())
1172 write_lut(mod
, write_lut_dst
);
1173 if (!write_box_dst
.empty())
1174 write_box(mod
, write_box_dst
);
1179 if (prep_xaiger_mode
)
1180 prep_xaiger(mod
, dff_mode
);
1181 if (reintegrate_mode
)
1187 PRIVATE_NAMESPACE_END