From 2bcd55f1aec8ff2108db835f96e8abd4e89e4be6 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 10 Jan 2020 12:33:58 +0100 Subject: Export wire properties as well in EDIF --- backends/edif/edif.cc | 64 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 26 deletions(-) (limited to 'backends') diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 6d9469538..1bfd4a335 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -300,13 +300,33 @@ struct EdifBackend : public Backend { *f << stringf(" (library DESIGN\n"); *f << stringf(" (edifLevel 0)\n"); *f << stringf(" (technology (numberDefinition))\n"); + + auto add_prop = [&](IdString name, Const val) { + if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0) + *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str()); + else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def()) + *f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int()); + else { + std::string hex_string = ""; + for (size_t i = 0; i < val.bits.size(); i += 4) { + int digit_value = 0; + if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1; + if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2; + if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4; + if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8; + char digit_str[2] = { "0123456789abcdef"[digit_value], 0 }; + hex_string = std::string(digit_str) + hex_string; + } + *f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str()); + } + }; for (auto module : sorted_modules) { if (module->get_blackbox_attribute()) continue; SigMap sigmap(module); - std::map> net_join_db; + std::map> net_join_db; *f << stringf(" (cell %s\n", EDIF_DEF(module->name)); *f << stringf(" (cellType GENERIC)\n"); @@ -323,14 +343,23 @@ struct EdifBackend : public Backend { else if (!wire->port_input) dir = "OUTPUT"; if (wire->width == 1) { - *f << stringf(" (port %s (direction %s))\n", EDIF_DEF(wire->name), dir); + *f << stringf(" (port %s (direction %s)", EDIF_DEF(wire->name), dir); + if (attr_properties) + for (auto &p : wire->attributes) + add_prop(p.first, p.second); + *f << ")\n"; RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire)); net_join_db[sig].insert(stringf("(portRef %s)", EDIF_REF(wire->name))); } else { int b[2]; b[wire->upto ? 0 : 1] = wire->start_offset; b[wire->upto ? 1 : 0] = wire->start_offset + GetSize(wire) - 1; - *f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEFR(wire->name, port_rename, b[0], b[1]), wire->width, dir); + *f << stringf(" (port (array %s %d) (direction %s)", EDIF_DEFR(wire->name, port_rename, b[0], b[1]), wire->width, dir); + if (attr_properties) + for (auto &p : wire->attributes) + add_prop(p.first, p.second); + + *f << ")\n"; for (int i = 0; i < wire->width; i++) { RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, i)); net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), GetSize(wire)-i-1)); @@ -348,27 +377,6 @@ struct EdifBackend : public Backend { *f << stringf(" (instance %s\n", EDIF_DEF(cell->name)); *f << stringf(" (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type), lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : ""); - - auto add_prop = [&](IdString name, Const val) { - if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0) - *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str()); - else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def()) - *f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int()); - else { - std::string hex_string = ""; - for (size_t i = 0; i < val.bits.size(); i += 4) { - int digit_value = 0; - if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1; - if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2; - if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4; - if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8; - char digit_str[2] = { "0123456789abcdef"[digit_value], 0 }; - hex_string = std::string(digit_str) + hex_string; - } - *f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str()); - } - }; - for (auto &p : cell->parameters) add_prop(p.first, p.second); if (attr_properties) @@ -431,8 +439,12 @@ struct EdifBackend : public Backend { *f << stringf(" (portRef %c (instanceRef GND))\n", gndvccy ? 'Y' : 'G'); if (sig == RTLIL::State::S1) *f << stringf(" (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P'); - } - *f << stringf(" ))\n"); + } + *f << stringf(" )"); + if (attr_properties && sig.wire != NULL) + for (auto &p : sig.wire->attributes) + add_prop(p.first, p.second); + *f << stringf("\n )\n"); } *f << stringf(" )\n"); *f << stringf(" )\n"); -- cgit v1.2.3 From 6888799c7545ff07b8c057e1b7382ddd2a2c1b8e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 10 Jan 2020 12:38:03 +0100 Subject: remove whitespace --- backends/edif/edif.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 1bfd4a335..6735d670f 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -326,7 +326,7 @@ struct EdifBackend : public Backend { continue; SigMap sigmap(module); - std::map> net_join_db; + std::map> net_join_db; *f << stringf(" (cell %s\n", EDIF_DEF(module->name)); *f << stringf(" (cellType GENERIC)\n"); -- cgit v1.2.3 From 0d2c06ee47a5008ba79d14d52f72d9b08ac2c7fc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Jan 2020 09:50:50 -0800 Subject: write_xaiger: cache arrival times --- backends/aiger/xaiger.cc | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 93e0ebc8c..0c08645d0 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -184,6 +184,7 @@ struct XAigerWriter } } + dict> arrival_cache; for (auto cell : module->cells()) { if (cell->type == "$_NOT_") { @@ -230,24 +231,29 @@ struct XAigerWriter if (GetSize(box_list) <= abc9_box_seq) box_list.resize(abc9_box_seq+1); box_list[abc9_box_seq] = cell; + // Only flop boxes may have arrival times if (!inst_module->get_bool_attribute("\\abc9_flop")) continue; } + auto &cell_arrivals = arrival_cache[cell->type]; for (const auto &conn : cell->connections()) { - auto port_wire = inst_module->wire(conn.first); - if (port_wire->port_output) { - int arrival = 0; - auto it = port_wire->attributes.find("\\abc9_arrival"); - if (it != port_wire->attributes.end()) { - if (it->second.flags != 0) - log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type)); - arrival = it->second.as_int(); + auto r = cell_arrivals.insert(conn.first); + auto &arrival = r.first->second; + if (r.second) { + auto port_wire = inst_module->wire(conn.first); + if (port_wire->port_output) { + auto it = port_wire->attributes.find("\\abc9_arrival"); + if (it != port_wire->attributes.end()) { + if (it->second.flags != 0) + log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type)); + arrival = it->second.as_int(); + } } - if (arrival) - for (auto bit : sigmap(conn.second)) - arrival_times[bit] = arrival; } + if (arrival) + for (auto bit : sigmap(conn.second)) + arrival_times[bit] = arrival; } } -- cgit v1.2.3 From 9ec948f3965eef214bee3af778b67fdd6ee86929 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Jan 2020 19:07:55 -0800 Subject: write_xaiger: add support and test for (* keep *) on wires --- backends/aiger/xaiger.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0c08645d0..2a0f5c7e4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -156,7 +156,6 @@ struct XAigerWriter if (wire->get_bool_attribute(ID::keep)) sigmap.add(wire); - for (auto wire : module->wires()) for (int i = 0; i < GetSize(wire); i++) { @@ -174,10 +173,11 @@ struct XAigerWriter undriven_bits.insert(bit); unused_bits.insert(bit); - if (wire->port_input) + bool keep = wire->get_bool_attribute(ID::keep); + if (wire->port_input || keep) input_bits.insert(bit); - if (wire->port_output) { + if (wire->port_output || keep) { if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); @@ -209,9 +209,9 @@ struct XAigerWriter } if (cell->type == "$__ABC9_FF_" && - // The presence of an abc9_mergeability attribute indicates - // that we do want to pass this flop to ABC - cell->attributes.count("\\abc9_mergeability")) + // The presence of an abc9_mergeability attribute indicates + // that we do want to pass this flop to ABC + cell->attributes.count("\\abc9_mergeability")) { SigBit D = sigmap(cell->getPort("\\D").as_bit()); SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); @@ -430,7 +430,17 @@ struct XAigerWriter for (const auto &bit : output_bits) { ordered_outputs[bit] = aig_o++; - aig_outputs.push_back(bit2aig(bit)); + int aig; + if (input_bits.count(bit)) { + auto it = aig_map.find(bit); + int input_aig = it->second; + aig_map.erase(it); + aig = bit2aig(bit); + aig_map.at(bit) = input_aig; + } + else + aig = bit2aig(bit); + aig_outputs.push_back(aig); } for (auto &i : ff_bits) { -- cgit v1.2.3 From a6d4ea74634826741f09793c36d596f2fa239f62 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Jan 2020 19:21:11 -0800 Subject: abc9: respect (* keep *) on cells --- backends/aiger/xaiger.cc | 130 +++++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 61 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2a0f5c7e4..ed0e48e01 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -186,74 +186,76 @@ struct XAigerWriter dict> arrival_cache; for (auto cell : module->cells()) { - if (cell->type == "$_NOT_") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - unused_bits.erase(A); - undriven_bits.erase(Y); - not_map[Y] = A; - continue; - } - - if (cell->type == "$_AND_") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit B = sigmap(cell->getPort("\\B").as_bit()); - SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - unused_bits.erase(A); - unused_bits.erase(B); - undriven_bits.erase(Y); - and_map[Y] = make_pair(A, B); - continue; - } + RTLIL::Module* inst_module = module->design->module(cell->type); + if (!cell->has_keep_attr()) { + if (cell->type == "$_NOT_") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + unused_bits.erase(A); + undriven_bits.erase(Y); + not_map[Y] = A; + continue; + } - if (cell->type == "$__ABC9_FF_" && - // The presence of an abc9_mergeability attribute indicates - // that we do want to pass this flop to ABC - cell->attributes.count("\\abc9_mergeability")) - { - SigBit D = sigmap(cell->getPort("\\D").as_bit()); - SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); - unused_bits.erase(D); - undriven_bits.erase(Q); - alias_map[Q] = D; - auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell)); - log_assert(r.second); - continue; - } + if (cell->type == "$_AND_") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit B = sigmap(cell->getPort("\\B").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + unused_bits.erase(A); + unused_bits.erase(B); + undriven_bits.erase(Y); + and_map[Y] = make_pair(A, B); + continue; + } - RTLIL::Module* inst_module = module->design->module(cell->type); - if (inst_module) { - auto it = cell->attributes.find("\\abc9_box_seq"); - if (it != cell->attributes.end()) { - int abc9_box_seq = it->second.as_int(); - if (GetSize(box_list) <= abc9_box_seq) - box_list.resize(abc9_box_seq+1); - box_list[abc9_box_seq] = cell; - // Only flop boxes may have arrival times - if (!inst_module->get_bool_attribute("\\abc9_flop")) - continue; + if (cell->type == "$__ABC9_FF_" && + // The presence of an abc9_mergeability attribute indicates + // that we do want to pass this flop to ABC + cell->attributes.count("\\abc9_mergeability")) + { + SigBit D = sigmap(cell->getPort("\\D").as_bit()); + SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); + unused_bits.erase(D); + undriven_bits.erase(Q); + alias_map[Q] = D; + auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell)); + log_assert(r.second); + continue; } - auto &cell_arrivals = arrival_cache[cell->type]; - for (const auto &conn : cell->connections()) { - auto r = cell_arrivals.insert(conn.first); - auto &arrival = r.first->second; - if (r.second) { - auto port_wire = inst_module->wire(conn.first); - if (port_wire->port_output) { - auto it = port_wire->attributes.find("\\abc9_arrival"); - if (it != port_wire->attributes.end()) { - if (it->second.flags != 0) - log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type)); - arrival = it->second.as_int(); + if (inst_module) { + auto it = cell->attributes.find("\\abc9_box_seq"); + if (it != cell->attributes.end()) { + int abc9_box_seq = it->second.as_int(); + if (GetSize(box_list) <= abc9_box_seq) + box_list.resize(abc9_box_seq+1); + box_list[abc9_box_seq] = cell; + // Only flop boxes may have arrival times + if (!inst_module->get_bool_attribute("\\abc9_flop")) + continue; + } + + auto &cell_arrivals = arrival_cache[cell->type]; + for (const auto &conn : cell->connections()) { + auto r = cell_arrivals.insert(conn.first); + auto &arrival = r.first->second; + if (r.second) { + auto port_wire = inst_module->wire(conn.first); + if (port_wire->port_output) { + auto it = port_wire->attributes.find("\\abc9_arrival"); + if (it != port_wire->attributes.end()) { + if (it->second.flags != 0) + log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type)); + arrival = it->second.as_int(); + } } } + if (arrival) + for (auto bit : sigmap(conn.second)) + arrival_times[bit] = arrival; } - if (arrival) - for (auto bit : sigmap(conn.second)) - arrival_times[bit] = arrival; } } @@ -270,6 +272,9 @@ struct XAigerWriter for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; + // Do not add as PO if bit is already a PI + if (input_bits.count(b)) + continue; if (!w->port_output || !cell_known) { SigBit I = sigmap(b); if (I != b) @@ -431,6 +436,9 @@ struct XAigerWriter for (const auto &bit : output_bits) { ordered_outputs[bit] = aig_o++; int aig; + // For inout/keep bits only, the output bit + // should be driven by logic, not the PI, + // so temporarily swap that out if (input_bits.count(bit)) { auto it = aig_map.find(bit); int input_aig = it->second; -- cgit v1.2.3 From 2c65e1abacc4401c4fd3e9b48f52c4de120bc511 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Jan 2020 21:45:27 -0800 Subject: abc9: break SCC by setting (* keep *) on output wires --- backends/aiger/xaiger.cc | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ed0e48e01..8651f3a01 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -436,15 +436,22 @@ struct XAigerWriter for (const auto &bit : output_bits) { ordered_outputs[bit] = aig_o++; int aig; - // For inout/keep bits only, the output bit - // should be driven by logic, not the PI, - // so temporarily swap that out + // Unlike bit2aig() which checks aig_map first, for + // inout/keep bits, since aig_map will point to + // the PI, first attempt to find the NOT/AND driver + // before resorting to an aig_map lookup (which + // could be another PO) if (input_bits.count(bit)) { - auto it = aig_map.find(bit); - int input_aig = it->second; - aig_map.erase(it); - aig = bit2aig(bit); - aig_map.at(bit) = input_aig; + if (not_map.count(bit)) { + aig = bit2aig(not_map.at(bit)) ^ 1; + } else if (and_map.count(bit)) { + auto args = and_map.at(bit); + int a0 = bit2aig(args.first); + int a1 = bit2aig(args.second); + aig = mkgate(a0, a1); + } + else + aig = aig_map.at(bit); } else aig = bit2aig(bit); -- cgit v1.2.3 From eb7dd7d3741983fafe62b13c4a2d6a21ced06133 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Jan 2020 23:23:21 -0800 Subject: write_xaiger: fix case of PI and CI and (* keep *) --- backends/aiger/xaiger.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8651f3a01..822ba4dec 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -356,6 +356,11 @@ struct XAigerWriter alias_map[O] = b; ci_bits.emplace_back(b); undriven_bits.erase(O); + // If PI and CI, then must be a (* keep *) wire + if (input_bits.erase(O)) { + log_assert(output_bits.count(O)); + log_assert(O.wire->get_bool_attribute(ID::keep)); + } } } -- cgit v1.2.3 From 468386d67d902722562e9a0412a76fca79ec4fa2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 12:25:45 -0800 Subject: abc9_ops: -prep_holes -> -prep_xaiger, move padding to write_xaiger --- backends/aiger/xaiger.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 822ba4dec..2d908e33b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -329,12 +329,11 @@ struct XAigerWriter } } - // Fully pad all unused input connections of this box cell with S0 - // Fully pad all undriven output connections of this box cell with anonymous wires for (auto port_name : r.first->second) { auto w = box_module->wire(port_name); log_assert(w); - auto rhs = cell->getPort(port_name); + auto rhs = cell->connections_.at(port_name, SigSpec()); + rhs.append(Const(State::Sx, GetSize(w)-GetSize(rhs))); if (w->port_input) for (auto b : rhs) { SigBit I = sigmap(b); @@ -429,6 +428,10 @@ struct XAigerWriter for (auto &bit : ci_bits) { aig_m++, aig_i++; + // 1'bx may exist here due to a box output + // that has been padded to its full width + if (bit == State::Sx) + continue; log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } -- cgit v1.2.3 From 654247abe9078566f93960a135ce08b0cfc96442 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 12:40:36 -0800 Subject: abc9_ops/write_xaiger: update doc --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2d908e33b..f9890a592 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -740,7 +740,8 @@ struct XAigerBackend : public Backend { log("Write the top module (according to the (* top *) attribute or if only one module\n"); log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_ABC9_FF_, or"); log("non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n"); - log("pseudo-outputs.\n"); + log("pseudo-outputs. Whitebox contents will be taken from the '$holes'\n"); + log("module, if it exists.\n"); log("\n"); log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); -- cgit v1.2.3