From d86d073ad657b5bc92b8ef020b79c070333f267f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 13 Dec 2019 10:26:30 -0800 Subject: [PATCH 1/4] Add testcase --- tests/opt/opt_merge_init.ys | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tests/opt/opt_merge_init.ys diff --git a/tests/opt/opt_merge_init.ys b/tests/opt/opt_merge_init.ys new file mode 100644 index 000000000..a29c29df6 --- /dev/null +++ b/tests/opt/opt_merge_init.ys @@ -0,0 +1,49 @@ +read_verilog -icells < Date: Fri, 13 Dec 2019 10:26:37 -0800 Subject: [PATCH 2/4] opt_merge to discard \init of '$' cells with 'Q' port when merging --- passes/opt/opt_merge.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index aaea6159e..643cf0215 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -323,6 +323,17 @@ struct OptMergeWorker log_signal(it.second), log_signal(other_sig)); module->connect(RTLIL::SigSig(it.second, other_sig)); assign_map.add(it.second, other_sig); + + if (cell->type.begins_with("$") && it.first == ID(Q)) { + for (auto c : it.second.chunks()) { + auto jt = c.wire->attributes.find(ID(init)); + if (jt == c.wire->attributes.end()) + continue; + for (int i = c.offset; i < c.offset + c.width; i++) + jt->second[i] = State::Sx; + } + dff_init_map.add(it.second, Const(State::Sx, GetSize(it.second))); + } } } log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); From d038cea3c7c5dd9f147c4da0e44de0e664df089f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Dec 2019 12:32:00 -0800 Subject: [PATCH 3/4] More stringent check for flop cells --- passes/opt/opt_merge.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 643cf0215..8dd238bc7 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -222,7 +222,8 @@ struct OptMergeWorker return true; } - if (cell1->type.begins_with("$") && conn1.count(ID(Q)) != 0) { + if (conn1.count(ID(Q)) != 0 && (cell1->type.begins_with("$dff") || cell1->type.begins_with("$dlatch") || cell1->type.in("$adff", "$sr", "$ff") || + cell1->type.begins_with("$_DFF") || cell1->type.begins_with("$_DLATCH"))) { std::vector q1 = dff_init_map(cell1->getPort(ID(Q))).to_sigbit_vector(); std::vector q2 = dff_init_map(cell2->getPort(ID(Q))).to_sigbit_vector(); for (size_t i = 0; i < q1.size(); i++) @@ -324,7 +325,8 @@ struct OptMergeWorker module->connect(RTLIL::SigSig(it.second, other_sig)); assign_map.add(it.second, other_sig); - if (cell->type.begins_with("$") && it.first == ID(Q)) { + if (it.first == ID(Q) && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") || cell->type.in("$adff", "$sr", "$ff") || + cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH"))) { for (auto c : it.second.chunks()) { auto jt = c.wire->attributes.find(ID(init)); if (jt == c.wire->attributes.end()) From f5e0a07ad679696b0d3077ef877941d4c1f864d7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Dec 2019 13:00:04 -0800 Subject: [PATCH 4/4] Add $_FF_ and $_SR* courtesy of @mwkmwkmwk --- backends/aiger/xaiger.cc | 46 +++++++++++++++++++++++----------------- passes/opt/opt_merge.cc | 10 +++++---- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 627133314..e0ae118ad 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -605,15 +605,25 @@ struct XAigerWriter RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); + dict cell_cache; + int port_id = 1; int box_count = 0; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); + log_assert(box_module); + IdString derived_name = box_module->derive(module->design, cell->parameters); + box_module = module->design->module(derived_name); + if (box_module->has_processes()) + log_error("ABC9 box '%s' contains processes!\n", box_module->name.c_str()); + int box_inputs = 0, box_outputs = 0; - Cell *holes_cell = nullptr; - if (box_module->get_bool_attribute("\\whitebox")) { + auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); + Cell *holes_cell = r.first->second; + if (r.second && !holes_cell && box_module->get_bool_attribute("\\whitebox")) { holes_cell = holes_module->addCell(cell->name, cell->type); holes_cell->parameters = cell->parameters; + r.first->second = holes_cell; } // NB: Assume box_module->ports are sorted alphabetically @@ -622,8 +632,8 @@ struct XAigerWriter RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); RTLIL::Wire *holes_wire; - RTLIL::SigSpec port_wire; - if (w->port_input) { + RTLIL::SigSpec port_sig; + if (w->port_input) for (int i = 0; i < GetSize(w); i++) { box_inputs++; holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); @@ -634,28 +644,29 @@ struct XAigerWriter holes_module->ports.push_back(holes_wire->name); } if (holes_cell) - port_wire.append(holes_wire); + port_sig.append(holes_wire); } - if (!port_wire.empty()) - holes_cell->setPort(w->name, port_wire); - } if (w->port_output) { box_outputs += GetSize(w); for (int i = 0; i < GetSize(w); i++) { if (GetSize(w) == 1) - holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), log_id(w->name))); else - holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), log_id(w->name), i)); holes_wire->port_output = true; holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); if (holes_cell) - port_wire.append(holes_wire); + port_sig.append(holes_wire); else holes_module->connect(holes_wire, State::S0); } - if (!port_wire.empty()) - holes_cell->setPort(w->name, port_wire); + } + if (!port_sig.empty()) { + if (r.second) + holes_cell->setPort(w->name, port_sig); + else + holes_module->connect(holes_cell->getPort(w->name), port_sig); } } @@ -685,14 +696,11 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - // TODO: Should not need to opt_merge if we only instantiate - // each box type once... - Pass::call(holes_module->design, "opt_merge -share_all"); - Pass::call(holes_module->design, "flatten -wb"); - // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, - // instead of per write_xaiger call + // Cannot techmap/aigmap all lib_whitebox-es just once per design + // instead of per write_xaiger call, since boxes may be parameterised + // and new $paramod-s may have been created... Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 8dd238bc7..8823a9061 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -222,8 +222,9 @@ struct OptMergeWorker return true; } - if (conn1.count(ID(Q)) != 0 && (cell1->type.begins_with("$dff") || cell1->type.begins_with("$dlatch") || cell1->type.in("$adff", "$sr", "$ff") || - cell1->type.begins_with("$_DFF") || cell1->type.begins_with("$_DLATCH"))) { + if (conn1.count(ID(Q)) != 0 && (cell1->type.begins_with("$dff") || cell1->type.begins_with("$dlatch") || + cell1->type.begins_with("$_DFF") || cell1->type.begins_with("$_DLATCH") || cell1->type.begins_with("$_SR_") || + cell1->type.in("$adff", "$sr", "$ff", "$_FF_"))) { std::vector q1 = dff_init_map(cell1->getPort(ID(Q))).to_sigbit_vector(); std::vector q2 = dff_init_map(cell2->getPort(ID(Q))).to_sigbit_vector(); for (size_t i = 0; i < q1.size(); i++) @@ -325,8 +326,9 @@ struct OptMergeWorker module->connect(RTLIL::SigSig(it.second, other_sig)); assign_map.add(it.second, other_sig); - if (it.first == ID(Q) && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") || cell->type.in("$adff", "$sr", "$ff") || - cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH"))) { + if (it.first == ID(Q) && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") || + cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH") || cell->type.begins_with("$_SR_") || + cell->type.in("$adff", "$sr", "$ff", "$_FF_"))) { for (auto c : it.second.chunks()) { auto jt = c.wire->attributes.find(ID(init)); if (jt == c.wire->attributes.end())