From 315f8194a052129438305bc860303714415b8e4d Mon Sep 17 00:00:00 2001 From: nella Date: Mon, 21 Sep 2026 10:44:44 +0200 Subject: [PATCH 1/2] Don't mark cells w no unput as boxes. --- frontends/liberty/liberty.cc | 5 +++-- tests/abc_new/openroad/generate_mk.py | 14 +------------- tests/abc_new/openroad/tie_box.ys | 2 +- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index eb793ba2d..844df084f 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -575,7 +575,7 @@ struct LibertyFrontend : public Frontend { for (auto &attr : attributes) module->attributes[attr] = 1; - bool simple_comb_cell = true, has_outputs = false; + bool simple_comb_cell = true, has_inputs = false, has_outputs = false; for (auto node : cell->children) { @@ -693,6 +693,7 @@ struct LibertyFrontend : public Frontend { } if (dir && dir->value == "input") { + has_inputs = true; wire->port_input = true; continue; } @@ -736,7 +737,7 @@ struct LibertyFrontend : public Frontend { simple_comb_cell = false; } - if (simple_comb_cell && has_outputs && flag_unit_delay) { + if (simple_comb_cell && has_inputs && has_outputs && flag_unit_delay) { module->set_bool_attribute(ID::abc9_box); for (auto wi : module->wires()) diff --git a/tests/abc_new/openroad/generate_mk.py b/tests/abc_new/openroad/generate_mk.py index 8793c7e13..1b98b4391 100644 --- a/tests/abc_new/openroad/generate_mk.py +++ b/tests/abc_new/openroad/generate_mk.py @@ -3,18 +3,6 @@ import sys sys.path.append("../..") -import glob - import gen_tests_makefile -skip = [ - "tie_box.ys", -] - -def create_tests(): - for ys in sorted(glob.glob("*.ys")): - if ys in skip: - continue - gen_tests_makefile.generate_ys_test(ys) - -gen_tests_makefile.generate_custom(create_tests) +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/abc_new/openroad/tie_box.ys b/tests/abc_new/openroad/tie_box.ys index 15989bc45..2aaca56fb 100644 --- a/tests/abc_new/openroad/tie_box.ys +++ b/tests/abc_new/openroad/tie_box.ys @@ -1,6 +1,6 @@ # https://github.com/The-OpenROAD-Project/OpenROAD/blob/80443953721b0134bed51bbab17a633a575098a6/src/cut/test/sky130_const_cell.v -# input-less box (tie cell): abc asserts in Gia_ManLevelWithBoxes, same with abc9 -lut +# input-less cells are not abc9 boxes as abc cannot represent a box with no inputs read_verilog < Date: Mon, 21 Sep 2026 12:21:19 +0200 Subject: [PATCH 2/2] Reject abc9 boxes without an input or an output. --- passes/techmap/abc9_ops.cc | 29 +++++++++++++++++++++++------ tests/abc_new/box_no_input.ys | 15 +++++++++++++++ tests/abc_new/box_no_output.ys | 15 +++++++++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 tests/abc_new/box_no_input.ys create mode 100644 tests/abc_new/box_no_output.ys diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 21059c774..4faa981c3 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -33,23 +33,33 @@ void check(RTLIL::Design *design, bool dff_mode) dict box_lookup; for (auto m : design->modules()) { auto flop = m->get_bool_attribute(ID::abc9_flop); + auto box = m->get_bool_attribute(ID::abc9_box); auto it = m->attributes.find(ID::abc9_box_id); if (!flop) { - if (it == m->attributes.end()) + if (!box && it == m->attributes.end()) continue; - auto id = it->second.as_int(); - auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); - if (!r.second) - log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - m, id, r.first->second.unescape()); + if (it != m->attributes.end()) { + auto id = it->second.as_int(); + auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); + if (!r.second) + log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", + m, id, r.first->second.unescape()); + } } // Make carry in the last PI, and carry out the last PO // since ABC requires it this way IdString carry_in, carry_out; + bool has_input = false, has_output = false; for (const auto &port_name : m->ports) { auto w = m->wire(port_name); log_assert(w); + if (GetSize(w)) { + if (w->port_input) + has_input = true; + if (w->port_output) + has_output = true; + } if (w->get_bool_attribute(ID::abc9_carry)) { if (w->port_input) { if (carry_in != IdString()) @@ -69,6 +79,13 @@ void check(RTLIL::Design *design, bool dff_mode) if (carry_in == IdString() && carry_out != IdString()) log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", m); + // A timing arc spans an input to an output, so a box missing either + // carries no timing for abc to work with + if (!flop && !has_input) + log_error("Module '%s' with (* abc9_box *) has no input port.\n", m); + if (!flop && !has_output) + log_error("Module '%s' with (* abc9_box *) has no output port.\n", m); + if (flop) { int num_outputs = 0; for (auto port_name : m->ports) { diff --git a/tests/abc_new/box_no_input.ys b/tests/abc_new/box_no_input.ys new file mode 100644 index 000000000..b1f40ec3b --- /dev/null +++ b/tests/abc_new/box_no_input.ys @@ -0,0 +1,15 @@ +# an abc9 box needs an input, or it can carry no timing arcs +logger -expect error "has no input port" 1 +read_verilog -specify <