From d4e188299ba729756ee689d14c81aab68a7ca1b7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 17 Jan 2020 12:00:14 -0800 Subject: abc9: add some log_{push,pop}() as per @nakengelhardt --- passes/techmap/abc9.cc | 5 +++++ passes/techmap/alumacc.cc | 19 ++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 6a296bfe7..f4a89efff 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -235,8 +235,11 @@ struct Abc9Pass : public ScriptPass extra_args(args, argidx, design); log_header(design, "Executing ABC9 pass.\n"); + log_push(); run_script(design, run_from, run_to); + + log_pop(); } void script() YS_OVERRIDE @@ -276,6 +279,7 @@ struct Abc9Pass : public ScriptPass } log_assert(!mod->attributes.count(ID(abc9_box_id))); + log_push(); active_design->selection().select(mod); if (!active_design->selected_whole_module(mod)) @@ -310,6 +314,7 @@ struct Abc9Pass : public ScriptPass } active_design->selection().selected_modules.clear(); + log_pop(); } active_design->selection_stack.pop_back(); diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index 034731b87..cf2ac16c9 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -397,18 +397,21 @@ struct AlumaccWorker { log(" creating $alu model for %s (%s):", log_id(cell), log_id(cell->type)); - bool cmp_less = cell->type.in(ID($lt), ID($le)); - bool cmp_equal = cell->type.in(ID($le), ID($ge)); + bool cmp_less = false; //cell->type.in(ID($lt), ID($le)); + bool cmp_equal = false; //cell->type.in(ID($le), ID($ge)); bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); RTLIL::SigSpec A = sigmap(cell->getPort(ID::A)); RTLIL::SigSpec B = sigmap(cell->getPort(ID::B)); RTLIL::SigSpec Y = sigmap(cell->getPort(ID::Y)); - if (B < A && GetSize(B)) { - cmp_less = !cmp_less; + if (cell->type.in(ID($lt), ID($ge))) std::swap(A, B); - } + + //if (B < A && GetSize(B)) { + // cmp_less = !cmp_less; + // std::swap(A, B); + //} alunode_t *n = nullptr; @@ -432,6 +435,12 @@ struct AlumaccWorker log(" merged with %s.\n", log_id(n->cells.front())); } + if (cell->type.in(ID($le), ID($ge))) { + SigSpec YY = module->addWire(NEW_ID, GetSize(Y)); + module->addNot(NEW_ID, YY, Y); + Y = YY; + } + n->cells.push_back(cell); n->cmp.push_back(std::make_tuple(cmp_less, !cmp_less, cmp_equal, false, Y)); } -- cgit v1.2.3 From 3b44b53e946780ac25581f236be7c836fa6927bf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 22 Jan 2020 09:36:54 -0800 Subject: abc9: fix scratchpad entry abc9.verify --- passes/techmap/abc9.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 1f6cdaa22..b0e2c7697 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -304,14 +304,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip for (size_t pos = abc9_script.find("{R}"); pos != std::string::npos; pos = abc9_script.find("{R}", pos)) abc9_script = abc9_script.substr(0, pos) + R + abc9_script.substr(pos+3); - abc9_script += stringf("; &ps -l; &write -n %s/output.aig;", tempdir_name.c_str()); + abc9_script += stringf("; &ps -l; &write -n %s/output.aig", tempdir_name.c_str()); if (design->scratchpad_get_bool("abc9.verify")) { if (dff_mode) - abc9_script += "verify -s;"; + abc9_script += "; &verify -s"; else - abc9_script += "verify;"; + abc9_script += "; &verify"; } - abc9_script += "time"; + abc9_script += "; time"; abc9_script = add_echos_to_abc9_cmd(abc9_script); for (size_t i = 0; i+1 < abc9_script.size(); i++) -- cgit v1.2.3 From a94b41011d5ec9514739c52b963e0bd96890973f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 22 Jan 2020 10:08:48 -0800 Subject: abc9: error out if flip-flop init is 1'b1 for '-dff' Due to ABC sequential synthesis restriction --- passes/techmap/abc9.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index b0e2c7697..2568a6cd1 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1069,6 +1069,8 @@ struct Abc9Pass : public Pass { SigSpec abc9_init = assign_map(abc9_init_wire); if (!abc9_init.is_fully_const()) log_error("'%s.init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + if (abc9_init == State::S1) + log_error("'%s.init' in module '%s' has value 1'b1 which is not supported by 'abc9 -dff'.\n", cell->name.c_str(), log_id(module)); r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); log_assert(r2.second); } -- cgit v1.2.3 From af0e7637a28f08978bc4dfb77089261f9fe18a5d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 22 Jan 2020 20:54:03 -0800 Subject: alumacc: undo accidental commit --- passes/techmap/alumacc.cc | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index cf2ac16c9..034731b87 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -397,21 +397,18 @@ struct AlumaccWorker { log(" creating $alu model for %s (%s):", log_id(cell), log_id(cell->type)); - bool cmp_less = false; //cell->type.in(ID($lt), ID($le)); - bool cmp_equal = false; //cell->type.in(ID($le), ID($ge)); + bool cmp_less = cell->type.in(ID($lt), ID($le)); + bool cmp_equal = cell->type.in(ID($le), ID($ge)); bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); RTLIL::SigSpec A = sigmap(cell->getPort(ID::A)); RTLIL::SigSpec B = sigmap(cell->getPort(ID::B)); RTLIL::SigSpec Y = sigmap(cell->getPort(ID::Y)); - if (cell->type.in(ID($lt), ID($ge))) + if (B < A && GetSize(B)) { + cmp_less = !cmp_less; std::swap(A, B); - - //if (B < A && GetSize(B)) { - // cmp_less = !cmp_less; - // std::swap(A, B); - //} + } alunode_t *n = nullptr; @@ -435,12 +432,6 @@ struct AlumaccWorker log(" merged with %s.\n", log_id(n->cells.front())); } - if (cell->type.in(ID($le), ID($ge))) { - SigSpec YY = module->addWire(NEW_ID, GetSize(Y)); - module->addNot(NEW_ID, YY, Y); - Y = YY; - } - n->cells.push_back(cell); n->cmp.push_back(std::make_tuple(cmp_less, !cmp_less, cmp_equal, false, Y)); } -- cgit v1.2.3 From 1d4314d88853feb1fa6af13fe56274d53d81d853 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 Jan 2020 14:58:56 -0800 Subject: abc9_ops -prep_dff: insert async s/r mux in holes when replacing $_DFF_* --- passes/techmap/abc9_ops.cc | 68 +++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 31 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 5091ac0f2..750f36ceb 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -106,38 +106,44 @@ void prep_dff(RTLIL::Module *module) SigMap sigmap(holes_module); dict replace; - for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) { - auto cell = it->second; - if (cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", - "$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) { - SigBit D = cell->getPort("\\D"); - SigBit Q = cell->getPort("\\Q"); - // Remove the $_DFF_* cell from what needs to be a combinatorial box - it = holes_module->cells_.erase(it); - Wire *port; - if (GetSize(Q.wire) == 1) - port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str())); - else - port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset)); - log_assert(port); - // Prepare to replace "assign = $_DFF_*.Q;" with "assign = $_DFF_*.D;" - // in order to extract just the combinatorial control logic that feeds the box - // (i.e. clock enable, synchronous reset, etc.) - replace.insert(std::make_pair(Q,D)); - // Since `flatten` above would have created wires named ".Q", - // extract the pre-techmap cell name - auto pos = Q.wire->name.str().rfind("."); - log_assert(pos != std::string::npos); - IdString driver = Q.wire->name.substr(0, pos); - // And drive the signal that was previously driven by "DFF.Q" (typically - // used to implement clock-enable functionality) with the ".$abc9_currQ" - // wire (which itself is driven an by input port) we inserted above - Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str())); - log_assert(currQ); - holes_module->connect(Q, currQ); - } + for (auto cell : holes_module->cells().to_vector()) { + if (!cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", + "$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) + continue; + SigBit D = cell->getPort("\\D"); + SigBit Q = cell->getPort("\\Q"); + // Emulate async control embedded inside $_DFF_* cell with mux in front of D + if (cell->type.in("$_DFF_NN0_", "$_DFF_PN0_")) + D = holes_module->MuxGate(NEW_ID, State::S0, D, cell->getPort("\\R")); + else if (cell->type.in("$_DFF_NN1_", "$_DFF_PN1_")) + D = holes_module->MuxGate(NEW_ID, State::S1, D, cell->getPort("\\R")); + else if (cell->type.in("$_DFF_NP0_", "$_DFF_PP0_")) + D = holes_module->MuxGate(NEW_ID, D, State::S0, cell->getPort("\\R")); + else if (cell->type.in("$_DFF_NP1_", "$_DFF_PP1_")) + D = holes_module->MuxGate(NEW_ID, D, State::S1, cell->getPort("\\R")); + // Remove the $_DFF_* cell from what needs to be a combinatorial box + holes_module->remove(cell); + Wire *port; + if (GetSize(Q.wire) == 1) + port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str())); else - ++it; + port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset)); + log_assert(port); + // Prepare to replace "assign = $_DFF_*.Q;" with "assign = $_DFF_*.D;" + // in order to extract just the combinatorial control logic that feeds the box + // (i.e. clock enable, synchronous reset, etc.) + replace.insert(std::make_pair(Q,D)); + // Since `flatten` above would have created wires named ".Q", + // extract the pre-techmap cell name + auto pos = Q.wire->name.str().rfind("."); + log_assert(pos != std::string::npos); + IdString driver = Q.wire->name.substr(0, pos); + // And drive the signal that was previously driven by "DFF.Q" (typically + // used to implement clock-enable functionality) with the ".$abc9_currQ" + // wire (which itself is driven an by input port) we inserted above + Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str())); + log_assert(currQ); + holes_module->connect(Q, currQ); } for (auto &conn : holes_module->connections_) -- cgit v1.2.3 From f180dba753c9f4bfb3b89575b0d224c73a1e8897 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 Jan 2020 18:56:06 -0800 Subject: abc9_ops: -prep_xaiger to skip (* keep *) cells --- passes/techmap/abc9_ops.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 750f36ceb..40622ece7 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -165,6 +165,8 @@ void prep_xaiger(RTLIL::Module *module, bool dff) for (auto cell : module->cells()) { if (cell->type == "$__ABC9_FF_") continue; + if (cell->has_keep_attr()) + continue; auto inst_module = module->design->module(cell->type); bool abc9_box = inst_module && inst_module->attributes.count("\\abc9_box_id"); -- cgit v1.2.3 From 245873d42d7975b6c303c2d04b75f3cafc6c5697 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 Jan 2020 19:08:51 -0800 Subject: abc9: warning message if no modules selected --- passes/techmap/abc9.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f4a89efff..2aeda16d6 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -234,6 +234,12 @@ struct Abc9Pass : public ScriptPass } extra_args(args, argidx, design); + log_assert(design); + if (design->selected_modules().empty()) { + log_warning("No modules selected for ABC9 techmapping.\n"); + return; + } + log_header(design, "Executing ABC9 pass.\n"); log_push(); -- cgit v1.2.3 From dbf351390e68a9d7c453e893de8fa9d09eb24f62 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 Jan 2020 22:45:34 -0800 Subject: abc9: -reintegrate recover type from existing cell, check against boxid --- passes/techmap/abc9_ops.cc | 49 ++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 30 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 40622ece7..d238ce0ad 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -356,24 +356,14 @@ void reintegrate(RTLIL::Module *module) for (auto w : mapped_mod->wires()) module->addWire(remap_name(w->name), GetSize(w)); - dict box_lookup; dict> box_ports; for (auto m : design->modules()) { - auto it = m->attributes.find(ID(abc9_box_id)); - if (it == m->attributes.end()) + if (!m->attributes.count(ID(abc9_box_id))) continue; - if (m->name.begins_with("$paramod")) - 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", - log_id(m), id, log_id(r.first->second)); - log_assert(r.second); - auto r2 = box_ports.insert(m->name); - if (r2.second) { + auto r = box_ports.insert(m->name); + if (r.second) { // Make carry in the last PI, and carry out the last PO // since ABC requires it this way IdString carry_in, carry_out; @@ -393,7 +383,7 @@ void reintegrate(RTLIL::Module *module) } } else - r2.first->second.push_back(port_name); + r.first->second.push_back(port_name); } if (carry_in != IdString() && carry_out == IdString()) @@ -401,8 +391,8 @@ void reintegrate(RTLIL::Module *module) if (carry_in == IdString() && carry_out != IdString()) log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); if (carry_in != IdString()) { - r2.first->second.push_back(carry_in); - r2.first->second.push_back(carry_out); + r.first->second.push_back(carry_in); + r.first->second.push_back(carry_out); } } } @@ -516,28 +506,27 @@ void reintegrate(RTLIL::Module *module) else { RTLIL::Cell *existing_cell = module->cell(mapped_cell->name); log_assert(existing_cell); - log_assert(mapped_cell->type.begins_with("$__boxid")); - auto type = box_lookup.at(mapped_cell->type, IdString()); - if (type == IdString()) - log_error("No module with abc9_box_id = %s found.\n", mapped_cell->type.c_str() + strlen("$__boxid")); - mapped_cell->type = type; + RTLIL::Module* box_module = design->module(existing_cell->type); + auto it = box_module->attributes.find(ID(abc9_box_id)); + log_assert(it != box_module->attributes.end()); + log_assert(mapped_cell->type == stringf("$__boxid%d", it->second.as_int())); + mapped_cell->type = existing_cell->type; RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); cell->parameters = existing_cell->parameters; cell->attributes = existing_cell->attributes; module->swap_names(cell, existing_cell); - auto it = mapped_cell->connections_.find("\\i"); - log_assert(it != mapped_cell->connections_.end()); - SigSpec inputs = std::move(it->second); - mapped_cell->connections_.erase(it); - it = mapped_cell->connections_.find("\\o"); - log_assert(it != mapped_cell->connections_.end()); - SigSpec outputs = std::move(it->second); - mapped_cell->connections_.erase(it); + auto jt = mapped_cell->connections_.find("\\i"); + log_assert(jt != mapped_cell->connections_.end()); + SigSpec inputs = std::move(jt->second); + mapped_cell->connections_.erase(jt); + jt = mapped_cell->connections_.find("\\o"); + log_assert(jt != mapped_cell->connections_.end()); + SigSpec outputs = std::move(jt->second); + mapped_cell->connections_.erase(jt); - RTLIL::Module* box_module = design->module(mapped_cell->type); auto abc9_flop = box_module->attributes.count("\\abc9_flop"); if (!abc9_flop) { for (const auto &i : inputs) -- cgit v1.2.3 From 9009b76a69b9e867f69295a8e555305925e83aeb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 Jan 2020 11:18:21 -0800 Subject: abc9_ops: add comments --- passes/techmap/abc9_ops.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index d238ce0ad..9ad29a8f6 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -213,6 +213,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) else if (!yosys_celltypes.cell_known(cell->type)) continue; + // TODO: Speed up toposort -- we care about box ordering only for (auto conn : cell->connections()) { if (cell->input(conn.first)) for (auto bit : sigmap(conn.second)) @@ -222,7 +223,6 @@ void prep_xaiger(RTLIL::Module *module, bool dff) for (auto bit : sigmap(conn.second)) bit_drivers[bit].insert(cell->name); } - toposort.node(cell->name); } @@ -415,6 +415,7 @@ void reintegrate(RTLIL::Module *module) std::map cell_stats; for (auto mapped_cell : mapped_mod->cells()) { + // TODO: Speed up toposort -- we care about NOT ordering only toposort.node(mapped_cell->name); if (mapped_cell->type == ID($_NOT_)) { @@ -625,6 +626,17 @@ void reintegrate(RTLIL::Module *module) } } + // ABC9 will return $_NOT_ gates in its mapping (since they are + // treated as being "free"), in particular driving primary + // outputs (real primary outputs, or cells treated as blackboxes) + // or driving box inputs. + // Instead of just mapping those $_NOT_ gates into 2-input $lut-s + // at an area and delay cost, see if it is possible to push + // this $_NOT_ into the driving LUT, or into all sink LUTs. + // When this is not possible, (i.e. this signal drives two primary + // outputs, only one of which is complemented) and when the driver + // is a LUT, then clone the LUT so that it can be inverted without + // increasing depth/delay. for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) -- cgit v1.2.3