From f1a206ba03c5b6fba2672754d09cc649a60beeb8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 20 Aug 2019 18:17:14 -0700 Subject: Revert "Remove sequential extension" This reverts commit 091bf4a18b2f4bf84fe62b61577c88d961468b3c. --- backends/aiger/xaiger.cc | 299 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 270 insertions(+), 29 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0d69e0f13..d02997da4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -76,25 +76,32 @@ void aiger_encode(std::ostream &f, int x) struct XAigerWriter { Module *module; + bool zinit_mode; SigMap sigmap; + dict init_map; pool input_bits, output_bits; - dict not_map, alias_map; + dict not_map, ff_map, alias_map; dict> and_map; vector> ci_bits; vector> co_bits; + vector ff_bits; dict arrival_times; vector> aig_gates; - vector aig_outputs; + vector aig_latchin, aig_latchinit, aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; dict aig_map; dict ordered_outputs; + dict ordered_latches; vector box_list; bool omode = false; + //dict init_inputs; + //int initstate_ff = 0; + int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -137,7 +144,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -160,6 +167,14 @@ struct XAigerWriter for (auto wire : module->wires()) { + if (wire->attributes.count("\\init")) { + SigSpec initsig = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++) + if (initval[i] == State::S0 || initval[i] == State::S1) + init_map[initsig[i]] = initval[i] == State::S1; + } + bool keep = wire->attributes.count("\\keep"); for (int i = 0; i < GetSize(wire); i++) @@ -203,6 +218,12 @@ struct XAigerWriter // box ordering, but not individual AIG cells dict> bit_drivers, bit_users; TopoSort toposort; + struct flop_data_t { + IdString d_port; + IdString q_port; + int q_arrival; + }; + dict flop_data; bool abc_box_seen = false; for (auto cell : module->selected_cells()) { @@ -241,25 +262,86 @@ struct XAigerWriter log_assert(!holes_mode); + if (cell->type == "$__ABC_FF_") + { + 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; + continue; + } + RTLIL::Module* inst_module = module->design->module(cell->type); if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; - if (!holes_mode) { - toposort.node(cell->name); - for (const auto &conn : cell->connections()) { - auto port_wire = inst_module->wire(conn.first); - if (port_wire->port_input) { - // Ignore inout for the sake of topographical ordering - if (port_wire->port_output) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); + toposort.node(cell->name); + + auto r = flop_data.insert(std::make_pair(cell->type, flop_data_t{IdString(), IdString(), 0})); + if (r.second && inst_module->attributes.count("\\abc_flop")) { + IdString &abc_flop_d = r.first->second.d_port; + IdString &abc_flop_q = r.first->second.q_port; + for (auto port_name : inst_module->ports) { + auto wire = inst_module->wire(port_name); + log_assert(wire); + if (wire->attributes.count("\\abc_flop_d")) { + if (abc_flop_d != IdString()) + log_error("More than one port has the 'abc_flop_d' attribute set on module '%s'.\n", log_id(cell->type)); + abc_flop_d = port_name; + } + if (wire->attributes.count("\\abc_flop_q")) { + if (abc_flop_q != IdString()) + log_error("More than one port has the 'abc_flop_q' attribute set on module '%s'.\n", log_id(cell->type)); + abc_flop_q = port_name; + + auto it = wire->attributes.find("\\abc_arrival"); + if (it != wire->attributes.end()) { + if (it->second.flags != 0) + log_error("Attribute 'abc_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(wire), log_id(cell->type)); + r.first->second.q_arrival = it->second.as_int(); + } } + } + if (abc_flop_d == IdString()) + log_error("'abc_flop_d' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); + if (abc_flop_q == IdString()) + log_error("'abc_flop_q' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); + } + + auto abc_flop_d = r.first->second.d_port; + if (abc_flop_d != IdString()) { + SigBit d = cell->getPort(abc_flop_d); + SigBit I = sigmap(d); + if (I != d) + alias_map[I] = d; + unused_bits.erase(d); + + auto abc_flop_q = r.first->second.q_port; + SigBit q = cell->getPort(abc_flop_q); + SigBit O = sigmap(q); + if (O != q) + alias_map[O] = q; + undriven_bits.erase(O); + ff_bits.emplace_back(q); + + auto arrival = r.first->second.q_arrival; + if (arrival) + arrival_times[q] = arrival; + } - if (port_wire->port_output) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); + for (const auto &conn : cell->connections()) { + auto port_wire = inst_module->wire(conn.first); + if (port_wire->port_input) { + // Ignore inout for the sake of topographical ordering + if (port_wire->port_output) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); } + + if (port_wire->port_output) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); } } else { @@ -466,6 +548,7 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } + init_map.sort(); if (holes_mode) { struct sort_by_port_id { bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { @@ -481,6 +564,7 @@ struct XAigerWriter } not_map.sort(); + ff_map.sort(); and_map.sort(); aig_map[State::S0] = 0; @@ -492,12 +576,77 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } + for (auto bit : ff_bits) { + aig_m++, aig_i++; + log_assert(!aig_map.count(bit)); + aig_map[bit] = 2*aig_m; + } + + dict ff_aig_map; for (auto &c : ci_bits) { RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; + auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); + if (!r.second) + ff_aig_map[bit] = 2*aig_m; } + //if (zinit_mode) + //{ + // for (auto it : ff_map) { + // if (init_map.count(it.first)) + // continue; + // aig_m++, aig_i++; + // init_inputs[it.first] = 2*aig_m; + // } + //} + + //for (auto it : ff_map) { + // aig_m++, aig_l++; + // aig_map[it.first] = 2*aig_m; + // ordered_latches[it.first] = aig_l-1; + // if (init_map.count(it.first) == 0) + // aig_latchinit.push_back(2); + // else + // aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); + //} + + //if (!init_inputs.empty()) { + // aig_m++, aig_l++; + // initstate_ff = 2*aig_m+1; + // aig_latchinit.push_back(0); + //} + + //if (zinit_mode) + //{ + // for (auto it : ff_map) + // { + // int l = ordered_latches[it.first]; + + // if (aig_latchinit.at(l) == 1) + // aig_map[it.first] ^= 1; + + // if (aig_latchinit.at(l) == 2) + // { + // int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); + // int gated_initin = mkgate(init_inputs[it.first], initstate_ff); + // aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; + // } + // } + //} + + //for (auto it : ff_map) { + // int a = bit2aig(it.second); + // int l = ordered_latches[it.first]; + // if (zinit_mode && aig_latchinit.at(l) == 1) + // aig_latchin.push_back(a ^ 1); + // else + // aig_latchin.push_back(a); + //} + + //if (!init_inputs.empty()) + // aig_latchin.push_back(1); + for (auto &c : co_bits) { RTLIL::SigBit bit = std::get<0>(c); std::get<4>(c) = ordered_outputs[bit] = aig_o++; @@ -509,6 +658,11 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } + for (auto bit : ff_bits) { + aig_o++; + aig_outputs.push_back(ff_aig_map.at(bit)); + } + if (output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -523,6 +677,8 @@ struct XAigerWriter int aig_obcjf = aig_obcj; log_assert(aig_m == aig_i + aig_l + aig_a); + log_assert(aig_l == GetSize(aig_latchin)); + log_assert(aig_l == GetSize(aig_latchinit)); log_assert(aig_obcjf == GetSize(aig_outputs)); f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); @@ -533,6 +689,15 @@ struct XAigerWriter for (int i = 0; i < aig_i; i++) f << stringf("%d\n", 2*i+2); + //for (int i = 0; i < aig_l; i++) { + // if (zinit_mode || aig_latchinit.at(i) == 0) + // f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); + // else if (aig_latchinit.at(i) == 1) + // f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); + // else if (aig_latchinit.at(i) == 2) + // f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); + //} + for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -550,6 +715,15 @@ struct XAigerWriter } else { + //for (int i = 0; i < aig_l; i++) { + // if (zinit_mode || aig_latchinit.at(i) == 0) + // f << stringf("%d\n", aig_latchin.at(i)); + // else if (aig_latchinit.at(i) == 1) + // f << stringf("%d 1\n", aig_latchin.at(i)); + // else if (aig_latchinit.at(i) == 2) + // f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); + //} + for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -582,14 +756,14 @@ struct XAigerWriter std::stringstream h_buffer; auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); - log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); - write_h_buffer(input_bits.size() + ci_bits.size()); - log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); - write_h_buffer(output_bits.size() + GetSize(co_bits)); - log_debug("piNum = %d\n", GetSize(input_bits)); - write_h_buffer(input_bits.size()); - log_debug("poNum = %d\n", GetSize(output_bits)); - write_h_buffer(output_bits.size()); + log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ff_bits) + GetSize(ci_bits)); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); + log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(ff_bits) + GetSize(co_bits)); + write_h_buffer(output_bits.size() + GetSize(ff_bits) + GetSize(co_bits)); + log_debug("piNum = %d\n", GetSize(input_bits) + GetSize(ff_bits)); + write_h_buffer(input_bits.size() + ff_bits.size()); + log_debug("poNum = %d\n", GetSize(output_bits) + GetSize(ff_bits)); + write_h_buffer(output_bits.size() + ff_bits.size()); log_debug("boxNum = %d\n", GetSize(box_list)); write_h_buffer(box_list.size()); @@ -605,7 +779,7 @@ struct XAigerWriter //for (auto bit : output_bits) // write_o_buffer(0); - if (!box_list.empty()) { + if (!box_list.empty() || !ff_bits.empty()) { RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); @@ -671,13 +845,41 @@ struct XAigerWriter std::stringstream r_buffer; auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - write_r_buffer(0); + log_debug("flopNum = %d\n", GetSize(ff_bits)); + write_r_buffer(ff_bits.size()); + int mergeability_class = 1; + for (auto bit : ff_bits) { + write_r_buffer(mergeability_class++); + write_i_buffer(arrival_times.at(bit, 0)); + //write_o_buffer(0); + } + f << "r"; std::string buffer_str = r_buffer.str(); int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + std::stringstream s_buffer; + auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); + write_s_buffer(ff_bits.size()); + for (auto bit : ff_bits) { + auto it = bit.wire->attributes.find("\\init"); + if (it != bit.wire->attributes.end()) { + auto init = it->second[bit.offset]; + if (init == RTLIL::S1) { + write_s_buffer(1); + continue; + } + } + write_s_buffer(0); + } + f << "s"; + buffer_str = s_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + if (holes_module) { log_push(); @@ -713,7 +915,7 @@ struct XAigerWriter Pass::call(holes_design, "clean -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module, true /* holes_mode */); + XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); delete holes_design; @@ -751,7 +953,9 @@ struct XAigerWriter void write_map(std::ostream &f, bool verbose_map) { dict input_lines; + dict init_lines; dict output_lines; + dict latch_lines; dict wire_lines; for (auto wire : module->wires()) @@ -772,10 +976,30 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); - output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), i, log_id(wire)); + int init = 2; + auto it = init_map.find(b); + if (it != init_map.end()) + init = it->second ? 1 : 0; + output_lines[o] += stringf("output %d %d %s %d\n", o - GetSize(co_bits), i, log_id(wire), init); continue; } + //if (init_inputs.count(sig[i])) { + // int a = init_inputs.at(sig[i]); + // log_assert((a & 1) == 0); + // init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + // continue; + //} + + //if (ordered_latches.count(sig[i])) { + // int l = ordered_latches.at(sig[i]); + // if (zinit_mode && (aig_latchinit.at(l) == 1)) + // latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); + // else + // latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); + // continue; + //} + if (verbose_map) { if (aig_map.count(sig[i]) == 0) continue; @@ -791,6 +1015,10 @@ struct XAigerWriter f << it.second; log_assert(input_lines.size() == input_bits.size()); + init_lines.sort(); + for (auto &it : init_lines) + f << it.second; + int box_count = 0; for (auto cell : box_list) f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); @@ -802,6 +1030,10 @@ struct XAigerWriter if (omode && output_bits.empty()) f << "output " << output_lines.size() << " 0 $__dummy__\n"; + latch_lines.sort(); + for (auto &it : latch_lines) + f << it.second; + wire_lines.sort(); for (auto &it : wire_lines) f << it.second; @@ -822,6 +1054,10 @@ struct XAigerBackend : public Backend { log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); log("\n"); + log(" -zinit\n"); + log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); + log(" uninitialized FFs.\n"); + log("\n"); log(" -map \n"); log(" write an extra file with port and latch symbols\n"); log("\n"); @@ -832,6 +1068,7 @@ struct XAigerBackend : public Backend { void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; + bool zinit_mode = false; bool verbose_map = false; std::string map_filename; @@ -844,6 +1081,10 @@ struct XAigerBackend : public Backend { ascii_mode = true; continue; } + if (args[argidx] == "-zinit") { + zinit_mode = true; + continue; + } if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { map_filename = args[++argidx]; continue; @@ -862,7 +1103,7 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module); + XAigerWriter writer(top_module, zinit_mode); writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { -- cgit v1.2.3 From dc154c39a8d296c0ed7619168d7b4eda95e2fbe0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Sep 2019 17:45:49 -0700 Subject: Fix infinite recursion --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index cc0857896..4045e8811 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -314,7 +314,7 @@ struct XAigerWriter SigBit d = cell->getPort(abc_flop_d); SigBit I = sigmap(d); if (I != d) - alias_map[I] = d; + alias_map[d] = I; unused_bits.erase(d); auto abc_flop_q = r.first->second.q_port; -- cgit v1.2.3 From cfa6dd61ef79fb16abd83164b1e013c0a5a2a63a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Sep 2019 18:41:43 -0700 Subject: Use abc_mergeability attr for "r" extension --- backends/aiger/xaiger.cc | 124 +++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 58 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4045e8811..4df97bd52 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -85,7 +85,7 @@ struct XAigerWriter dict> and_map; vector> ci_bits; vector> co_bits; - vector ff_bits; + vector> ff_bits; dict arrival_times; vector> aig_gates; @@ -319,11 +319,12 @@ struct XAigerWriter auto abc_flop_q = r.first->second.q_port; SigBit q = cell->getPort(abc_flop_q); - SigBit O = sigmap(q); - if (O != q) - alias_map[O] = q; - undriven_bits.erase(O); - ff_bits.emplace_back(q); + log_assert(q == sigmap(q)); + undriven_bits.erase(q); + auto it = cell->attributes.find(ID(abc_mergeability)); + log_assert(it != cell->attributes.end()); + ff_bits.emplace_back(q, it->second.as_int()); + cell->attributes.erase(it); auto arrival = r.first->second.q_arrival; if (arrival) @@ -343,56 +344,57 @@ struct XAigerWriter for (auto bit : sigmap(conn.second)) bit_drivers[bit].insert(cell->name); } + + continue; } - else { - bool cell_known = inst_module || cell->known(); - for (const auto &c : cell->connections()) { - if (c.second.is_fully_const()) continue; - auto port_wire = inst_module ? inst_module->wire(c.first) : nullptr; - auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first); - auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first); - if (!is_input && !is_output) - log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); - - if (is_input) { - for (auto b : c.second) { - Wire *w = b.wire; - if (!w) continue; - if (!w->port_output || !cell_known) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - output_bits.insert(b); - unused_bits.erase(b); - if (!cell_known) - keep_bits.insert(b); - } + bool cell_known = inst_module || cell->known(); + for (const auto &c : cell->connections()) { + if (c.second.is_fully_const()) continue; + auto port_wire = inst_module ? inst_module->wire(c.first) : nullptr; + auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first); + auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first); + if (!is_input && !is_output) + log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); + + if (is_input) { + for (auto b : c.second) { + Wire *w = b.wire; + if (!w) continue; + if (!w->port_output || !cell_known) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + output_bits.insert(b); + unused_bits.erase(b); + + if (!cell_known) + keep_bits.insert(b); } } - if (is_output) { - int arrival = 0; - if (port_wire) { - auto it = port_wire->attributes.find("\\abc_arrival"); - if (it != port_wire->attributes.end()) { - if (it->second.flags != 0) - log_error("Attribute 'abc_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 (is_output) { + int arrival = 0; + if (port_wire) { + auto it = port_wire->attributes.find("\\abc_arrival"); + if (it != port_wire->attributes.end()) { + if (it->second.flags != 0) + log_error("Attribute 'abc_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(); } + } - for (auto b : c.second) { - Wire *w = b.wire; - if (!w) continue; - input_bits.insert(b); - SigBit O = sigmap(b); - if (O != b) - alias_map[O] = b; - undriven_bits.erase(O); - - if (arrival) - arrival_times[b] = arrival; - } + for (auto b : c.second) { + Wire *w = b.wire; + if (!w) continue; + input_bits.insert(b); + SigBit O = sigmap(b); + if (O != b) + alias_map[O] = b; + undriven_bits.erase(O); + + if (arrival) + arrival_times[b] = arrival; } } } @@ -540,12 +542,15 @@ struct XAigerWriter undriven_bits.erase(bit); if (!undriven_bits.empty() && !holes_mode) { + bool whole_module = module->design->selected_whole_module(module->name); undriven_bits.sort(); for (auto bit : undriven_bits) { - log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); + if (whole_module) + log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); input_bits.insert(bit); } - log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + if (whole_module) + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } init_map.sort(); @@ -576,7 +581,8 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto bit : ff_bits) { + for (const auto &i : ff_bits) { + const SigBit &bit = i.first; aig_m++, aig_i++; log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; @@ -663,7 +669,8 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - for (auto bit : ff_bits) { + for (auto &i : ff_bits) { + const SigBit &bit = i.first; aig_o++; aig_outputs.push_back(ff_aig_map.at(bit)); } @@ -853,9 +860,9 @@ struct XAigerWriter auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); log_debug("flopNum = %d\n", GetSize(ff_bits)); write_r_buffer(ff_bits.size()); - int mergeability_class = 1; - for (auto bit : ff_bits) { - write_r_buffer(mergeability_class++); + for (const auto &i : ff_bits) { + write_r_buffer(i.second); + const SigBit &bit = i.first; write_i_buffer(arrival_times.at(bit, 0)); //write_o_buffer(0); } @@ -869,7 +876,8 @@ struct XAigerWriter std::stringstream s_buffer; auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); write_s_buffer(ff_bits.size()); - for (auto bit : ff_bits) { + for (const auto &i : ff_bits) { + const SigBit &bit = i.first; auto it = bit.wire->attributes.find("\\init"); if (it != bit.wire->attributes.end()) { auto init = it->second[bit.offset]; -- cgit v1.2.3 From 79b6edb6397c530a7304eb4334f95324a4208aba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 28 Sep 2019 23:48:17 -0700 Subject: Big rework; flop info now mostly in cells_sim.v --- backends/aiger/xaiger.cc | 155 ++++++++++++++++++++++++++++------------------- 1 file changed, 93 insertions(+), 62 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4df97bd52..5d41d49b9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -81,11 +81,11 @@ struct XAigerWriter dict init_map; pool input_bits, output_bits; - dict not_map, ff_map, alias_map; + dict not_map, /*ff_map,*/ alias_map; dict> and_map; vector> ci_bits; vector> co_bits; - vector> ff_bits; + dict ff_bits; dict arrival_times; vector> aig_gates; @@ -218,13 +218,8 @@ struct XAigerWriter // box ordering, but not individual AIG cells dict> bit_drivers, bit_users; TopoSort toposort; - struct flop_data_t { - IdString d_port; - IdString q_port; - int q_arrival; - }; - dict flop_data; bool abc_box_seen = false; + std::vector flop_boxes; for (auto cell : module->selected_cells()) { if (cell->type == "$_NOT_") @@ -269,6 +264,8 @@ struct XAigerWriter unused_bits.erase(D); undriven_bits.erase(Q); alias_map[Q] = D; + auto r = ff_bits.insert(std::make_pair(D, 0)); + log_assert(r.second); continue; } @@ -278,59 +275,6 @@ struct XAigerWriter toposort.node(cell->name); - auto r = flop_data.insert(std::make_pair(cell->type, flop_data_t{IdString(), IdString(), 0})); - if (r.second && inst_module->attributes.count("\\abc_flop")) { - IdString &abc_flop_d = r.first->second.d_port; - IdString &abc_flop_q = r.first->second.q_port; - for (auto port_name : inst_module->ports) { - auto wire = inst_module->wire(port_name); - log_assert(wire); - if (wire->attributes.count("\\abc_flop_d")) { - if (abc_flop_d != IdString()) - log_error("More than one port has the 'abc_flop_d' attribute set on module '%s'.\n", log_id(cell->type)); - abc_flop_d = port_name; - } - if (wire->attributes.count("\\abc_flop_q")) { - if (abc_flop_q != IdString()) - log_error("More than one port has the 'abc_flop_q' attribute set on module '%s'.\n", log_id(cell->type)); - abc_flop_q = port_name; - - auto it = wire->attributes.find("\\abc_arrival"); - if (it != wire->attributes.end()) { - if (it->second.flags != 0) - log_error("Attribute 'abc_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(wire), log_id(cell->type)); - r.first->second.q_arrival = it->second.as_int(); - } - } - } - if (abc_flop_d == IdString()) - log_error("'abc_flop_d' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); - if (abc_flop_q == IdString()) - log_error("'abc_flop_q' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); - } - - auto abc_flop_d = r.first->second.d_port; - if (abc_flop_d != IdString()) { - SigBit d = cell->getPort(abc_flop_d); - SigBit I = sigmap(d); - if (I != d) - alias_map[d] = I; - unused_bits.erase(d); - - auto abc_flop_q = r.first->second.q_port; - SigBit q = cell->getPort(abc_flop_q); - log_assert(q == sigmap(q)); - undriven_bits.erase(q); - auto it = cell->attributes.find(ID(abc_mergeability)); - log_assert(it != cell->attributes.end()); - ff_bits.emplace_back(q, it->second.as_int()); - cell->attributes.erase(it); - - auto arrival = r.first->second.q_arrival; - if (arrival) - arrival_times[q] = arrival; - } - for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); if (port_wire->port_input) { @@ -345,6 +289,8 @@ struct XAigerWriter bit_drivers[bit].insert(cell->name); } + if (inst_module->attributes.count("\\abc9_flop")) + flop_boxes.push_back(cell); continue; } @@ -403,6 +349,45 @@ struct XAigerWriter } if (abc_box_seen) { + dict> flop_q; + for (auto cell : flop_boxes) { + auto r = flop_q.insert(std::make_pair(cell->type, std::make_pair(IdString(), 0))); + SigBit d; + if (r.second) { + for (const auto &conn : cell->connections()) { + const SigSpec &rhs = conn.second; + if (!rhs.is_bit()) + continue; + if (!ff_bits.count(rhs)) + continue; + r.first->second.first = conn.first; + Module *inst_module = module->design->module(cell->type); + Wire *wire = inst_module->wire(conn.first); + log_assert(wire); + auto jt = wire->attributes.find("\\abc_arrival"); + if (jt != wire->attributes.end()) { + if (jt->second.flags != 0) + log_error("Attribute 'abc_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(wire), log_id(cell->type)); + r.first->second.second = jt->second.as_int(); + } + d = rhs; + log_assert(d == sigmap(d)); + break; + } + } + else + d = cell->getPort(r.first->second.first); + + auto it = cell->attributes.find(ID(abc9_mergeability)); + log_assert(it != cell->attributes.end()); + ff_bits.at(d) = it->second.as_int(); + cell->attributes.erase(it); + + auto arrival = r.first->second.second; + if (arrival) + arrival_times[d] = arrival; + } + for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) @@ -498,6 +483,29 @@ struct XAigerWriter } } } + + if (box_module->get_bool_attribute("\\abc9_flop")) { + IdString port_name = "\\$currQ"; + RTLIL::Wire* w = box_module->wire(port_name); + SigSpec rhs = cell->getPort(port_name); + log_assert(GetSize(w) == GetSize(rhs)); + + int offset = 0; + for (auto b : rhs.bits()) { + SigBit I = sigmap(b); + if (b == RTLIL::Sx) + b = State::S0; + else if (I != b) { + if (I == RTLIL::Sx) + alias_map[b] = State::S0; + else + alias_map[b] = I; + } + co_bits.emplace_back(b, cell, port_name, offset++, 0); + unused_bits.erase(b); + } + } + box_list.emplace_back(cell); } @@ -569,7 +577,7 @@ struct XAigerWriter } not_map.sort(); - ff_map.sort(); + //ff_map.sort(); and_map.sort(); aig_map[State::S0] = 0; @@ -850,6 +858,28 @@ struct XAigerWriter } } + if (box_module->get_bool_attribute("\\abc9_flop")) { + log_assert(holes_cell); + IdString port_name = "\\$currQ"; + Wire* w = box_module->wire(port_name); + SigSpec rhs = cell->getPort(port_name); + log_assert(GetSize(w) == GetSize(rhs)); + SigSpec port_wire; + Wire *holes_wire; + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + } + port_wire.append(holes_wire); + } + holes_cell->setPort(w->name, port_wire); + } + write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); @@ -861,6 +891,7 @@ struct XAigerWriter log_debug("flopNum = %d\n", GetSize(ff_bits)); write_r_buffer(ff_bits.size()); for (const auto &i : ff_bits) { + log_assert(i.second > 0); write_r_buffer(i.second); const SigBit &bit = i.first; write_i_buffer(arrival_times.at(bit, 0)); -- cgit v1.2.3 From bd8356799aaee629b747984fd01d3ef4d1182a27 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 12:34:28 -0700 Subject: Use derived module --- backends/aiger/xaiger.cc | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 616aca074..6907ccecc 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -808,6 +808,11 @@ struct XAigerWriter int box_count = 0; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); + if (box_module->get_bool_attribute("\\abc9_flop")) { + auto derived_name = box_module->derive(module->design, cell->parameters); + box_module = module->design->module(derived_name); + } + int box_inputs = 0, box_outputs = 0; Cell *holes_cell = nullptr; if (box_module->get_bool_attribute("\\whitebox")) { @@ -858,28 +863,6 @@ struct XAigerWriter } } - if (box_module->get_bool_attribute("\\abc9_flop")) { - log_assert(holes_cell); - IdString port_name = "\\$currQ"; - Wire* w = box_module->wire(port_name); - SigSpec rhs = cell->getPort(port_name); - log_assert(GetSize(w) == GetSize(rhs)); - SigSpec port_wire; - Wire *holes_wire; - for (int i = 0; i < GetSize(w); i++) { - box_inputs++; - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - } - port_wire.append(holes_wire); - } - holes_cell->setPort(w->name, port_wire); - } - write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); -- cgit v1.2.3 From a6994c5f167c530e0dc81afcac5836ae66447a92 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 12:57:19 -0700 Subject: scc call on active module module only, plus cleanup --- backends/aiger/xaiger.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6907ccecc..3ae57bd3a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -915,30 +915,34 @@ struct XAigerWriter //holes_module->fixup_ports(); holes_module->check(); - holes_module->design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = holes_module->design->selection_stack.back(); + Design *design = holes_module->design; + design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = design->selection_stack.back(); + log_assert(design->selected_active_module == module->name.c_str()); + design->selected_active_module = holes_module->name.str(); 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(design, "opt_merge -share_all"); - Pass::call(holes_module->design, "flatten -wb"); + Pass::call(design, "flatten -wb"); // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, // instead of per write_xaiger call - Pass::call(holes_module->design, "techmap"); - Pass::call(holes_module->design, "aigmap"); + Pass::call(design, "techmap"); + Pass::call(design, "aigmap"); for (auto cell : holes_module->cells()) if (!cell->type.in("$_NOT_", "$_AND_")) log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - holes_module->design->selection_stack.pop_back(); + design->selection_stack.pop_back(); + design->selected_active_module = module->name.str(); // Move into a new (temporary) design so that "clean" will only // operate (and run checks on) this one module RTLIL::Design *holes_design = new RTLIL::Design; - holes_module->design->modules_.erase(holes_module->name); + design->modules_.erase(holes_module->name); holes_design->add(holes_module); Pass::call(holes_design, "clean -purge"); -- cgit v1.2.3 From 74678227c73d0ba1dfa391ba93bd2010ce3202c1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 13:21:07 -0700 Subject: Use a cell_cache to instantiate once rather than opt_merge call --- backends/aiger/xaiger.cc | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3ae57bd3a..1aa2bc62e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -804,20 +804,23 @@ 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); - if (box_module->get_bool_attribute("\\abc9_flop")) { - auto derived_name = box_module->derive(module->design, cell->parameters); - box_module = module->design->module(derived_name); - } + log_assert(box_module); + IdString derived_name = box_module->derive(module->design, cell->parameters); + box_module = module->design->module(derived_name); 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 @@ -827,7 +830,7 @@ struct XAigerWriter log_assert(w); RTLIL::Wire *holes_wire; RTLIL::SigSpec port_wire; - if (w->port_input) { + if (w->port_input) for (int i = 0; i < GetSize(w); i++) { box_inputs++; holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); @@ -840,9 +843,6 @@ struct XAigerWriter if (holes_cell) port_wire.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++) { @@ -858,8 +858,12 @@ struct XAigerWriter else holes_module->connect(holes_wire, State::S0); } - if (!port_wire.empty()) + } + if (!port_wire.empty()) { + if (r.second) holes_cell->setPort(w->name, port_wire); + else + holes_module->connect(port_wire, holes_cell->getPort(w->name)); } } @@ -922,10 +926,6 @@ struct XAigerWriter design->selected_active_module = holes_module->name.str(); sel.select(holes_module); - // TODO: Should not need to opt_merge if we only instantiate - // each box type once... - Pass::call(design, "opt_merge -share_all"); - Pass::call(design, "flatten -wb"); // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, -- cgit v1.2.3 From eecfdda6144856f399f0440d82595ca05c11e41b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 15:24:03 -0700 Subject: Cleanup --- backends/aiger/xaiger.cc | 103 ++--------------------------------------------- 1 file changed, 3 insertions(+), 100 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1aa2bc62e..52273e9b9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -81,7 +81,7 @@ struct XAigerWriter dict init_map; pool input_bits, output_bits; - dict not_map, /*ff_map,*/ alias_map; + dict not_map, alias_map; dict> and_map; vector> ci_bits; vector> co_bits; @@ -89,7 +89,7 @@ struct XAigerWriter dict arrival_times; vector> aig_gates; - vector aig_latchin, aig_latchinit, aig_outputs; + vector aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; dict aig_map; @@ -99,9 +99,6 @@ struct XAigerWriter vector box_list; bool omode = false; - //dict init_inputs; - //int initstate_ff = 0; - int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -561,7 +558,6 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } - init_map.sort(); if (holes_mode) { struct sort_by_port_id { bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { @@ -577,7 +573,6 @@ struct XAigerWriter } not_map.sort(); - //ff_map.sort(); and_map.sort(); aig_map[State::S0] = 0; @@ -605,62 +600,6 @@ struct XAigerWriter ff_aig_map[bit] = 2*aig_m; } - //if (zinit_mode) - //{ - // for (auto it : ff_map) { - // if (init_map.count(it.first)) - // continue; - // aig_m++, aig_i++; - // init_inputs[it.first] = 2*aig_m; - // } - //} - - //for (auto it : ff_map) { - // aig_m++, aig_l++; - // aig_map[it.first] = 2*aig_m; - // ordered_latches[it.first] = aig_l-1; - // if (init_map.count(it.first) == 0) - // aig_latchinit.push_back(2); - // else - // aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); - //} - - //if (!init_inputs.empty()) { - // aig_m++, aig_l++; - // initstate_ff = 2*aig_m+1; - // aig_latchinit.push_back(0); - //} - - //if (zinit_mode) - //{ - // for (auto it : ff_map) - // { - // int l = ordered_latches[it.first]; - - // if (aig_latchinit.at(l) == 1) - // aig_map[it.first] ^= 1; - - // if (aig_latchinit.at(l) == 2) - // { - // int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); - // int gated_initin = mkgate(init_inputs[it.first], initstate_ff); - // aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; - // } - // } - //} - - //for (auto it : ff_map) { - // int a = bit2aig(it.second); - // int l = ordered_latches[it.first]; - // if (zinit_mode && aig_latchinit.at(l) == 1) - // aig_latchin.push_back(a ^ 1); - // else - // aig_latchin.push_back(a); - //} - - //if (!init_inputs.empty()) - // aig_latchin.push_back(1); - for (auto &c : co_bits) { RTLIL::SigBit bit = std::get<0>(c); std::get<4>(c) = ordered_outputs[bit] = aig_o++; @@ -697,8 +636,6 @@ struct XAigerWriter int aig_obcjf = aig_obcj; log_assert(aig_m == aig_i + aig_l + aig_a); - log_assert(aig_l == GetSize(aig_latchin)); - log_assert(aig_l == GetSize(aig_latchinit)); log_assert(aig_obcjf == GetSize(aig_outputs)); f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); @@ -709,15 +646,6 @@ struct XAigerWriter for (int i = 0; i < aig_i; i++) f << stringf("%d\n", 2*i+2); - //for (int i = 0; i < aig_l; i++) { - // if (zinit_mode || aig_latchinit.at(i) == 0) - // f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - // else if (aig_latchinit.at(i) == 1) - // f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - // else if (aig_latchinit.at(i) == 2) - // f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); - //} - for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -735,15 +663,6 @@ struct XAigerWriter } else { - //for (int i = 0; i < aig_l; i++) { - // if (zinit_mode || aig_latchinit.at(i) == 0) - // f << stringf("%d\n", aig_latchin.at(i)); - // else if (aig_latchinit.at(i) == 1) - // f << stringf("%d 1\n", aig_latchin.at(i)); - // else if (aig_latchinit.at(i) == 2) - // f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); - //} - for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -1008,7 +927,7 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); - int init = 2; + int init = zinit_mode ? 0 : 2; auto it = init_map.find(b); if (it != init_map.end()) init = it->second ? 1 : 0; @@ -1016,22 +935,6 @@ struct XAigerWriter continue; } - //if (init_inputs.count(sig[i])) { - // int a = init_inputs.at(sig[i]); - // log_assert((a & 1) == 0); - // init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - // continue; - //} - - //if (ordered_latches.count(sig[i])) { - // int l = ordered_latches.at(sig[i]); - // if (zinit_mode && (aig_latchinit.at(l) == 1)) - // latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); - // else - // latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); - // continue; - //} - if (verbose_map) { if (aig_map.count(sig[i]) == 0) continue; -- cgit v1.2.3 From e529872b0170ba269db2d00c96108c86b260e864 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 16:33:40 -0700 Subject: Remove need for $currQ port connection --- backends/aiger/xaiger.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 52273e9b9..65792421f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -483,12 +483,12 @@ struct XAigerWriter if (box_module->get_bool_attribute("\\abc9_flop")) { IdString port_name = "\\$currQ"; - RTLIL::Wire* w = box_module->wire(port_name); - SigSpec rhs = cell->getPort(port_name); + Wire *w = box_module->wire(port_name); + SigSpec rhs = module->wire(stringf("%s.$currQ", cell->name.c_str())); log_assert(GetSize(w) == GetSize(rhs)); int offset = 0; - for (auto b : rhs.bits()) { + for (auto b : rhs) { SigBit I = sigmap(b); if (b == RTLIL::Sx) b = State::S0; -- cgit v1.2.3 From 1b96d29174d7c56a14031bc117a7da5fa5192c81 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 17:02:20 -0700 Subject: No need to punch ports at all --- backends/aiger/xaiger.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 65792421f..4bdd54772 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -481,6 +481,7 @@ struct XAigerWriter } } + // Connect $currQ as an input to the flop box if (box_module->get_bool_attribute("\\abc9_flop")) { IdString port_name = "\\$currQ"; Wire *w = box_module->wire(port_name); @@ -786,6 +787,29 @@ struct XAigerWriter } } + // For flops only, create an extra input for $currQ + if (box_module->get_bool_attribute("\\abc9_flop")) { + log_assert(holes_cell); + + Wire *w = box_module->wire("\\$currQ"); + Wire *holes_wire; + RTLIL::SigSpec port_wire; + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + } + port_wire.append(holes_wire); + } + w = holes_module->addWire(stringf("%s.$currQ", cell->name.c_str()), GetSize(w)); + w->set_bool_attribute("\\hierconn"); + holes_module->connect(w, port_wire); + } + write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); -- cgit v1.2.3 From 7959e9d6b25d7afefded4b14e14ccf2b0b5af553 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 4 Oct 2019 17:21:14 -0700 Subject: Fix merge issues --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 09b5586fe..4547b9c09 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -254,7 +254,7 @@ struct XAigerWriter log_assert(!holes_mode); - if (cell->type == "$__ABC_FF_") + if (cell->type == "$__ABC9_FF_") { SigBit D = sigmap(cell->getPort("\\D").as_bit()); SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); -- cgit v1.2.3 From 3c6e5d82a62650a48027d35e6d92a7a88ad43a16 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 5 Oct 2019 09:06:13 -0700 Subject: Error if $currQ not found --- backends/aiger/xaiger.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4547b9c09..3e3a8fdc6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -485,7 +485,11 @@ struct XAigerWriter if (box_module->get_bool_attribute("\\abc9_flop")) { IdString port_name = "\\$currQ"; Wire *w = box_module->wire(port_name); + if (!w) + log_error("'$currQ' is not a wire present in module '%s'.\n", log_id(box_module)); SigSpec rhs = module->wire(stringf("%s.$currQ", cell->name.c_str())); + if (rhs.empty()) + log_error("'%s.$currQ' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); log_assert(GetSize(w) == GetSize(rhs)); int offset = 0; -- cgit v1.2.3 From 3879ca13983a6e3f7d4653b1d80dacd14fbe82df Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 5 Oct 2019 22:55:18 -0700 Subject: Do not require changes to cells_sim.v; try and work out comb model --- backends/aiger/xaiger.cc | 118 ++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 48 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3e3a8fdc6..cedf611f2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -481,16 +481,11 @@ struct XAigerWriter } } - // Connect $currQ as an input to the flop box + // Connect .$currQ (inserted by abc9_map.v) as an input to the flop box if (box_module->get_bool_attribute("\\abc9_flop")) { - IdString port_name = "\\$currQ"; - Wire *w = box_module->wire(port_name); - if (!w) - log_error("'$currQ' is not a wire present in module '%s'.\n", log_id(box_module)); SigSpec rhs = module->wire(stringf("%s.$currQ", cell->name.c_str())); if (rhs.empty()) log_error("'%s.$currQ' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); - log_assert(GetSize(w) == GetSize(rhs)); int offset = 0; for (auto b : rhs) { @@ -503,7 +498,7 @@ struct XAigerWriter else alias_map[b] = I; } - co_bits.emplace_back(b, cell, port_name, offset++, 0); + co_bits.emplace_back(b, cell, "\\$currQ", offset++, 0); unused_bits.erase(b); } } @@ -737,6 +732,8 @@ struct XAigerWriter 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()) + Pass::call_on_module(module->design, box_module, "proc"); int box_inputs = 0, box_outputs = 0; auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); @@ -753,7 +750,7 @@ struct XAigerWriter RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); RTLIL::Wire *holes_wire; - RTLIL::SigSpec port_wire; + RTLIL::SigSpec port_sig; if (w->port_input) for (int i = 0; i < GetSize(w); i++) { box_inputs++; @@ -765,7 +762,7 @@ struct XAigerWriter holes_module->ports.push_back(holes_wire->name); } if (holes_cell) - port_wire.append(holes_wire); + port_sig.append(holes_wire); } if (w->port_output) { box_outputs += GetSize(w); @@ -777,41 +774,36 @@ struct XAigerWriter 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); + if (holes_cell) { + port_sig.append(holes_wire); + } else holes_module->connect(holes_wire, State::S0); } } - if (!port_wire.empty()) { + if (!port_sig.empty()) { if (r.second) - holes_cell->setPort(w->name, port_wire); + holes_cell->setPort(w->name, port_sig); else - holes_module->connect(port_wire, holes_cell->getPort(w->name)); + holes_module->connect(holes_cell->getPort(w->name), port_sig); } } - // For flops only, create an extra input for $currQ + // For flops only, create an extra 1-bit input that drives a new wire + // called ".$currQ" that is used below if (box_module->get_bool_attribute("\\abc9_flop")) { log_assert(holes_cell); - Wire *w = box_module->wire("\\$currQ"); - Wire *holes_wire; - RTLIL::SigSpec port_wire; - for (int i = 0; i < GetSize(w); i++) { - box_inputs++; - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - } - port_wire.append(holes_wire); + box_inputs++; + Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); } - w = holes_module->addWire(stringf("%s.$currQ", cell->name.c_str()), GetSize(w)); - w->set_bool_attribute("\\hierconn"); - holes_module->connect(w, port_wire); + Wire *w = holes_module->addWire(stringf("%s.$currQ", cell->name.c_str())); + holes_module->connect(w, holes_wire); } write_h_buffer(box_inputs); @@ -866,37 +858,67 @@ struct XAigerWriter //holes_module->fixup_ports(); holes_module->check(); - Design *design = holes_module->design; - design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = design->selection_stack.back(); - log_assert(design->selected_active_module == module->name.c_str()); - design->selected_active_module = holes_module->name.str(); - sel.select(holes_module); - - Pass::call(design, "flatten -wb"); - // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, // instead of per write_xaiger call - Pass::call(design, "techmap"); - Pass::call(design, "aigmap"); - for (auto cell : holes_module->cells()) - if (!cell->type.in("$_NOT_", "$_AND_")) + Pass::call_on_module(holes_module->design, holes_module, "flatten -wb; techmap; aigmap"); + + dict output_port; + SigMap holes_sigmap(holes_module); + for (auto port_name : holes_module->ports) { + Wire *port = holes_module->wire(port_name); + if (port->port_input) + continue; + output_port.insert(std::make_pair(holes_sigmap(port), port)); + } + + 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_P_")) { + 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 = output_port.at(Q); + log_assert(port); + // Prepare to replace "assign = DFF.Q;" with "assign = DFF.D;" + // in order to extract the combinatorial control logic that feeds the box + // (i.e. clock enable, synchronous reset, etc.) + replace.insert(std::make_pair(SigSig(port,Q), SigSig(port,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 ".$currQ" + // wire (which itself is driven an input port) we inserted above + Wire *currQ = holes_module->wire(stringf("%s.$currQ", driver.c_str())); + log_assert(currQ); + holes_module->connect(Q, currQ); + continue; + } + else if (!cell->type.in("$_NOT_", "$_AND_")) log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); + ++it; + } - design->selection_stack.pop_back(); - design->selected_active_module = module->name.str(); + for (auto &conn : holes_module->connections_) { + auto it = replace.find(conn); + if (it != replace.end()) + conn = it->second; + } // Move into a new (temporary) design so that "clean" will only // operate (and run checks on) this one module RTLIL::Design *holes_design = new RTLIL::Design; - design->modules_.erase(holes_module->name); + module->design->modules_.erase(holes_module->name); holes_design->add(holes_module); Pass::call(holes_design, "clean -purge"); std::stringstream a_buffer; XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); - delete holes_design; f << "a"; -- cgit v1.2.3 From d9fba95177ce6d37966af6a89e15c09feceee3df Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 7 Oct 2019 11:49:06 -0700 Subject: Get rid of output_port lookup --- backends/aiger/xaiger.cc | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index cedf611f2..33d4cfe8e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -768,15 +768,14 @@ struct XAigerWriter 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("$abc%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("$abc%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) { + if (holes_cell) port_sig.append(holes_wire); - } else holes_module->connect(holes_wire, State::S0); } @@ -862,15 +861,6 @@ struct XAigerWriter // instead of per write_xaiger call Pass::call_on_module(holes_module->design, holes_module, "flatten -wb; techmap; aigmap"); - dict output_port; - SigMap holes_sigmap(holes_module); - for (auto port_name : holes_module->ports) { - Wire *port = holes_module->wire(port_name); - if (port->port_input) - continue; - output_port.insert(std::make_pair(holes_sigmap(port), port)); - } - dict replace; for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) { auto cell = it->second; @@ -879,7 +869,11 @@ struct XAigerWriter 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 = output_port.at(Q); + 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 the combinatorial control logic that feeds the box -- cgit v1.2.3 From e1554b56dd9c82b609c6565067160268cbc403f3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 7 Oct 2019 11:56:17 -0700 Subject: Add comment on default flop init --- backends/aiger/xaiger.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 33d4cfe8e..ce67cac54 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -842,6 +842,7 @@ struct XAigerWriter continue; } } + // Default flop init is zero write_s_buffer(0); } f << "s"; -- cgit v1.2.3 From 1504ca2cd9211d9c4f31ecc262e347c842dc4fba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 7 Oct 2019 11:58:49 -0700 Subject: Remove "write_xaiger -zinit" --- backends/aiger/xaiger.cc | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ce67cac54..b1b7af513 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -76,7 +76,6 @@ void aiger_encode(std::ostream &f, int x) struct XAigerWriter { Module *module; - bool zinit_mode; SigMap sigmap; dict init_map; @@ -141,7 +140,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool zinit_mode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -912,7 +911,7 @@ struct XAigerWriter Pass::call(holes_design, "clean -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); + XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); delete holes_design; @@ -972,10 +971,10 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); - int init = zinit_mode ? 0 : 2; + int init = 0; auto it = init_map.find(b); - if (it != init_map.end()) - init = it->second ? 1 : 0; + if (it != init_map.end() && it->second) + init = 1; output_lines[o] += stringf("output %d %d %s %d\n", o - GetSize(co_bits), i, log_id(wire), init); continue; } @@ -1036,10 +1035,6 @@ struct XAigerBackend : public Backend { log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); log("\n"); - log(" -zinit\n"); - log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); - log(" uninitialized FFs.\n"); - log("\n"); log(" -map \n"); log(" write an extra file with port and latch symbols\n"); log("\n"); @@ -1050,7 +1045,6 @@ struct XAigerBackend : public Backend { void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; - bool zinit_mode = false; bool verbose_map = false; std::string map_filename; @@ -1063,10 +1057,6 @@ struct XAigerBackend : public Backend { ascii_mode = true; continue; } - if (args[argidx] == "-zinit") { - zinit_mode = true; - continue; - } if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { map_filename = args[++argidx]; continue; @@ -1085,7 +1075,7 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode); + XAigerWriter writer(top_module); writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { -- cgit v1.2.3 From 90a954bb9c856cc6934cb0db6e37e5f80ade5b9a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 7 Oct 2019 13:09:13 -0700 Subject: Get rid of latch_* in write_xaiger --- backends/aiger/xaiger.cc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index b1b7af513..4f6491311 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -93,7 +93,6 @@ struct XAigerWriter dict aig_map; dict ordered_outputs; - dict ordered_latches; vector box_list; bool omode = false; @@ -950,7 +949,6 @@ struct XAigerWriter dict input_lines; dict init_lines; dict output_lines; - dict latch_lines; dict wire_lines; for (auto wire : module->wires()) @@ -1011,10 +1009,6 @@ struct XAigerWriter if (omode && output_bits.empty()) f << "output " << output_lines.size() << " 0 $__dummy__\n"; - latch_lines.sort(); - for (auto &it : latch_lines) - f << it.second; - wire_lines.sort(); for (auto &it : wire_lines) f << it.second; @@ -1036,7 +1030,7 @@ struct XAigerBackend : public Backend { log(" write ASCII version of AIGER format\n"); log("\n"); log(" -map \n"); - log(" write an extra file with port and latch symbols\n"); + log(" write an extra file with port and box symbols\n"); log("\n"); log(" -vmap \n"); log(" like -map, but more verbose\n"); -- cgit v1.2.3 From b2e34f932ac37e66435d413ab7a9f0074dc0343f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 7 Oct 2019 15:31:43 -0700 Subject: Rename $currQ to $abc9_currQ --- backends/aiger/xaiger.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4f6491311..03246a9b5 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -479,11 +479,11 @@ struct XAigerWriter } } - // Connect .$currQ (inserted by abc9_map.v) as an input to the flop box + // Connect .$abc9_currQ (inserted by abc9_map.v) as an input to the flop box if (box_module->get_bool_attribute("\\abc9_flop")) { - SigSpec rhs = module->wire(stringf("%s.$currQ", cell->name.c_str())); + SigSpec rhs = module->wire(stringf("%s.$abc9_currQ", cell->name.c_str())); if (rhs.empty()) - log_error("'%s.$currQ' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); + log_error("'%s.$abc9_currQ' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); int offset = 0; for (auto b : rhs) { @@ -496,7 +496,7 @@ struct XAigerWriter else alias_map[b] = I; } - co_bits.emplace_back(b, cell, "\\$currQ", offset++, 0); + co_bits.emplace_back(b, cell, "\\$abc9_currQ", offset++, 0); unused_bits.erase(b); } } @@ -787,7 +787,7 @@ struct XAigerWriter } // For flops only, create an extra 1-bit input that drives a new wire - // called ".$currQ" that is used below + // called ".$abc9_currQ" that is used below if (box_module->get_bool_attribute("\\abc9_flop")) { log_assert(holes_cell); @@ -799,7 +799,7 @@ struct XAigerWriter holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); } - Wire *w = holes_module->addWire(stringf("%s.$currQ", cell->name.c_str())); + Wire *w = holes_module->addWire(stringf("%s.$abc9_currQ", cell->name.c_str())); holes_module->connect(w, holes_wire); } @@ -884,9 +884,9 @@ struct XAigerWriter 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 ".$currQ" + // used to implement clock-enable functionality) with the ".$abc9_currQ" // wire (which itself is driven an input port) we inserted above - Wire *currQ = holes_module->wire(stringf("%s.$currQ", driver.c_str())); + Wire *currQ = holes_module->wire(stringf("%s.$abc9_currQ", driver.c_str())); log_assert(currQ); holes_module->connect(Q, currQ); continue; -- cgit v1.2.3 From 929beda19c24e8e6cb6e87b0ceaa97ad2829abbe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Nov 2019 16:57:26 -0800 Subject: abc9 to support async flops $_DFF_[NP][NP][01]_ --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 03246a9b5..5d125b653 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -863,7 +863,8 @@ struct XAigerWriter 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_P_")) { + 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 -- cgit v1.2.3 From 0ab1e496dc601f8e9d5efbcc5b2be7cf6b2d9673 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Nov 2019 16:19:28 -0800 Subject: write_xaiger to not use module POs but only write outputs if driven --- backends/aiger/xaiger.cc | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 5d125b653..c69b0fa85 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -542,18 +542,30 @@ struct XAigerWriter } for (auto bit : unused_bits) - undriven_bits.erase(bit); - - if (!undriven_bits.empty() && !holes_mode) { - bool whole_module = module->design->selected_whole_module(module->name); - undriven_bits.sort(); - for (auto bit : undriven_bits) { - if (whole_module) - log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); - input_bits.insert(bit); + if (holes_mode) + undriven_bits.erase(bit); + else if (!undriven_bits.count(bit)) + output_bits.insert(bit); + + if (!holes_mode) { + for (auto port : module->ports) { + auto wire = module->wire(port); + if (!wire->port_output) + continue; + for (int i = 0; i < GetSize(wire); i++) { + SigBit wirebit(wire, i); + SigBit bit = sigmap(wirebit); + if (bit == State::Sx) + continue; + if (!undriven_bits.count(bit)) { + output_bits.insert(wirebit); + } + } } - if (whole_module) - log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + + if (!undriven_bits.empty()) + for (auto bit : undriven_bits) + input_bits.insert(bit); } if (holes_mode) { -- cgit v1.2.3 From 8ef241c6f4a976dca67760c43e820d4e812f2fc2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 13:24:28 -0800 Subject: Revert "write_xaiger to not use module POs but only write outputs if driven" This reverts commit 0ab1e496dc601f8e9d5efbcc5b2be7cf6b2d9673. --- backends/aiger/xaiger.cc | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c69b0fa85..5d125b653 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -542,30 +542,18 @@ struct XAigerWriter } for (auto bit : unused_bits) - if (holes_mode) - undriven_bits.erase(bit); - else if (!undriven_bits.count(bit)) - output_bits.insert(bit); - - if (!holes_mode) { - for (auto port : module->ports) { - auto wire = module->wire(port); - if (!wire->port_output) - continue; - for (int i = 0; i < GetSize(wire); i++) { - SigBit wirebit(wire, i); - SigBit bit = sigmap(wirebit); - if (bit == State::Sx) - continue; - if (!undriven_bits.count(bit)) { - output_bits.insert(wirebit); - } - } + undriven_bits.erase(bit); + + if (!undriven_bits.empty() && !holes_mode) { + bool whole_module = module->design->selected_whole_module(module->name); + undriven_bits.sort(); + for (auto bit : undriven_bits) { + if (whole_module) + log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); + input_bits.insert(bit); } - - if (!undriven_bits.empty()) - for (auto bit : undriven_bits) - input_bits.insert(bit); + if (whole_module) + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } if (holes_mode) { -- cgit v1.2.3 From 81548d1ef988d10007706c36df5885f8557de74a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 16:52:17 -0800 Subject: write_xaiger back to working with whole modules only --- backends/aiger/xaiger.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 5d125b653..de2f7dd73 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -545,15 +545,12 @@ struct XAigerWriter undriven_bits.erase(bit); if (!undriven_bits.empty() && !holes_mode) { - bool whole_module = module->design->selected_whole_module(module->name); undriven_bits.sort(); for (auto bit : undriven_bits) { - if (whole_module) - log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); + log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); input_bits.insert(bit); } - if (whole_module) - log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } if (holes_mode) { -- cgit v1.2.3 From 7f0914a40896b566a8b1e139438bd585a9ae2b4b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Nov 2019 15:42:07 -0800 Subject: Do not sigmap keep bits inside write_xaiger --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index de2f7dd73..763a14909 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -183,7 +183,7 @@ struct XAigerWriter } if (keep) - keep_bits.insert(bit); + keep_bits.insert(wirebit); if (wire->port_input || keep) { if (bit != wirebit) -- cgit v1.2.3 From da51492dbcc9f19a4808ef18e8ae1222bc55b118 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Nov 2019 15:43:37 -0800 Subject: Fold loop --- backends/aiger/xaiger.cc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 763a14909..37ef30522 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -189,6 +189,7 @@ struct XAigerWriter if (bit != wirebit) alias_map[bit] = wirebit; input_bits.insert(wirebit); + undriven_bits.erase(bit); } if (wire->port_output || keep) { @@ -196,6 +197,8 @@ struct XAigerWriter if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); + if (!wire->port_input) + unused_bits.erase(bit); } else log_debug("Skipping PO '%s' driven by 1'bx\n", log_signal(wirebit)); @@ -203,12 +206,6 @@ struct XAigerWriter } } - for (auto bit : input_bits) - undriven_bits.erase(sigmap(bit)); - for (auto bit : output_bits) - if (!bit.wire->port_input) - unused_bits.erase(bit); - // TODO: Speed up toposort -- ultimately we care about // box ordering, but not individual AIG cells dict> bit_drivers, bit_users; -- cgit v1.2.3 From 99702efabae4005970bdbae4bbb34c39fdd4c46d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Nov 2019 19:03:02 -0800 Subject: xaiger: do not promote output wires --- backends/aiger/xaiger.cc | 5 ----- 1 file changed, 5 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 37ef30522..f17a4c775 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -155,11 +155,6 @@ struct XAigerWriter if (wire->port_input) sigmap.add(wire); - // promote output wires - for (auto wire : module->wires()) - if (wire->port_output) - sigmap.add(wire); - for (auto wire : module->wires()) { if (wire->attributes.count("\\init")) { -- cgit v1.2.3 From 403214f44d8f447ce4e367e2d7e135bfaabcb88d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 27 Nov 2019 12:35:25 -0800 Subject: Revert "Fold loop" This reverts commit da51492dbcc9f19a4808ef18e8ae1222bc55b118. --- backends/aiger/xaiger.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f17a4c775..8b809b2e2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -184,7 +184,6 @@ struct XAigerWriter if (bit != wirebit) alias_map[bit] = wirebit; input_bits.insert(wirebit); - undriven_bits.erase(bit); } if (wire->port_output || keep) { @@ -192,8 +191,6 @@ struct XAigerWriter if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); - if (!wire->port_input) - unused_bits.erase(bit); } else log_debug("Skipping PO '%s' driven by 1'bx\n", log_signal(wirebit)); @@ -201,6 +198,12 @@ struct XAigerWriter } } + for (auto bit : input_bits) + undriven_bits.erase(sigmap(bit)); + for (auto bit : output_bits) + if (!bit.wire->port_input) + unused_bits.erase(bit); + // TODO: Speed up toposort -- ultimately we care about // box ordering, but not individual AIG cells dict> bit_drivers, bit_users; -- cgit v1.2.3 From 449b1d2c6f3f3dffcb0bd50f4d6398ceb928b114 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 27 Nov 2019 13:20:12 -0800 Subject: Add comment, use sigmap --- backends/aiger/xaiger.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8b809b2e2..e05b6cc60 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -198,11 +198,11 @@ struct XAigerWriter } } + // Cannot fold into above due to use of sigmap for (auto bit : input_bits) undriven_bits.erase(sigmap(bit)); for (auto bit : output_bits) - if (!bit.wire->port_input) - unused_bits.erase(bit); + unused_bits.erase(sigmap(bit)); // TODO: Speed up toposort -- ultimately we care about // box ordering, but not individual AIG cells -- cgit v1.2.3 From df52bc80d80e384dddf50a01fa970d1aa36123f2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Dec 2019 18:47:44 -0800 Subject: write_xaiger to consume abc9_init attribute for abc9_flops --- backends/aiger/xaiger.cc | 62 ++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 34 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e05b6cc60..2943ed90d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -78,13 +78,12 @@ struct XAigerWriter Module *module; SigMap sigmap; - dict init_map; pool input_bits, output_bits; dict not_map, alias_map; dict> and_map; vector> ci_bits; vector> co_bits; - dict ff_bits; + dict> ff_bits; dict arrival_times; vector> aig_gates; @@ -157,14 +156,6 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (wire->attributes.count("\\init")) { - SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at("\\init"); - for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++) - if (initval[i] == State::S0 || initval[i] == State::S1) - init_map[initsig[i]] = initval[i] == State::S1; - } - bool keep = wire->attributes.count("\\keep"); for (int i = 0; i < GetSize(wire); i++) @@ -254,7 +245,7 @@ struct XAigerWriter unused_bits.erase(D); undriven_bits.erase(Q); alias_map[Q] = D; - auto r = ff_bits.insert(std::make_pair(D, 0)); + auto r = ff_bits.insert(std::make_pair(D, std::make_pair(0, State::Sx))); log_assert(r.second); continue; } @@ -368,11 +359,20 @@ struct XAigerWriter else d = cell->getPort(r.first->second.first); + auto &rhs = ff_bits.at(d); + auto it = cell->attributes.find(ID(abc9_mergeability)); log_assert(it != cell->attributes.end()); - ff_bits.at(d) = it->second.as_int(); + rhs.first = it->second.as_int(); + cell->attributes.erase(it); + + it = cell->attributes.find(ID(abc9_init)); + log_assert(it != cell->attributes.end()); + log_assert(GetSize(it->second) == 1); + rhs.second = it->second[0]; cell->attributes.erase(it); + auto arrival = r.first->second.second; if (arrival) arrival_times[d] = arrival; @@ -805,10 +805,23 @@ struct XAigerWriter auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); log_debug("flopNum = %d\n", GetSize(ff_bits)); write_r_buffer(ff_bits.size()); + + std::stringstream s_buffer; + auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); + write_s_buffer(ff_bits.size()); + for (const auto &i : ff_bits) { - log_assert(i.second > 0); - write_r_buffer(i.second); const SigBit &bit = i.first; + int mergeability = i.second.first; + log_assert(mergeability > 0); + write_r_buffer(mergeability); + State init = i.second.second; + if (init == State::S1) + write_s_buffer(1); + else if (init == State::S0) + write_s_buffer(0); + else + write_s_buffer(0); write_i_buffer(arrival_times.at(bit, 0)); //write_o_buffer(0); } @@ -819,22 +832,6 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - std::stringstream s_buffer; - auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); - write_s_buffer(ff_bits.size()); - for (const auto &i : ff_bits) { - const SigBit &bit = i.first; - auto it = bit.wire->attributes.find("\\init"); - if (it != bit.wire->attributes.end()) { - auto init = it->second[bit.offset]; - if (init == RTLIL::S1) { - write_s_buffer(1); - continue; - } - } - // Default flop init is zero - write_s_buffer(0); - } f << "s"; buffer_str = s_buffer.str(); buffer_size_be = to_big_endian(buffer_str.size()); @@ -962,10 +959,7 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); - int init = 0; - auto it = init_map.find(b); - if (it != init_map.end() && it->second) - init = 1; + int init = 2; output_lines[o] += stringf("output %d %d %s %d\n", o - GetSize(co_bits), i, log_id(wire), init); continue; } -- cgit v1.2.3 From c6ee2fb4825de727cc18c222888c4c8832d6f26f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Dec 2019 19:21:47 -0800 Subject: Cleanup --- backends/aiger/xaiger.cc | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2943ed90d..c6d24cf94 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -83,7 +83,7 @@ struct XAigerWriter dict> and_map; vector> ci_bits; vector> co_bits; - dict> ff_bits; + dict> ff_bits; dict arrival_times; vector> aig_gates; @@ -245,7 +245,7 @@ struct XAigerWriter unused_bits.erase(D); undriven_bits.erase(Q); alias_map[Q] = D; - auto r = ff_bits.insert(std::make_pair(D, std::make_pair(0, State::Sx))); + auto r = ff_bits.insert(std::make_pair(D, std::make_pair(0, 2))); log_assert(r.second); continue; } @@ -369,10 +369,16 @@ struct XAigerWriter it = cell->attributes.find(ID(abc9_init)); log_assert(it != cell->attributes.end()); log_assert(GetSize(it->second) == 1); - rhs.second = it->second[0]; + if (it->second[0] == State::S1) + rhs.second = 1; + else if (it->second[0] == State::S0) + rhs.second = 0; + else { + log_assert(it->second[0] == State::Sx); + rhs.second = 0; + } cell->attributes.erase(it); - auto arrival = r.first->second.second; if (arrival) arrival_times[d] = arrival; @@ -815,13 +821,8 @@ struct XAigerWriter int mergeability = i.second.first; log_assert(mergeability > 0); write_r_buffer(mergeability); - State init = i.second.second; - if (init == State::S1) - write_s_buffer(1); - else if (init == State::S0) - write_s_buffer(0); - else - write_s_buffer(0); + int init = i.second.second; + write_s_buffer(init); write_i_buffer(arrival_times.at(bit, 0)); //write_o_buffer(0); } -- cgit v1.2.3 From a682a3cf9393787a21ef64c4f7273ceeccdbd357 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Dec 2019 17:54:43 -0800 Subject: write_xaiger to support part-selected modules again --- backends/aiger/xaiger.cc | 48 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c6d24cf94..8b4cebe60 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -78,7 +78,7 @@ struct XAigerWriter Module *module; SigMap sigmap; - pool input_bits, output_bits; + pool input_bits, output_bits, external_bits; dict not_map, alias_map; dict> and_map; vector> ci_bits; @@ -154,6 +154,11 @@ struct XAigerWriter if (wire->port_input) sigmap.add(wire); + // promote output wires + for (auto wire : module->wires()) + if (wire->port_output) + sigmap.add(wire); + for (auto wire : module->wires()) { bool keep = wire->attributes.count("\\keep"); @@ -168,20 +173,29 @@ struct XAigerWriter unused_bits.insert(bit); } - if (keep) + if (keep) { keep_bits.insert(wirebit); + if (bit != wirebit) + alias_map[wirebit] = bit; + input_bits.insert(wirebit); + output_bits.insert(wirebit); + continue; + } - if (wire->port_input || keep) { + if (wire->port_input) { if (bit != wirebit) alias_map[bit] = wirebit; input_bits.insert(wirebit); } - if (wire->port_output || keep) { + if (wire->port_output) { if (bit != RTLIL::Sx) { if (bit != wirebit) alias_map[wirebit] = bit; - output_bits.insert(wirebit); + if (holes_mode) + output_bits.insert(wirebit); + else + external_bits.insert(wirebit); } else log_debug("Skipping PO '%s' driven by 1'bx\n", log_signal(wirebit)); @@ -293,7 +307,7 @@ struct XAigerWriter if (I != b) alias_map[b] = I; output_bits.insert(b); - unused_bits.erase(b); + unused_bits.erase(I); if (!cell_known) keep_bits.insert(b); @@ -329,6 +343,12 @@ struct XAigerWriter //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } + for (auto cell : module->cells()) + if (!module->selected(cell)) + for (auto &conn : cell->connections()) + for (auto bit : sigmap(conn.second)) + external_bits.insert(bit); + if (abc9_box_seen) { dict> flop_q; for (auto cell : flop_boxes) { @@ -449,7 +469,7 @@ struct XAigerWriter alias_map[b] = I; } co_bits.emplace_back(b, cell, port_name, offset++, 0); - unused_bits.erase(b); + unused_bits.erase(I); } } if (w->port_output) { @@ -498,7 +518,7 @@ struct XAigerWriter alias_map[b] = I; } co_bits.emplace_back(b, cell, "\\$abc9_currQ", offset++, 0); - unused_bits.erase(b); + unused_bits.erase(I); } } @@ -542,16 +562,22 @@ struct XAigerWriter } } + for (auto bit : external_bits) + if (!undriven_bits.count(sigmap(bit))) { + output_bits.insert(bit); + unused_bits.erase(sigmap(bit)); + } + for (auto bit : unused_bits) undriven_bits.erase(bit); if (!undriven_bits.empty() && !holes_mode) { - undriven_bits.sort(); + //undriven_bits.sort(); for (auto bit : undriven_bits) { - log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); + //log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); input_bits.insert(bit); } - log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + //log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } if (holes_mode) { -- cgit v1.2.3 From 1f96de04c9da12e17df0a8bf27f83b4fe4af8595 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Dec 2019 16:19:10 -0800 Subject: Fix writing non-whole modules, including inouts and keeps --- backends/aiger/xaiger.cc | 171 ++++++++++++++++++++++------------------------- 1 file changed, 81 insertions(+), 90 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8b4cebe60..c080cca4d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -142,7 +142,7 @@ struct XAigerWriter { pool undriven_bits; pool unused_bits; - pool keep_bits; + pool inout_bits; // promote public wires for (auto wire : module->wires()) @@ -154,60 +154,45 @@ struct XAigerWriter if (wire->port_input) sigmap.add(wire); - // promote output wires + // promote keep wires for (auto wire : module->wires()) - if (wire->port_output) + if (wire->get_bool_attribute(ID::keep)) sigmap.add(wire); for (auto wire : module->wires()) - { - bool keep = wire->attributes.count("\\keep"); - for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); SigBit bit = sigmap(wirebit); - if (bit.wire) { - undriven_bits.insert(bit); - unused_bits.insert(bit); - } - - if (keep) { - keep_bits.insert(wirebit); - if (bit != wirebit) - alias_map[wirebit] = bit; - input_bits.insert(wirebit); - output_bits.insert(wirebit); + if (bit.wire == nullptr) { + if (wire->port_output) { + aig_map[wirebit] = (bit == State::S1) ? 1 : 0; + if (holes_mode) + output_bits.insert(wirebit); + //external_bits.insert(wirebit); + } continue; } - if (wire->port_input) { - if (bit != wirebit) - alias_map[bit] = wirebit; - input_bits.insert(wirebit); - } + undriven_bits.insert(bit); + unused_bits.insert(bit); + + if (wire->port_input) + input_bits.insert(bit); if (wire->port_output) { - if (bit != RTLIL::Sx) { - if (bit != wirebit) - alias_map[wirebit] = bit; - if (holes_mode) - output_bits.insert(wirebit); - else - external_bits.insert(wirebit); - } + if (bit != wirebit) + alias_map[wirebit] = bit; + if (holes_mode) + output_bits.insert(wirebit); else - log_debug("Skipping PO '%s' driven by 1'bx\n", log_signal(wirebit)); + external_bits.insert(wirebit); } - } - } - // Cannot fold into above due to use of sigmap - for (auto bit : input_bits) - undriven_bits.erase(sigmap(bit)); - for (auto bit : output_bits) - unused_bits.erase(sigmap(bit)); + if (wire->port_input && wire->port_output) + inout_bits.insert(bit); + } // TODO: Speed up toposort -- ultimately we care about // box ordering, but not individual AIG cells @@ -307,10 +292,9 @@ struct XAigerWriter if (I != b) alias_map[b] = I; output_bits.insert(b); - unused_bits.erase(I); if (!cell_known) - keep_bits.insert(b); + inout_bits.insert(b); } } } @@ -328,11 +312,10 @@ struct XAigerWriter for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; - input_bits.insert(b); SigBit O = sigmap(b); if (O != b) alias_map[O] = b; - undriven_bits.erase(O); + input_bits.insert(b); if (arrival) arrival_times[b] = arrival; @@ -343,12 +326,6 @@ struct XAigerWriter //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } - for (auto cell : module->cells()) - if (!module->selected(cell)) - for (auto &conn : cell->connections()) - for (auto bit : sigmap(conn.second)) - external_bits.insert(bit); - if (abc9_box_seen) { dict> flop_q; for (auto cell : flop_boxes) { @@ -494,8 +471,8 @@ struct XAigerWriter SigBit O = sigmap(b); if (O != b) alias_map[O] = b; - undriven_bits.erase(O); input_bits.erase(b); + undriven_bits.erase(O); } } } @@ -528,56 +505,70 @@ struct XAigerWriter // TODO: Free memory from toposort, bit_drivers, bit_users } - for (auto bit : input_bits) { - if (!output_bits.count(bit)) + if (!holes_mode) + for (auto cell : module->cells()) + if (!module->selected(cell)) + for (auto &conn : cell->connections()) + if (cell->input(conn.first)) + for (auto wirebit : conn.second) + if (sigmap(wirebit).wire) + external_bits.insert(wirebit); + + // For all bits consumed outside of the selected cells, + // but driven from a selected cell, then add it as + // a primary output + for (auto wirebit : external_bits) { + SigBit bit = sigmap(wirebit); + if (!bit.wire) continue; - RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, or a keep-ed wire, then create a new wire - // with $inout.out suffix, make it a PO driven by the existing inout, and - // inherit existing inout's drivers - if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) - || keep_bits.count(bit)) { - RTLIL::IdString wire_name = stringf("$%s$inout.out", wire->name.c_str()); - RTLIL::Wire *new_wire = module->wire(wire_name); - if (!new_wire) - new_wire = module->addWire(wire_name, GetSize(wire)); - SigBit new_bit(new_wire, bit.offset); - module->connect(new_bit, bit); - if (not_map.count(bit)) { - auto a = not_map.at(bit); - not_map[new_bit] = a; - } - else if (and_map.count(bit)) { - auto a = and_map.at(bit); - and_map[new_bit] = a; - } - else if (alias_map.count(bit)) { - auto a = alias_map.at(bit); - alias_map[new_bit] = a; - } - else - alias_map[new_bit] = bit; - output_bits.erase(bit); - output_bits.insert(new_bit); + if (!undriven_bits.count(bit)) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); } } - for (auto bit : external_bits) - if (!undriven_bits.count(sigmap(bit))) { - output_bits.insert(bit); - unused_bits.erase(sigmap(bit)); - } - + for (auto bit : input_bits) + undriven_bits.erase(sigmap(bit)); + for (auto bit : output_bits) + unused_bits.erase(sigmap(bit)); for (auto bit : unused_bits) undriven_bits.erase(bit); - if (!undriven_bits.empty() && !holes_mode) { - //undriven_bits.sort(); + // Make all undriven bits a primary input + if (!holes_mode) for (auto bit : undriven_bits) { - //log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); input_bits.insert(bit); + undriven_bits.erase(bit); + } + + // For inout ports, or keep-ed wires, then create a new wire with an + // $inout.out suffix, make it a PO driven by the existing inout, and + // inherit existing inout's drivers + for (auto bit : inout_bits) { + RTLIL::Wire *wire = bit.wire; + RTLIL::IdString wire_name = stringf("$%s$inout.out", wire->name.c_str()); + RTLIL::Wire *new_wire = module->wire(wire_name); + if (!new_wire) + new_wire = module->addWire(wire_name, GetSize(wire)); + SigBit new_bit(new_wire, bit.offset); + module->connect(new_bit, bit); + if (not_map.count(bit)) { + auto a = not_map.at(bit); + not_map[new_bit] = a; + } + else if (and_map.count(bit)) { + auto a = and_map.at(bit); + and_map[new_bit] = a; + } + else if (alias_map.count(bit)) { + auto a = alias_map.at(bit); + alias_map[new_bit] = a; } - //log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + else + alias_map[new_bit] = bit; + output_bits.erase(bit); + output_bits.insert(new_bit); } if (holes_mode) { @@ -880,7 +871,7 @@ struct XAigerWriter 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_")) { + "$_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 -- cgit v1.2.3 From f2ac36de4ae372cd4467580ca1b28757ea7c9ff7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Dec 2019 17:06:10 -0800 Subject: write_xaiger to inst each cell type once, do not call techmap/aigmap --- backends/aiger/xaiger.cc | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 627133314..7765c37bf 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,31 +644,33 @@ 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); } } + write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_module->attributes.at("\\abc9_box_id").as_int()); @@ -685,16 +697,8 @@ 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 - Pass::call(holes_module->design, "techmap"); - Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) if (!cell->type.in("$_NOT_", "$_AND_")) log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); -- cgit v1.2.3 From 91467938c477c5c668f5ea1a38fef59e2b19db5c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Dec 2019 17:08:19 -0800 Subject: Stray newline --- backends/aiger/xaiger.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7765c37bf..8074fa835 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -670,7 +670,6 @@ struct XAigerWriter } } - write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_module->attributes.at("\\abc9_box_id").as_int()); -- cgit v1.2.3 From 6c340112fee1bb8989cbd41923aaa627d77d5110 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 10:21:08 -0800 Subject: write_xaiger: use sigmap bits more consistently --- backends/aiger/xaiger.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c080cca4d..cff3183c1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -294,7 +294,7 @@ struct XAigerWriter output_bits.insert(b); if (!cell_known) - inout_bits.insert(b); + inout_bits.insert(I); } } } @@ -315,7 +315,7 @@ struct XAigerWriter SigBit O = sigmap(b); if (O != b) alias_map[O] = b; - input_bits.insert(b); + input_bits.insert(O); if (arrival) arrival_times[b] = arrival; @@ -542,9 +542,8 @@ struct XAigerWriter undriven_bits.erase(bit); } - // For inout ports, or keep-ed wires, then create a new wire with an - // $inout.out suffix, make it a PO driven by the existing inout, and - // inherit existing inout's drivers + // For inout ports, or keep-ed wires, which end up being both a PI and a + // a PO then replace the PO with a new wire with the $inout.out suffix for (auto bit : inout_bits) { RTLIL::Wire *wire = bit.wire; RTLIL::IdString wire_name = stringf("$%s$inout.out", wire->name.c_str()); -- cgit v1.2.3 From 78c0246d4abbd290289ed55a0008968293119446 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 14:35:35 -0800 Subject: Revert "write_xaiger: use sigmap bits more consistently" This reverts commit 6c340112fee1bb8989cbd41923aaa627d77d5110. --- backends/aiger/xaiger.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index cff3183c1..c080cca4d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -294,7 +294,7 @@ struct XAigerWriter output_bits.insert(b); if (!cell_known) - inout_bits.insert(I); + inout_bits.insert(b); } } } @@ -315,7 +315,7 @@ struct XAigerWriter SigBit O = sigmap(b); if (O != b) alias_map[O] = b; - input_bits.insert(O); + input_bits.insert(b); if (arrival) arrival_times[b] = arrival; @@ -542,8 +542,9 @@ struct XAigerWriter undriven_bits.erase(bit); } - // For inout ports, or keep-ed wires, which end up being both a PI and a - // a PO then replace the PO with a new wire with the $inout.out suffix + // For inout ports, or keep-ed wires, then create a new wire with an + // $inout.out suffix, make it a PO driven by the existing inout, and + // inherit existing inout's drivers for (auto bit : inout_bits) { RTLIL::Wire *wire = bit.wire; RTLIL::IdString wire_name = stringf("$%s$inout.out", wire->name.c_str()); -- cgit v1.2.3 From b19fc8839bdbf652d136790fe94cdaa1b520c75b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 14:39:13 -0800 Subject: Skip $inout transformation if not a PI --- backends/aiger/xaiger.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c080cca4d..6ca24bd7e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -542,10 +542,12 @@ struct XAigerWriter undriven_bits.erase(bit); } - // For inout ports, or keep-ed wires, then create a new wire with an - // $inout.out suffix, make it a PO driven by the existing inout, and - // inherit existing inout's drivers + // For inout ports, or keep-ed wires, that end up as both a PI and a + // PO, then create a new PO with an $inout.out suffix that is driven + // by the existing inout, and inherit its drivers for (auto bit : inout_bits) { + if (!input_bits.count(bit)) + continue; RTLIL::Wire *wire = bit.wire; RTLIL::IdString wire_name = stringf("$%s$inout.out", wire->name.c_str()); RTLIL::Wire *new_wire = module->wire(wire_name); -- cgit v1.2.3 From 42f990f3a6b7928841fa0e290fa2688925485907 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 16:40:52 -0800 Subject: Use sigmap signal --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6ca24bd7e..e060efece 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -471,7 +471,7 @@ struct XAigerWriter SigBit O = sigmap(b); if (O != b) alias_map[O] = b; - input_bits.erase(b); + input_bits.erase(O); undriven_bits.erase(O); } } -- cgit v1.2.3 From 2e7113070010705b2c6c4a550cc2ebd3fd111ce0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 17 Dec 2019 00:00:07 -0800 Subject: Revert "Use sigmap signal" This reverts commit 42f990f3a6b7928841fa0e290fa2688925485907. --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e060efece..6ca24bd7e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -471,7 +471,7 @@ struct XAigerWriter SigBit O = sigmap(b); if (O != b) alias_map[O] = b; - input_bits.erase(O); + input_bits.erase(b); undriven_bits.erase(O); } } -- cgit v1.2.3 From e82a9bc642782ea84d46ca135d2c0b6a42b9e772 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 17 Dec 2019 00:03:03 -0800 Subject: Do not sigmap --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6ca24bd7e..8db166fc2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -191,7 +191,7 @@ struct XAigerWriter } if (wire->port_input && wire->port_output) - inout_bits.insert(bit); + inout_bits.insert(wirebit); } // TODO: Speed up toposort -- ultimately we care about -- cgit v1.2.3 From 5f50e4f1121d139c3c9b842514c86cfc7712b32e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 17 Dec 2019 15:44:35 -0800 Subject: Cleanup xaiger, remove unnecessary complexity with inout --- backends/aiger/xaiger.cc | 81 ++++++++++++------------------------------------ 1 file changed, 20 insertions(+), 61 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8db166fc2..af52daa0c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -264,9 +264,22 @@ struct XAigerWriter bit_users[bit].insert(cell->name); } - if (port_wire->port_output) - for (auto bit : sigmap(conn.second)) + 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(); + } + + for (auto bit : sigmap(conn.second)) { bit_drivers[bit].insert(cell->name); + if (arrival) + arrival_times[bit] = arrival; + } + } + } if (inst_module->attributes.count("\\abc9_flop")) @@ -291,35 +304,12 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - output_bits.insert(b); - - if (!cell_known) - inout_bits.insert(b); - } - } - } - if (is_output) { - int arrival = 0; - if (port_wire) { - 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 (holes_mode) + output_bits.insert(b); + else + external_bits.insert(b); } } - - for (auto b : c.second) { - Wire *w = b.wire; - if (!w) continue; - SigBit O = sigmap(b); - if (O != b) - alias_map[O] = b; - input_bits.insert(b); - - if (arrival) - arrival_times[b] = arrival; - } } } @@ -471,7 +461,7 @@ struct XAigerWriter SigBit O = sigmap(b); if (O != b) alias_map[O] = b; - input_bits.erase(b); + input_bits.erase(O); undriven_bits.erase(O); } } @@ -542,37 +532,6 @@ struct XAigerWriter undriven_bits.erase(bit); } - // For inout ports, or keep-ed wires, that end up as both a PI and a - // PO, then create a new PO with an $inout.out suffix that is driven - // by the existing inout, and inherit its drivers - for (auto bit : inout_bits) { - if (!input_bits.count(bit)) - continue; - RTLIL::Wire *wire = bit.wire; - RTLIL::IdString wire_name = stringf("$%s$inout.out", wire->name.c_str()); - RTLIL::Wire *new_wire = module->wire(wire_name); - if (!new_wire) - new_wire = module->addWire(wire_name, GetSize(wire)); - SigBit new_bit(new_wire, bit.offset); - module->connect(new_bit, bit); - if (not_map.count(bit)) { - auto a = not_map.at(bit); - not_map[new_bit] = a; - } - else if (and_map.count(bit)) { - auto a = and_map.at(bit); - and_map[new_bit] = a; - } - else if (alias_map.count(bit)) { - auto a = alias_map.at(bit); - alias_map[new_bit] = a; - } - else - alias_map[new_bit] = bit; - output_bits.erase(bit); - output_bits.insert(new_bit); - } - if (holes_mode) { struct sort_by_port_id { bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { -- cgit v1.2.3 From 10e82e103f7b95d5a50d2ac85bc8e07e4461e388 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Dec 2019 12:05:45 -0800 Subject: Revert "Optimise write_xaiger" --- backends/aiger/xaiger.cc | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8074fa835..627133314 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -605,25 +605,15 @@ 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; - 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")) { + Cell *holes_cell = nullptr; + if (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 @@ -632,8 +622,8 @@ struct XAigerWriter RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); RTLIL::Wire *holes_wire; - RTLIL::SigSpec port_sig; - if (w->port_input) + RTLIL::SigSpec port_wire; + if (w->port_input) { for (int i = 0; i < GetSize(w); i++) { box_inputs++; holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); @@ -644,29 +634,28 @@ struct XAigerWriter holes_module->ports.push_back(holes_wire->name); } if (holes_cell) - port_sig.append(holes_wire); + port_wire.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(), log_id(w->name))); + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); else - holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), log_id(w->name), i)); + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); holes_wire->port_output = true; holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); if (holes_cell) - port_sig.append(holes_wire); + port_wire.append(holes_wire); else holes_module->connect(holes_wire, State::S0); } - } - 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); + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } } @@ -696,8 +685,16 @@ 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 + Pass::call(holes_module->design, "techmap"); + Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) if (!cell->type.in("$_NOT_", "$_AND_")) log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); -- cgit v1.2.3 From a75e08c7094d7d6f623057ad936c63551f1ebfbe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Dec 2019 13:07:24 -0800 Subject: write_xaiger: only instantiate each whitebox cell type once --- backends/aiger/xaiger.cc | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 627133314..5729f045a 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/check all lib_whitebox-es outside of write_xaiger + // since boxes may contain parameters in which case `flatten` would have + // created a new $paramod ... Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) -- cgit v1.2.3 From 6eadd4390a3c9650912bac9fbf8bd309f0088217 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Dec 2019 08:35:53 -0800 Subject: write_xaiger to opt instead of just clean whiteboxes --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index af52daa0c..78496b13c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -876,7 +876,7 @@ struct XAigerWriter RTLIL::Design *holes_design = new RTLIL::Design; module->design->modules_.erase(holes_module->name); holes_design->add(holes_module); - Pass::call(holes_design, "clean -purge"); + Pass::call(holes_design, "opt -purge"); std::stringstream a_buffer; XAigerWriter writer(holes_module, true /* holes_mode */); -- cgit v1.2.3 From 49881b4468bbd02ac141495dd3b30c9739eb5072 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 11:30:18 -0800 Subject: write_xaiger: fix arrival times for non boxes --- backends/aiger/xaiger.cc | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 78496b13c..e03f95eaa 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -250,41 +250,48 @@ struct XAigerWriter } RTLIL::Module* inst_module = module->design->module(cell->type); - if (inst_module && inst_module->attributes.count("\\abc9_box_id")) { - abc9_box_seen = true; - - toposort.node(cell->name); + if (inst_module) { + bool abc9_box = inst_module->attributes.count("\\abc9_box_id"); for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); - if (port_wire->port_input) { - // Ignore inout for the sake of topographical ordering - if (port_wire->port_output) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - } + int arrival = 0; 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(); } + } - for (auto bit : sigmap(conn.second)) { - bit_drivers[bit].insert(cell->name); - if (arrival) - arrival_times[bit] = arrival; + if (abc9_box) { + if (port_wire->port_input) { + // Ignore inout for the sake of topographical ordering + if (port_wire->port_output) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); } + if (port_wire->port_output) + for (auto bit : sigmap(conn.second)) { + bit_drivers[bit].insert(cell->name); + if (arrival) + arrival_times[bit] = arrival; + } } } - if (inst_module->attributes.count("\\abc9_flop")) - flop_boxes.push_back(cell); - continue; + if (abc9_box) { + abc9_box_seen = true; + + toposort.node(cell->name); + + if (inst_module->attributes.count("\\abc9_flop")) + flop_boxes.push_back(cell); + continue; + } } bool cell_known = inst_module || cell->known(); -- cgit v1.2.3 From dd503a5f3f50ec9762aa7301b5e0c5112aff1866 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 15:18:55 -0800 Subject: Really fix it! --- backends/aiger/xaiger.cc | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e03f95eaa..80077c10a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -255,32 +255,29 @@ struct XAigerWriter for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); - int arrival = 0; 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(); } + if (arrival) + for (auto bit : sigmap(conn.second)) + arrival_times[bit] = arrival; } if (abc9_box) { - if (port_wire->port_input) { - // Ignore inout for the sake of topographical ordering - if (port_wire->port_output) continue; + // Ignore inout for the sake of topographical ordering + if (port_wire->port_input && !port_wire->port_output) for (auto bit : sigmap(conn.second)) bit_users[bit].insert(cell->name); - } if (port_wire->port_output) - for (auto bit : sigmap(conn.second)) { + for (auto bit : sigmap(conn.second)) bit_drivers[bit].insert(cell->name); - if (arrival) - arrival_times[bit] = arrival; - } } - } if (abc9_box) { -- cgit v1.2.3 From df31ade3b3b4f19e997c3cc8800a4a88e0a71177 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 27 Dec 2019 23:25:20 +0000 Subject: Revert "write_xaiger: only instantiate each whitebox cell type once" --- backends/aiger/xaiger.cc | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 5729f045a..627133314 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -605,25 +605,15 @@ 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; - 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")) { + Cell *holes_cell = nullptr; + if (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 @@ -632,8 +622,8 @@ struct XAigerWriter RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); RTLIL::Wire *holes_wire; - RTLIL::SigSpec port_sig; - if (w->port_input) + RTLIL::SigSpec port_wire; + if (w->port_input) { for (int i = 0; i < GetSize(w); i++) { box_inputs++; holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); @@ -644,29 +634,28 @@ struct XAigerWriter holes_module->ports.push_back(holes_wire->name); } if (holes_cell) - port_sig.append(holes_wire); + port_wire.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(), log_id(w->name))); + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); else - holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), log_id(w->name), i)); + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); holes_wire->port_output = true; holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); if (holes_cell) - port_sig.append(holes_wire); + port_wire.append(holes_wire); else holes_module->connect(holes_wire, State::S0); } - } - 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); + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } } @@ -696,11 +685,14 @@ 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"); - // Cannot techmap/aigmap/check all lib_whitebox-es outside of write_xaiger - // since boxes may contain parameters in which case `flatten` would have - // created a new $paramod ... + // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, + // instead of per write_xaiger call Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) -- cgit v1.2.3 From 3d4644804ea779831b617fe7d12473e3161a93b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 15:35:19 -0800 Subject: write_xaiger: simplify c{i,o}_bits --- backends/aiger/xaiger.cc | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 5729f045a..68d1b1e69 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -81,8 +81,7 @@ struct XAigerWriter pool input_bits, output_bits; dict not_map, alias_map; dict> and_map; - vector> ci_bits; - vector> co_bits; + vector ci_bits, co_bits; dict arrival_times; vector> aig_gates; @@ -367,7 +366,6 @@ struct XAigerWriter cell->setPort(port_name, rhs); } - int offset = 0; for (auto b : rhs.bits()) { SigBit I = sigmap(b); if (b == RTLIL::Sx) @@ -378,7 +376,7 @@ struct XAigerWriter else alias_map[b] = I; } - co_bits.emplace_back(b, cell, port_name, offset++, 0); + co_bits.emplace_back(b); unused_bits.erase(b); } } @@ -398,9 +396,8 @@ struct XAigerWriter cell->setPort(port_name, rhs); } - int offset = 0; for (const auto &b : rhs.bits()) { - ci_bits.emplace_back(b, cell, port_name, offset++); + ci_bits.emplace_back(b); SigBit O = sigmap(b); if (O != b) alias_map[O] = b; @@ -487,15 +484,13 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto &c : ci_bits) { - RTLIL::SigBit bit = std::get<0>(c); + for (auto bit : ci_bits) { aig_m++, aig_i++; aig_map[bit] = 2*aig_m; } - for (auto &c : co_bits) { - RTLIL::SigBit bit = std::get<0>(c); - std::get<4>(c) = ordered_outputs[bit] = aig_o++; + for (auto bit : co_bits) { + ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -508,7 +503,6 @@ struct XAigerWriter ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } - } void write_aiger(std::ostream &f, bool ascii_mode) -- cgit v1.2.3 From a56d6970f24ae6044e02bea333c484035fd5cdfa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 16:05:58 -0800 Subject: Revert "Merge pull request #1598 from YosysHQ/revert-1588-eddie/xaiger_cleanup" This reverts commit 92654f73ea92ee9e390c8ab50d8cb51c47a7ffa9, reversing changes made to 3e14ff16676884a1f65cf0eeb0ca9cb1958b8804. --- backends/aiger/xaiger.cc | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3599e19e3..68d1b1e69 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -599,15 +599,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 @@ -616,8 +626,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)); @@ -628,28 +638,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); } } @@ -679,14 +690,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/check all lib_whitebox-es outside of write_xaiger + // since boxes may contain parameters in which case `flatten` would have + // created a new $paramod ... Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) -- cgit v1.2.3 From 237415e78cab2c15d783657c4c2bc959efb298bb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 16:44:18 -0800 Subject: write_xaiger: inherit port ordering from original module --- backends/aiger/xaiger.cc | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 68d1b1e69..445103771 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -604,27 +604,38 @@ struct XAigerWriter 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); + RTLIL::Module* orig_box_module = module->design->module(cell->type); + log_assert(orig_box_module); + IdString derived_name = orig_box_module->derive(module->design, cell->parameters); + RTLIL::Module* 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; 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")) { + if (r.second && 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; + + // Since Module::derive() will create a new module, there + // is a chance that the ports will be alphabetically ordered + // again, which is a problem when carry-chains are involved. + // Inherit the port ordering from the original module here... + // (and set the port_id below, when iterating through those) + log_assert(GetSize(box_module->ports) == GetSize(orig_box_module->ports)); + box_module->ports = orig_box_module->ports; } // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) + int box_port_id = 1; for (const auto &port_name : box_module->ports) { RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); + if (r.second) + w->port_id = box_port_id++; RTLIL::Wire *holes_wire; RTLIL::SigSpec port_sig; if (w->port_input) -- cgit v1.2.3 From d7ada6649766cfa32b077a744e066476278afd02 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 14:13:16 -0800 Subject: Add "synth_xilinx -dff" option, cleanup abc9 --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 80077c10a..d27e0cde5 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -251,7 +251,7 @@ struct XAigerWriter RTLIL::Module* inst_module = module->design->module(cell->type); if (inst_module) { - bool abc9_box = inst_module->attributes.count("\\abc9_box_id"); + bool abc9_box = inst_module->attributes.count("\\abc9_box_id") && !cell->get_bool_attribute("\\abc9_keep"); for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); @@ -403,7 +403,8 @@ struct XAigerWriter log_assert(cell); RTLIL::Module* box_module = module->design->module(cell->type); - if (!box_module || !box_module->attributes.count("\\abc9_box_id")) + if (!box_module || !box_module->attributes.count("\\abc9_box_id") + || cell->get_bool_attribute("\\abc9_keep")) continue; bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); -- cgit v1.2.3 From 3cbbae251fc4a4b10abe21fde9c7316bb940a957 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 14:33:05 -0800 Subject: Call "proc" if processes inside whiteboxes --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bfdae7160..8e8f29457 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -706,7 +706,7 @@ struct XAigerWriter IdString derived_name = orig_box_module->derive(module->design, cell->parameters); RTLIL::Module* 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()); + Pass::call_on_module(module->design, box_module, "proc"); int box_inputs = 0, box_outputs = 0; auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); -- cgit v1.2.3 From d1fccd5a2d63b265c1866cb4d54aba8f2c9d225c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 14:35:52 -0800 Subject: Remove unused --- backends/aiger/xaiger.cc | 5 ----- 1 file changed, 5 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8e8f29457..ce7b479ff 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -927,7 +927,6 @@ struct XAigerWriter void write_map(std::ostream &f, bool verbose_map) { dict input_lines; - dict init_lines; dict output_lines; dict wire_lines; @@ -969,10 +968,6 @@ struct XAigerWriter f << it.second; log_assert(input_lines.size() == input_bits.size()); - init_lines.sort(); - for (auto &it : init_lines) - f << it.second; - int box_count = 0; for (auto cell : box_list) f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); -- cgit v1.2.3 From 07355729341e5104cf83210af280cb0cc6e8c7de Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 15:35:33 -0800 Subject: write_xaiger to use scratchpad for stats; cleanup abc9 --- backends/aiger/xaiger.cc | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ce7b479ff..e7d767721 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -93,7 +93,6 @@ struct XAigerWriter dict ordered_outputs; vector box_list; - bool omode = false; int mkgate(int a0, int a1) { @@ -579,11 +578,6 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - if (output_bits.empty()) { - output_bits.insert(State::S0); - omode = true; - } - for (auto bit : output_bits) { ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); @@ -594,12 +588,6 @@ struct XAigerWriter aig_o++; aig_outputs.push_back(ff_aig_map.at(bit)); } - - if (output_bits.empty()) { - aig_o++; - aig_outputs.push_back(0); - omode = true; - } } void write_aiger(std::ostream &f, bool ascii_mode) @@ -661,7 +649,6 @@ struct XAigerWriter f << "c"; - log_assert(!output_bits.empty()); auto write_buffer = [](std::stringstream &buffer, int i32) { int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); @@ -922,6 +909,11 @@ struct XAigerWriter //f.write(buffer_str.data(), buffer_str.size()); f << stringf("Generated by %s\n", yosys_version_str); + + module->design->scratchpad_set_int("write_xaiger.num_ands", and_map.size()); + module->design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size()); + module->design->scratchpad_set_int("write_xaiger.num_inputs", input_bits.size()); + module->design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size()); } void write_map(std::ostream &f, bool verbose_map) @@ -973,13 +965,9 @@ struct XAigerWriter f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); output_lines.sort(); - if (omode) - output_lines[State::S0] = "output 0 0 $__dummy__\n"; for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); - if (omode && output_bits.empty()) - f << "output " << output_lines.size() << " 0 $__dummy__\n"; wire_lines.sort(); for (auto &it : wire_lines) -- cgit v1.2.3 From b50de28c045e786f3140c95ab23cb2f426918093 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 18:00:49 -0800 Subject: Add abc9_ops -prep_holes --- backends/aiger/xaiger.cc | 140 +++-------------------------------------------- 1 file changed, 8 insertions(+), 132 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e7d767721..73af3bdfb 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -680,12 +680,11 @@ struct XAigerWriter // write_o_buffer(0); if (!box_list.empty() || !ff_bits.empty()) { - RTLIL::Module *holes_module = module->design->addModule("$__holes__"); + RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); log_assert(holes_module); dict cell_cache; - int port_id = 1; int box_count = 0; for (auto cell : box_list) { RTLIL::Module* orig_box_module = module->design->module(cell->type); @@ -696,85 +695,21 @@ struct XAigerWriter Pass::call_on_module(module->design, box_module, "proc"); int box_inputs = 0, box_outputs = 0; - auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); - Cell *holes_cell = r.first->second; - if (r.second && 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; - - // Since Module::derive() will create a new module, there - // is a chance that the ports will be alphabetically ordered - // again, which is a problem when carry-chains are involved. - // Inherit the port ordering from the original module here... - // (and set the port_id below, when iterating through those) - log_assert(GetSize(box_module->ports) == GetSize(orig_box_module->ports)); - box_module->ports = orig_box_module->ports; - } - // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) - int box_port_id = 1; for (const auto &port_name : box_module->ports) { RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); - if (r.second) - w->port_id = box_port_id++; - RTLIL::Wire *holes_wire; - 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)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - } - if (holes_cell) - port_sig.append(holes_wire); - } - if (w->port_output) { + box_inputs += GetSize(w); + 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("$abc%s.%s", cell->name.c_str(), log_id(w->name))); - else - holes_wire = holes_module->addWire(stringf("$abc%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_sig.append(holes_wire); - else - holes_module->connect(holes_wire, State::S0); - } - } - 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); - } } // For flops only, create an extra 1-bit input that drives a new wire // called ".$abc9_currQ" that is used below - if (box_module->get_bool_attribute("\\abc9_flop")) { - log_assert(holes_cell); - + if (box_module->get_bool_attribute("\\abc9_flop")) box_inputs++; - Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - } - Wire *w = holes_module->addWire(stringf("%s.$abc9_currQ", cell->name.c_str())); - holes_module->connect(w, holes_wire); - } write_h_buffer(box_inputs); write_h_buffer(box_outputs); @@ -815,79 +750,20 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { - log_push(); - - // NB: fixup_ports() will sort ports by name - //holes_module->fixup_ports(); - holes_module->check(); - - // Cannot techmap/aigmap/check all lib_whitebox-es outside of write_xaiger - // since boxes may contain parameters in which case `flatten` would have - // created a new $paramod ... - Pass::call_on_module(holes_module->design, holes_module, "flatten -wb; techmap; aigmap"); - - 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 the combinatorial control logic that feeds the box - // (i.e. clock enable, synchronous reset, etc.) - replace.insert(std::make_pair(SigSig(port,Q), SigSig(port,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 input port) we inserted above - Wire *currQ = holes_module->wire(stringf("%s.$abc9_currQ", driver.c_str())); - log_assert(currQ); - holes_module->connect(Q, currQ); - continue; - } - else if (!cell->type.in("$_NOT_", "$_AND_")) - log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - ++it; - } - - for (auto &conn : holes_module->connections_) { - auto it = replace.find(conn); - if (it != replace.end()) - conn = it->second; - } - - // Move into a new (temporary) design so that "clean" will only - // operate (and run checks on) this one module - RTLIL::Design *holes_design = new RTLIL::Design; - module->design->modules_.erase(holes_module->name); - holes_design->add(holes_module); - Pass::call(holes_design, "opt -purge"); + module->design->selection_stack.emplace_back(false); + module->design->selection().select(holes_module); std::stringstream a_buffer; XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); - delete holes_design; + + module->design->selection_stack.pop_back(); f << "a"; std::string buffer_str = a_buffer.str(); int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - - log_pop(); } } -- cgit v1.2.3 From e2bbe33a88c11b89e5a011c43d5a9c6b4623f9a7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 18:24:29 -0800 Subject: Get rid of holes_mode --- backends/aiger/xaiger.cc | 105 ++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 70 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 73af3bdfb..877e0e58a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -78,7 +78,7 @@ struct XAigerWriter Module *module; SigMap sigmap; - pool input_bits, output_bits, external_bits; + pool input_bits, output_bits; dict not_map, alias_map; dict> and_map; vector ci_bits, co_bits; @@ -136,7 +136,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) + XAigerWriter(Module *module) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -166,9 +166,7 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - if (holes_mode) - output_bits.insert(wirebit); - //external_bits.insert(wirebit); + output_bits.insert(wirebit); } continue; } @@ -182,10 +180,7 @@ struct XAigerWriter if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - if (holes_mode) - output_bits.insert(wirebit); - else - external_bits.insert(wirebit); + output_bits.insert(wirebit); } if (wire->port_input && wire->port_output) @@ -207,11 +202,9 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - if (!holes_mode) { - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_drivers[Y].insert(cell->name); - } + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); continue; } @@ -224,17 +217,13 @@ struct XAigerWriter unused_bits.erase(B); undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); - if (!holes_mode) { - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_users[B].insert(cell->name); - bit_drivers[Y].insert(cell->name); - } + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); continue; } - log_assert(!holes_mode); - if (cell->type == "$__ABC9_FF_") { SigBit D = sigmap(cell->getPort("\\D").as_bit()); @@ -298,7 +287,7 @@ struct XAigerWriter if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); - if (is_input) { + if (is_input) for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; @@ -306,13 +295,19 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - if (holes_mode) - output_bits.insert(b); - else - external_bits.insert(b); + output_bits.insert(b); } } - } + + if (is_output) + for (auto b : c.second) { + Wire *w = b.wire; + if (!w) continue; + SigBit O = sigmap(b); + if (O != b) + alias_map[O] = b; + input_bits.insert(O); + } } //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); @@ -495,57 +490,27 @@ struct XAigerWriter // TODO: Free memory from toposort, bit_drivers, bit_users } - if (!holes_mode) - for (auto cell : module->cells()) - if (!module->selected(cell)) - for (auto &conn : cell->connections()) - if (cell->input(conn.first)) - for (auto wirebit : conn.second) - if (sigmap(wirebit).wire) - external_bits.insert(wirebit); - - // For all bits consumed outside of the selected cells, - // but driven from a selected cell, then add it as - // a primary output - for (auto wirebit : external_bits) { - SigBit bit = sigmap(wirebit); - if (!bit.wire) - continue; - if (!undriven_bits.count(bit)) { - if (bit != wirebit) - alias_map[wirebit] = bit; - output_bits.insert(wirebit); - } - } - for (auto bit : input_bits) - undriven_bits.erase(sigmap(bit)); + undriven_bits.erase(bit); for (auto bit : output_bits) unused_bits.erase(sigmap(bit)); for (auto bit : unused_bits) undriven_bits.erase(bit); - - // Make all undriven bits a primary input - if (!holes_mode) + if (!undriven_bits.empty()) { for (auto bit : undriven_bits) { + log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); input_bits.insert(bit); - undriven_bits.erase(bit); } - - if (holes_mode) { - struct sort_by_port_id { - bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { - return a.wire->port_id < b.wire->port_id; - } - }; - input_bits.sort(sort_by_port_id()); - output_bits.sort(sort_by_port_id()); - } - else { - input_bits.sort(); - output_bits.sort(); + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } + struct sort_by_port_id { + bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { + return a.wire->port_id < b.wire->port_id; + } + }; + input_bits.sort(sort_by_port_id()); + output_bits.sort(sort_by_port_id()); not_map.sort(); and_map.sort(); @@ -754,7 +719,7 @@ struct XAigerWriter module->design->selection().select(holes_module); std::stringstream a_buffer; - XAigerWriter writer(holes_module, true /* holes_mode */); + XAigerWriter writer(holes_module); writer.write_aiger(a_buffer, false /*ascii_mode*/); module->design->selection_stack.pop_back(); -- cgit v1.2.3 From 65baefecd39b3be641b9a6be350d2ae83854cacc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 18:26:35 -0800 Subject: Rid unnecessary if --- backends/aiger/xaiger.cc | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 877e0e58a..35fb8d5dc 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -714,22 +714,20 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - if (holes_module) { - module->design->selection_stack.emplace_back(false); - module->design->selection().select(holes_module); + module->design->selection_stack.emplace_back(false); + module->design->selection().select(holes_module); - std::stringstream a_buffer; - XAigerWriter writer(holes_module); - writer.write_aiger(a_buffer, false /*ascii_mode*/); + std::stringstream a_buffer; + XAigerWriter writer(holes_module); + writer.write_aiger(a_buffer, false /*ascii_mode*/); - module->design->selection_stack.pop_back(); + module->design->selection_stack.pop_back(); - f << "a"; - std::string buffer_str = a_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - } + f << "a"; + buffer_str = a_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); } f << "h"; -- cgit v1.2.3 From 88334cab891d47778931c1ea0060fd107052e189 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 18:49:33 -0800 Subject: Cleanup --- backends/aiger/xaiger.cc | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 35fb8d5dc..9e0a56963 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -645,19 +645,12 @@ struct XAigerWriter // write_o_buffer(0); if (!box_list.empty() || !ff_bits.empty()) { - RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); - log_assert(holes_module); - - dict cell_cache; - int box_count = 0; for (auto cell : box_list) { RTLIL::Module* orig_box_module = module->design->module(cell->type); log_assert(orig_box_module); IdString derived_name = orig_box_module->derive(module->design, cell->parameters); RTLIL::Module* box_module = module->design->module(derived_name); - if (box_module->has_processes()) - Pass::call_on_module(module->design, box_module, "proc"); int box_inputs = 0, box_outputs = 0; // NB: Assume box_module->ports are sorted alphabetically @@ -714,6 +707,9 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); + log_assert(holes_module); + module->design->selection_stack.emplace_back(false); module->design->selection().select(holes_module); -- cgit v1.2.3 From b42b64e8ed713b0e9810f18db7cafcf356e2b4f6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 19:23:54 -0800 Subject: Move Pass::call() out of abc9_ops into abc9 --- backends/aiger/xaiger.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 9e0a56963..830c86787 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -710,6 +710,10 @@ struct XAigerWriter RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); log_assert(holes_module); + for (auto cell : holes_module->cells()) + if (!cell->type.in("$_NOT_", "$_AND_")) + log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); + module->design->selection_stack.emplace_back(false); module->design->selection().select(holes_module); -- cgit v1.2.3 From 7997e2a90fd37886241b7eb657408177ef7f6fa7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 18:24:29 -0800 Subject: Get rid of holes_mode --- backends/aiger/xaiger.cc | 105 ++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 70 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e7d767721..277017dfd 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -78,7 +78,7 @@ struct XAigerWriter Module *module; SigMap sigmap; - pool input_bits, output_bits, external_bits; + pool input_bits, output_bits; dict not_map, alias_map; dict> and_map; vector ci_bits, co_bits; @@ -136,7 +136,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) + XAigerWriter(Module *module) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -166,9 +166,7 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - if (holes_mode) - output_bits.insert(wirebit); - //external_bits.insert(wirebit); + output_bits.insert(wirebit); } continue; } @@ -182,10 +180,7 @@ struct XAigerWriter if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - if (holes_mode) - output_bits.insert(wirebit); - else - external_bits.insert(wirebit); + output_bits.insert(wirebit); } if (wire->port_input && wire->port_output) @@ -207,11 +202,9 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - if (!holes_mode) { - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_drivers[Y].insert(cell->name); - } + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); continue; } @@ -224,17 +217,13 @@ struct XAigerWriter unused_bits.erase(B); undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); - if (!holes_mode) { - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_users[B].insert(cell->name); - bit_drivers[Y].insert(cell->name); - } + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); continue; } - log_assert(!holes_mode); - if (cell->type == "$__ABC9_FF_") { SigBit D = sigmap(cell->getPort("\\D").as_bit()); @@ -298,7 +287,7 @@ struct XAigerWriter if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); - if (is_input) { + if (is_input) for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; @@ -306,13 +295,19 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - if (holes_mode) - output_bits.insert(b); - else - external_bits.insert(b); + output_bits.insert(b); } } - } + + if (is_output) + for (auto b : c.second) { + Wire *w = b.wire; + if (!w) continue; + SigBit O = sigmap(b); + if (O != b) + alias_map[O] = b; + input_bits.insert(O); + } } //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); @@ -495,57 +490,27 @@ struct XAigerWriter // TODO: Free memory from toposort, bit_drivers, bit_users } - if (!holes_mode) - for (auto cell : module->cells()) - if (!module->selected(cell)) - for (auto &conn : cell->connections()) - if (cell->input(conn.first)) - for (auto wirebit : conn.second) - if (sigmap(wirebit).wire) - external_bits.insert(wirebit); - - // For all bits consumed outside of the selected cells, - // but driven from a selected cell, then add it as - // a primary output - for (auto wirebit : external_bits) { - SigBit bit = sigmap(wirebit); - if (!bit.wire) - continue; - if (!undriven_bits.count(bit)) { - if (bit != wirebit) - alias_map[wirebit] = bit; - output_bits.insert(wirebit); - } - } - for (auto bit : input_bits) - undriven_bits.erase(sigmap(bit)); + undriven_bits.erase(bit); for (auto bit : output_bits) unused_bits.erase(sigmap(bit)); for (auto bit : unused_bits) undriven_bits.erase(bit); - - // Make all undriven bits a primary input - if (!holes_mode) + if (!undriven_bits.empty()) { for (auto bit : undriven_bits) { + log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); input_bits.insert(bit); - undriven_bits.erase(bit); } - - if (holes_mode) { - struct sort_by_port_id { - bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { - return a.wire->port_id < b.wire->port_id; - } - }; - input_bits.sort(sort_by_port_id()); - output_bits.sort(sort_by_port_id()); - } - else { - input_bits.sort(); - output_bits.sort(); + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } + struct sort_by_port_id { + bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { + return a.wire->port_id < b.wire->port_id; + } + }; + input_bits.sort(sort_by_port_id()); + output_bits.sort(sort_by_port_id()); not_map.sort(); and_map.sort(); @@ -877,7 +842,7 @@ struct XAigerWriter Pass::call(holes_design, "opt -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module, true /* holes_mode */); + XAigerWriter writer(holes_module); writer.write_aiger(a_buffer, false /*ascii_mode*/); delete holes_design; -- cgit v1.2.3 From 436c96e2fba0d7f73adb0ebb2b69821fe1dfc58c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 23:29:14 -0800 Subject: Revert "Get rid of holes_mode" This reverts commit 7997e2a90fd37886241b7eb657408177ef7f6fa7. --- backends/aiger/xaiger.cc | 105 +++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 35 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 277017dfd..e7d767721 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -78,7 +78,7 @@ struct XAigerWriter Module *module; SigMap sigmap; - pool input_bits, output_bits; + pool input_bits, output_bits, external_bits; dict not_map, alias_map; dict> and_map; vector ci_bits, co_bits; @@ -136,7 +136,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module) : module(module), sigmap(module) + XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -166,7 +166,9 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - output_bits.insert(wirebit); + if (holes_mode) + output_bits.insert(wirebit); + //external_bits.insert(wirebit); } continue; } @@ -180,7 +182,10 @@ struct XAigerWriter if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - output_bits.insert(wirebit); + if (holes_mode) + output_bits.insert(wirebit); + else + external_bits.insert(wirebit); } if (wire->port_input && wire->port_output) @@ -202,9 +207,11 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_drivers[Y].insert(cell->name); + if (!holes_mode) { + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); + } continue; } @@ -217,13 +224,17 @@ struct XAigerWriter unused_bits.erase(B); undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_users[B].insert(cell->name); - bit_drivers[Y].insert(cell->name); + if (!holes_mode) { + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); + } continue; } + log_assert(!holes_mode); + if (cell->type == "$__ABC9_FF_") { SigBit D = sigmap(cell->getPort("\\D").as_bit()); @@ -287,7 +298,7 @@ struct XAigerWriter if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); - if (is_input) + if (is_input) { for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; @@ -295,19 +306,13 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - output_bits.insert(b); + if (holes_mode) + output_bits.insert(b); + else + external_bits.insert(b); } } - - if (is_output) - for (auto b : c.second) { - Wire *w = b.wire; - if (!w) continue; - SigBit O = sigmap(b); - if (O != b) - alias_map[O] = b; - input_bits.insert(O); - } + } } //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); @@ -490,27 +495,57 @@ struct XAigerWriter // TODO: Free memory from toposort, bit_drivers, bit_users } + if (!holes_mode) + for (auto cell : module->cells()) + if (!module->selected(cell)) + for (auto &conn : cell->connections()) + if (cell->input(conn.first)) + for (auto wirebit : conn.second) + if (sigmap(wirebit).wire) + external_bits.insert(wirebit); + + // For all bits consumed outside of the selected cells, + // but driven from a selected cell, then add it as + // a primary output + for (auto wirebit : external_bits) { + SigBit bit = sigmap(wirebit); + if (!bit.wire) + continue; + if (!undriven_bits.count(bit)) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); + } + } + for (auto bit : input_bits) - undriven_bits.erase(bit); + undriven_bits.erase(sigmap(bit)); for (auto bit : output_bits) unused_bits.erase(sigmap(bit)); for (auto bit : unused_bits) undriven_bits.erase(bit); - if (!undriven_bits.empty()) { + + // Make all undriven bits a primary input + if (!holes_mode) for (auto bit : undriven_bits) { - log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); input_bits.insert(bit); + undriven_bits.erase(bit); } - log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + + if (holes_mode) { + struct sort_by_port_id { + bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { + return a.wire->port_id < b.wire->port_id; + } + }; + input_bits.sort(sort_by_port_id()); + output_bits.sort(sort_by_port_id()); + } + else { + input_bits.sort(); + output_bits.sort(); } - struct sort_by_port_id { - bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { - return a.wire->port_id < b.wire->port_id; - } - }; - input_bits.sort(sort_by_port_id()); - output_bits.sort(sort_by_port_id()); not_map.sort(); and_map.sort(); @@ -842,7 +877,7 @@ struct XAigerWriter Pass::call(holes_design, "opt -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module); + XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); delete holes_design; -- cgit v1.2.3 From 3798fa3bead6b944ebdee892c9bf5231559766f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 09:59:17 -0800 Subject: Retry getting rid of write_xaiger's holes_mode --- backends/aiger/xaiger.cc | 122 ++++++++++++++++------------------------------- 1 file changed, 41 insertions(+), 81 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e7d767721..40cf72548 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -136,11 +136,10 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) + XAigerWriter(Module *module) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; - pool inout_bits; // promote public wires for (auto wire : module->wires()) @@ -157,7 +156,12 @@ struct XAigerWriter if (wire->get_bool_attribute(ID::keep)) sigmap.add(wire); - for (auto wire : module->wires()) + // First, collect all the ports in port_id order + // since module->wires() could be sorted + // alphabetically + for (auto port : module->ports) { + auto wire = module->wire(port); + log_assert(wire); for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -166,30 +170,32 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - if (holes_mode) - output_bits.insert(wirebit); - //external_bits.insert(wirebit); + output_bits.insert(wirebit); } continue; } - undriven_bits.insert(bit); - unused_bits.insert(bit); - if (wire->port_input) input_bits.insert(bit); if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - if (holes_mode) - output_bits.insert(wirebit); - else - external_bits.insert(wirebit); + output_bits.insert(wirebit); } + } + } + + for (auto wire : module->wires()) + for (int i = 0; i < GetSize(wire); i++) + { + SigBit wirebit(wire, i); + SigBit bit = sigmap(wirebit); - if (wire->port_input && wire->port_output) - inout_bits.insert(wirebit); + if (bit.wire) { + undriven_bits.insert(bit); + unused_bits.insert(bit); + } } // TODO: Speed up toposort -- ultimately we care about @@ -207,11 +213,9 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - if (!holes_mode) { - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_drivers[Y].insert(cell->name); - } + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); continue; } @@ -224,17 +228,13 @@ struct XAigerWriter unused_bits.erase(B); undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); - if (!holes_mode) { - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_users[B].insert(cell->name); - bit_drivers[Y].insert(cell->name); - } + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); continue; } - log_assert(!holes_mode); - if (cell->type == "$__ABC9_FF_") { SigBit D = sigmap(cell->getPort("\\D").as_bit()); @@ -298,7 +298,7 @@ struct XAigerWriter if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); - if (is_input) { + if (is_input) for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; @@ -306,13 +306,9 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - if (holes_mode) - output_bits.insert(b); - else - external_bits.insert(b); + output_bits.insert(b); } } - } } //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); @@ -495,29 +491,6 @@ struct XAigerWriter // TODO: Free memory from toposort, bit_drivers, bit_users } - if (!holes_mode) - for (auto cell : module->cells()) - if (!module->selected(cell)) - for (auto &conn : cell->connections()) - if (cell->input(conn.first)) - for (auto wirebit : conn.second) - if (sigmap(wirebit).wire) - external_bits.insert(wirebit); - - // For all bits consumed outside of the selected cells, - // but driven from a selected cell, then add it as - // a primary output - for (auto wirebit : external_bits) { - SigBit bit = sigmap(wirebit); - if (!bit.wire) - continue; - if (!undriven_bits.count(bit)) { - if (bit != wirebit) - alias_map[wirebit] = bit; - output_bits.insert(wirebit); - } - } - for (auto bit : input_bits) undriven_bits.erase(sigmap(bit)); for (auto bit : output_bits) @@ -526,33 +499,18 @@ struct XAigerWriter undriven_bits.erase(bit); // Make all undriven bits a primary input - if (!holes_mode) - for (auto bit : undriven_bits) { - input_bits.insert(bit); - undriven_bits.erase(bit); - } - - if (holes_mode) { - struct sort_by_port_id { - bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { - return a.wire->port_id < b.wire->port_id; - } - }; - input_bits.sort(sort_by_port_id()); - output_bits.sort(sort_by_port_id()); - } - else { - input_bits.sort(); - output_bits.sort(); + for (auto bit : undriven_bits) { + input_bits.insert(bit); + undriven_bits.erase(bit); } - not_map.sort(); - and_map.sort(); - aig_map[State::S0] = 0; aig_map[State::S1] = 1; - for (auto bit : input_bits) { + // pool<> iterates in LIFO order... + for (int i = input_bits.size()-1; i >= 0; i--) { + const auto &bit = *input_bits.element(i); + log_dump(bit, i); aig_m++, aig_i++; log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; @@ -578,7 +536,9 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - for (auto bit : output_bits) { + // pool<> iterates in LIFO order... + for (int i = output_bits.size()-1; i >= 0; i--) { + const auto &bit = *output_bits.element(i); ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -877,7 +837,7 @@ struct XAigerWriter Pass::call(holes_design, "opt -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module, true /* holes_mode */); + XAigerWriter writer(holes_module); writer.write_aiger(a_buffer, false /*ascii_mode*/); delete holes_design; -- cgit v1.2.3 From 134e70e8e7798dd1e841b8deac2165c9f334ba09 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 10:21:11 -0800 Subject: write_xaiger: be more precise with ff_bits, remove ff_aig_map --- backends/aiger/xaiger.cc | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 40cf72548..650ceba7a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -82,7 +82,7 @@ struct XAigerWriter dict not_map, alias_map; dict> and_map; vector ci_bits, co_bits; - dict> ff_bits; + dict> ff_bits; dict arrival_times; vector> aig_gates; @@ -242,7 +242,7 @@ struct XAigerWriter unused_bits.erase(D); undriven_bits.erase(Q); alias_map[Q] = D; - auto r = ff_bits.insert(std::make_pair(D, std::make_pair(0, 2))); + auto r = ff_bits.insert(std::make_pair(D, std::make_tuple(Q, 0, 2))); log_assert(r.second); continue; } @@ -348,25 +348,26 @@ struct XAigerWriter auto it = cell->attributes.find(ID(abc9_mergeability)); log_assert(it != cell->attributes.end()); - rhs.first = it->second.as_int(); + std::get<1>(rhs) = it->second.as_int(); cell->attributes.erase(it); it = cell->attributes.find(ID(abc9_init)); log_assert(it != cell->attributes.end()); log_assert(GetSize(it->second) == 1); if (it->second[0] == State::S1) - rhs.second = 1; + std::get<2>(rhs) = 1; else if (it->second[0] == State::S0) - rhs.second = 0; + std::get<2>(rhs) = 0; else { log_assert(it->second[0] == State::Sx); - rhs.second = 0; + std::get<2>(rhs) = 0; } cell->attributes.erase(it); + const SigBit &q = std::get<0>(rhs); auto arrival = r.first->second.second; if (arrival) - arrival_times[d] = arrival; + arrival_times[q] = arrival; } for (auto &it : bit_users) @@ -510,25 +511,22 @@ struct XAigerWriter // pool<> iterates in LIFO order... for (int i = input_bits.size()-1; i >= 0; i--) { const auto &bit = *input_bits.element(i); - log_dump(bit, i); aig_m++, aig_i++; log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } for (const auto &i : ff_bits) { - const SigBit &bit = i.first; + const SigBit &q = std::get<0>(i.second); aig_m++, aig_i++; - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; + log_assert(!aig_map.count(q)); + aig_map[q] = 2*aig_m; } - dict ff_aig_map; for (auto &bit : ci_bits) { aig_m++, aig_i++; - auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); - if (!r.second) - ff_aig_map[bit] = 2*aig_m; + log_assert(!aig_map.count(bit)); + aig_map[bit] = 2*aig_m; } for (auto bit : co_bits) { @@ -544,9 +542,9 @@ struct XAigerWriter } for (auto &i : ff_bits) { - const SigBit &bit = i.first; + const SigBit &d = i.first; aig_o++; - aig_outputs.push_back(ff_aig_map.at(bit)); + aig_outputs.push_back(aig_map.at(d)); } } @@ -752,13 +750,13 @@ struct XAigerWriter write_s_buffer(ff_bits.size()); for (const auto &i : ff_bits) { - const SigBit &bit = i.first; - int mergeability = i.second.first; + const SigBit &q = std::get<0>(i.second); + int mergeability = std::get<1>(i.second); log_assert(mergeability > 0); write_r_buffer(mergeability); - int init = i.second.second; + int init = std::get<2>(i.second); write_s_buffer(init); - write_i_buffer(arrival_times.at(bit, 0)); + write_i_buffer(arrival_times.at(q, 0)); //write_o_buffer(0); } -- cgit v1.2.3 From cac7f5d82eb2760bcc248d15315b0d8460c92cb0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 16:12:40 -0800 Subject: Do not re-order carry chain ports, just precompute iteration order --- backends/aiger/xaiger.cc | 54 ++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 650ceba7a..3e40562b7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -93,6 +93,7 @@ struct XAigerWriter dict ordered_outputs; vector box_list; + dict> box_ports; int mkgate(int a0, int a1) { @@ -404,12 +405,34 @@ struct XAigerWriter bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); + auto r = box_ports.insert(cell->type); + 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; + for (const auto &port_name : box_module->ports) { + auto w = box_module->wire(port_name); + log_assert(w); + if (w->get_bool_attribute("\\abc9_carry")) { + if (w->port_input) + carry_in = port_name; + if (w->port_output) + carry_out = port_name; + } + else + r.first->second.push_back(port_name); + } + if (carry_in != IdString()) { + log_assert(carry_out != IdString()); + r.first->second.push_back(carry_in); + r.first->second.push_back(carry_out); + } + } + // 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 - // NB: Assume box_module->ports are sorted alphabetically - // (as RTLIL::Module::fixup_ports() would do) - for (const auto &port_name : box_module->ports) { - RTLIL::Wire* w = box_module->wire(port_name); + for (auto port_name : r.first->second) { + auto w = box_module->wire(port_name); log_assert(w); auto it = cell->connections_.find(port_name); if (w->port_input) { @@ -424,7 +447,7 @@ struct XAigerWriter cell->setPort(port_name, rhs); } - for (auto b : rhs.bits()) { + for (auto b : rhs) { SigBit I = sigmap(b); if (b == RTLIL::Sx) b = State::S0; @@ -455,11 +478,10 @@ struct XAigerWriter } for (const auto &b : rhs.bits()) { - ci_bits.emplace_back(b); SigBit O = sigmap(b); if (O != b) alias_map[O] = b; - input_bits.erase(O); + ci_bits.emplace_back(b); undriven_bits.erase(O); } } @@ -653,33 +675,21 @@ struct XAigerWriter if (box_module->has_processes()) Pass::call_on_module(module->design, box_module, "proc"); - int box_inputs = 0, box_outputs = 0; auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); Cell *holes_cell = r.first->second; if (r.second && 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; - - // Since Module::derive() will create a new module, there - // is a chance that the ports will be alphabetically ordered - // again, which is a problem when carry-chains are involved. - // Inherit the port ordering from the original module here... - // (and set the port_id below, when iterating through those) - log_assert(GetSize(box_module->ports) == GetSize(orig_box_module->ports)); - box_module->ports = orig_box_module->ports; } - // NB: Assume box_module->ports are sorted alphabetically - // (as RTLIL::Module::fixup_ports() would do) - int box_port_id = 1; - for (const auto &port_name : box_module->ports) { + int box_inputs = 0, box_outputs = 0; + for (auto port_name : box_ports.at(cell->type)) { RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); - if (r.second) - w->port_id = box_port_id++; RTLIL::Wire *holes_wire; RTLIL::SigSpec port_sig; + if (w->port_input) for (int i = 0; i < GetSize(w); i++) { box_inputs++; -- cgit v1.2.3 From 96db05aaefd970c819ba1f75b7246c5958527b8b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 17:06:03 -0800 Subject: parse_xaiger to not take box_lookup --- backends/aiger/xaiger.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3e40562b7..be900f0e7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -414,14 +414,25 @@ struct XAigerWriter auto w = box_module->wire(port_name); log_assert(w); if (w->get_bool_attribute("\\abc9_carry")) { - if (w->port_input) + if (w->port_input) { + if (carry_in != IdString()) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module)); carry_in = port_name; - if (w->port_output) + } + if (w->port_output) { + if (carry_out != IdString()) + log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module)); carry_out = port_name; + } } else r.first->second.push_back(port_name); } + + if (carry_in != IdString() && carry_out == IdString()) + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_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(box_module)); if (carry_in != IdString()) { log_assert(carry_out != IdString()); r.first->second.push_back(carry_in); -- cgit v1.2.3 From ac808c5e2aa0fbcfb5b56160131fcc61ba13da05 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 22:54:56 -0800 Subject: attributes.count() -> get_bool_attribute() --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index be900f0e7..77659b4d8 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -284,7 +284,7 @@ struct XAigerWriter toposort.node(cell->name); - if (inst_module->attributes.count("\\abc9_flop")) + if (inst_module->get_bool_attribute("\\abc9_flop")) flop_boxes.push_back(cell); continue; } -- cgit v1.2.3 From 11577b46fcfa6c9aef4c3ed83e508ab07bc722c7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 1 Jan 2020 08:38:23 -0800 Subject: Get rid of (* abc9_keep *) in write_xaiger too --- backends/aiger/xaiger.cc | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 77659b4d8..9c6152dff 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -250,7 +250,12 @@ struct XAigerWriter RTLIL::Module* inst_module = module->design->module(cell->type); if (inst_module) { - bool abc9_box = inst_module->attributes.count("\\abc9_box_id") && !cell->get_bool_attribute("\\abc9_keep"); + bool abc9_box = inst_module->attributes.count("\\abc9_box_id"); + bool abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); + // The lack of an abc9_mergeability attribute indicates that + // we do want to keep this flop, so do not treat it as a box + if (abc9_flop && !cell->attributes.count("\\abc9_mergeability")) + abc9_box = false; for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); @@ -279,15 +284,15 @@ struct XAigerWriter } } - if (abc9_box) { - abc9_box_seen = true; + if (abc9_box) { + abc9_box_seen = true; - toposort.node(cell->name); + toposort.node(cell->name); - if (inst_module->get_bool_attribute("\\abc9_flop")) - flop_boxes.push_back(cell); - continue; - } + if (abc9_flop) + flop_boxes.push_back(cell); + continue; + } } bool cell_known = inst_module || cell->known(); @@ -322,11 +327,12 @@ struct XAigerWriter SigBit d; if (r.second) { for (const auto &conn : cell->connections()) { - const SigSpec &rhs = conn.second; - if (!rhs.is_bit()) + if (!conn.second.is_bit()) continue; - if (!ff_bits.count(rhs)) + d = conn.second; + if (!ff_bits.count(d)) continue; + r.first->second.first = conn.first; Module *inst_module = module->design->module(cell->type); Wire *wire = inst_module->wire(conn.first); @@ -337,7 +343,6 @@ struct XAigerWriter log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(wire), log_id(cell->type)); r.first->second.second = jt->second.as_int(); } - d = rhs; log_assert(d == sigmap(d)); break; } @@ -399,8 +404,7 @@ struct XAigerWriter log_assert(cell); RTLIL::Module* box_module = module->design->module(cell->type); - if (!box_module || !box_module->attributes.count("\\abc9_box_id") - || cell->get_bool_attribute("\\abc9_keep")) + if (!box_module || !box_module->attributes.count("\\abc9_box_id")) continue; bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); @@ -434,7 +438,6 @@ struct XAigerWriter if (carry_in == IdString() && carry_out != IdString()) log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(box_module)); if (carry_in != IdString()) { - log_assert(carry_out != IdString()); r.first->second.push_back(carry_in); r.first->second.push_back(carry_out); } -- cgit v1.2.3 From 8e507bd80785db9fa6723eada4214a5a06516cae Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 12:36:54 -0800 Subject: abc9 -keepff -> -dff; refactor dff operations --- backends/aiger/xaiger.cc | 136 ++++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 89 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 9c6152dff..053f9d835 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -82,7 +82,7 @@ struct XAigerWriter dict not_map, alias_map; dict> and_map; vector ci_bits, co_bits; - dict> ff_bits; + dict ff_bits; dict arrival_times; vector> aig_gates; @@ -204,7 +204,6 @@ struct XAigerWriter dict> bit_drivers, bit_users; TopoSort toposort; bool abc9_box_seen = false; - std::vector flop_boxes; for (auto cell : module->selected_cells()) { if (cell->type == "$_NOT_") @@ -236,14 +235,17 @@ struct XAigerWriter continue; } - if (cell->type == "$__ABC9_FF_") + 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 = ff_bits.insert(std::make_pair(D, std::make_tuple(Q, 0, 2))); + auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell)); log_assert(r.second); continue; } @@ -252,14 +254,25 @@ struct XAigerWriter if (inst_module) { bool abc9_box = inst_module->attributes.count("\\abc9_box_id"); bool abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); - // The lack of an abc9_mergeability attribute indicates that - // we do want to keep this flop, so do not treat it as a box - if (abc9_flop && !cell->attributes.count("\\abc9_mergeability")) + if (abc9_box && cell->get_bool_attribute("\\abc9_keep")) abc9_box = false; for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); + if (abc9_box) { + // Ignore inout for the sake of topographical ordering + if (port_wire->port_input && !port_wire->port_output) + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + if (port_wire->port_output) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + + if (!abc9_flop) + continue; + } + if (port_wire->port_output) { int arrival = 0; auto it = port_wire->attributes.find("\\abc9_arrival"); @@ -272,25 +285,11 @@ struct XAigerWriter for (auto bit : sigmap(conn.second)) arrival_times[bit] = arrival; } - - if (abc9_box) { - // Ignore inout for the sake of topographical ordering - if (port_wire->port_input && !port_wire->port_output) - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - if (port_wire->port_output) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); - } } if (abc9_box) { abc9_box_seen = true; - toposort.node(cell->name); - - if (abc9_flop) - flop_boxes.push_back(cell); continue; } } @@ -321,61 +320,6 @@ struct XAigerWriter } if (abc9_box_seen) { - dict> flop_q; - for (auto cell : flop_boxes) { - auto r = flop_q.insert(std::make_pair(cell->type, std::make_pair(IdString(), 0))); - SigBit d; - if (r.second) { - for (const auto &conn : cell->connections()) { - if (!conn.second.is_bit()) - continue; - d = conn.second; - if (!ff_bits.count(d)) - continue; - - r.first->second.first = conn.first; - Module *inst_module = module->design->module(cell->type); - Wire *wire = inst_module->wire(conn.first); - log_assert(wire); - auto jt = wire->attributes.find("\\abc9_arrival"); - if (jt != wire->attributes.end()) { - if (jt->second.flags != 0) - log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(wire), log_id(cell->type)); - r.first->second.second = jt->second.as_int(); - } - log_assert(d == sigmap(d)); - break; - } - } - else - d = cell->getPort(r.first->second.first); - - auto &rhs = ff_bits.at(d); - - auto it = cell->attributes.find(ID(abc9_mergeability)); - log_assert(it != cell->attributes.end()); - std::get<1>(rhs) = it->second.as_int(); - cell->attributes.erase(it); - - it = cell->attributes.find(ID(abc9_init)); - log_assert(it != cell->attributes.end()); - log_assert(GetSize(it->second) == 1); - if (it->second[0] == State::S1) - std::get<2>(rhs) = 1; - else if (it->second[0] == State::S0) - std::get<2>(rhs) = 0; - else { - log_assert(it->second[0] == State::Sx); - std::get<2>(rhs) = 0; - } - cell->attributes.erase(it); - - const SigBit &q = std::get<0>(rhs); - auto arrival = r.first->second.second; - if (arrival) - arrival_times[q] = arrival; - } - for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) @@ -501,11 +445,11 @@ struct XAigerWriter } } - // Connect .$abc9_currQ (inserted by abc9_map.v) as an input to the flop box + // Connect .abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box if (box_module->get_bool_attribute("\\abc9_flop")) { - SigSpec rhs = module->wire(stringf("%s.$abc9_currQ", cell->name.c_str())); + SigSpec rhs = module->wire(stringf("%s.abc9_ff.Q", cell->name.c_str())); if (rhs.empty()) - log_error("'%s.$abc9_currQ' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); + log_error("'%s.abc9_ff.Q' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); for (auto b : rhs) { SigBit I = sigmap(b); @@ -553,7 +497,8 @@ struct XAigerWriter } for (const auto &i : ff_bits) { - const SigBit &q = std::get<0>(i.second); + const Cell *cell = i.second; + const SigBit &q = sigmap(cell->getPort("\\Q")); aig_m++, aig_i++; log_assert(!aig_map.count(q)); aig_map[q] = 2*aig_m; @@ -742,7 +687,7 @@ struct XAigerWriter } // For flops only, create an extra 1-bit input that drives a new wire - // called ".$abc9_currQ" that is used below + // called ".abc9_ff.Q" that is used below if (box_module->get_bool_attribute("\\abc9_flop")) { log_assert(holes_cell); @@ -754,7 +699,8 @@ struct XAigerWriter holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); } - Wire *w = holes_module->addWire(stringf("%s.$abc9_currQ", cell->name.c_str())); + Wire *w = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str())); + log_assert(w); holes_module->connect(w, holes_wire); } @@ -774,13 +720,25 @@ struct XAigerWriter write_s_buffer(ff_bits.size()); for (const auto &i : ff_bits) { - const SigBit &q = std::get<0>(i.second); - int mergeability = std::get<1>(i.second); + const SigBit &d = i.first; + const Cell *cell = i.second; + + int mergeability = cell->attributes.at(ID(abc9_mergeability)).as_int(); log_assert(mergeability > 0); write_r_buffer(mergeability); - int init = std::get<2>(i.second); - write_s_buffer(init); - write_i_buffer(arrival_times.at(q, 0)); + + Const init = cell->attributes.at(ID(abc9_init)); + log_assert(GetSize(init) == 1); + if (init == State::S1) + write_s_buffer(1); + else if (init == State::S0) + write_s_buffer(0); + else { + log_assert(init == State::Sx); + write_s_buffer(0); + } + + write_i_buffer(arrival_times.at(d, 0)); //write_o_buffer(0); } @@ -833,9 +791,9 @@ struct XAigerWriter 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" + // used to implement clock-enable functionality) with the ".abc9_ff.Q" // wire (which itself is driven an input port) we inserted above - Wire *currQ = holes_module->wire(stringf("%s.$abc9_currQ", driver.c_str())); + Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str())); log_assert(currQ); holes_module->connect(Q, currQ); continue; -- cgit v1.2.3 From 07feedfa736637952663dd8174123ea3bf1dddbc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 15:32:58 -0800 Subject: write_xaiger: get rid of external_bits dict --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 053f9d835..2b456bb9a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -78,7 +78,7 @@ struct XAigerWriter Module *module; SigMap sigmap; - pool input_bits, output_bits, external_bits; + pool input_bits, output_bits; dict not_map, alias_map; dict> and_map; vector ci_bits, co_bits; -- cgit v1.2.3 From dedea5a58d00b97180a9e0a2645f1018add00a36 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 17:25:14 -0800 Subject: Cleanup --- backends/aiger/xaiger.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2b456bb9a..faa722398 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -473,7 +473,7 @@ struct XAigerWriter } for (auto bit : input_bits) - undriven_bits.erase(sigmap(bit)); + undriven_bits.erase(bit); for (auto bit : output_bits) unused_bits.erase(sigmap(bit)); for (auto bit : unused_bits) @@ -700,7 +700,6 @@ struct XAigerWriter holes_module->ports.push_back(holes_wire->name); } Wire *w = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str())); - log_assert(w); holes_module->connect(w, holes_wire); } -- cgit v1.2.3 From e62eb02c1dd3074e58c9be64b8bb3b13b8d9a1ea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 3 Jan 2020 12:30:22 -0800 Subject: Restore write_xaiger's holes_mode since port_id order causes QoR regressions inside abc9 --- backends/aiger/xaiger.cc | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index faa722398..1f1b9dffe 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -137,7 +137,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module) : module(module), sigmap(module) + XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -157,12 +157,8 @@ struct XAigerWriter if (wire->get_bool_attribute(ID::keep)) sigmap.add(wire); - // First, collect all the ports in port_id order - // since module->wires() could be sorted - // alphabetically - for (auto port : module->ports) { - auto wire = module->wire(port); - log_assert(wire); + + for (auto wire : module->wires()) for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -176,6 +172,9 @@ struct XAigerWriter continue; } + undriven_bits.insert(bit); + unused_bits.insert(bit); + if (wire->port_input) input_bits.insert(bit); @@ -185,19 +184,6 @@ struct XAigerWriter output_bits.insert(wirebit); } } - } - - for (auto wire : module->wires()) - for (int i = 0; i < GetSize(wire); i++) - { - SigBit wirebit(wire, i); - SigBit bit = sigmap(wirebit); - - if (bit.wire) { - undriven_bits.insert(bit); - unused_bits.insert(bit); - } - } // TODO: Speed up toposort -- ultimately we care about // box ordering, but not individual AIG cells @@ -485,12 +471,20 @@ struct XAigerWriter undriven_bits.erase(bit); } + if (holes_mode) { + struct sort_by_port_id { + bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { + return a.wire->port_id < b.wire->port_id; + } + }; + input_bits.sort(sort_by_port_id()); + output_bits.sort(sort_by_port_id()); + } + aig_map[State::S0] = 0; aig_map[State::S1] = 1; - // pool<> iterates in LIFO order... - for (int i = input_bits.size()-1; i >= 0; i--) { - const auto &bit = *input_bits.element(i); + for (const auto &bit : input_bits) { aig_m++, aig_i++; log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; @@ -515,9 +509,7 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - // pool<> iterates in LIFO order... - for (int i = output_bits.size()-1; i >= 0; i--) { - const auto &bit = *output_bits.element(i); + for (const auto &bit : output_bits) { ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -816,7 +808,7 @@ struct XAigerWriter Pass::call(holes_design, "opt -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module); + XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); delete holes_design; -- cgit v1.2.3 From e1f494ab1db523f90cf1e386ba133b1550dcb300 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 3 Jan 2020 13:08:52 -0800 Subject: WIP --- backends/aiger/xaiger.cc | 164 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 141 insertions(+), 23 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 42a26cbf9..02ab47ac0 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -619,26 +619,90 @@ struct XAigerWriter // write_o_buffer(0); if (!box_list.empty() || !ff_bits.empty()) { + 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* orig_box_module = module->design->module(cell->type); log_assert(orig_box_module); IdString derived_name = orig_box_module->derive(module->design, cell->parameters); RTLIL::Module* box_module = module->design->module(derived_name); + if (box_module->has_processes()) + Pass::call_on_module(module->design, box_module, "proc"); + + auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); + Cell *holes_cell = r.first->second; + if (r.second && 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; + } int box_inputs = 0, box_outputs = 0; for (auto port_name : box_ports.at(cell->type)) { RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); + RTLIL::Wire *holes_wire; + RTLIL::SigSpec port_sig; + if (w->port_input) - box_inputs += GetSize(w); - if (w->port_output) + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + } + if (holes_cell) + port_sig.append(holes_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("$abc%s.%s", cell->name.c_str(), log_id(w->name))); + else + holes_wire = holes_module->addWire(stringf("$abc%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_sig.append(holes_wire); + else + holes_module->connect(holes_wire, State::S0); + } + } + 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); + } } - // For flops only, create an extra 1-bit input for abc9_ff.Q - if (box_module->get_bool_attribute("\\abc9_flop")) + // For flops only, create an extra 1-bit input that drives a new wire + // called ".abc9_ff.Q" that is used below + if (box_module->get_bool_attribute("\\abc9_flop")) { + log_assert(holes_cell); + box_inputs++; + Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + } + Wire *w = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str())); + log_assert(w); + holes_module->connect(w, holes_wire); + } write_h_buffer(box_inputs); write_h_buffer(box_outputs); @@ -690,27 +754,81 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); - log_assert(holes_module); - - for (auto cell : holes_module->cells()) - if (!cell->type.in("$_NOT_", "$_AND_")) - log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - - module->design->selection_stack.emplace_back(false); - module->design->selection().select(holes_module); - - std::stringstream a_buffer; - XAigerWriter writer(holes_module); - writer.write_aiger(a_buffer, false /*ascii_mode*/); + if (holes_module) { + log_push(); + + // NB: fixup_ports() will sort ports by name + //holes_module->fixup_ports(); + holes_module->check(); + + // Cannot techmap/aigmap/check all lib_whitebox-es outside of write_xaiger + // since boxes may contain parameters in which case `flatten` would have + // created a new $paramod ... + Pass::call_on_module(holes_module->design, holes_module, "flatten -wb; techmap; aigmap"); + + 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 the combinatorial control logic that feeds the box + // (i.e. clock enable, synchronous reset, etc.) + replace.insert(std::make_pair(SigSig(port,Q), SigSig(port,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_ff.Q" + // wire (which itself is driven an 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); + continue; + } + else if (!cell->type.in("$_NOT_", "$_AND_")) + log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); + ++it; + } - module->design->selection_stack.pop_back(); + for (auto &conn : holes_module->connections_) { + auto it = replace.find(conn); + if (it != replace.end()) + conn = it->second; + } - f << "a"; - buffer_str = a_buffer.str(); - buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); + // Move into a new (temporary) design so that "clean" will only + // operate (and run checks on) this one module + RTLIL::Design *holes_design = new RTLIL::Design; + module->design->modules_.erase(holes_module->name); + holes_design->add(holes_module); + Pass::call(holes_design, "opt -purge"); + + std::stringstream a_buffer; + XAigerWriter writer(holes_module); + writer.write_aiger(a_buffer, false /*ascii_mode*/); + delete holes_design; + + f << "a"; + std::string buffer_str = a_buffer.str(); + int32_t buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + + log_pop(); + } } f << "h"; -- cgit v1.2.3 From bb70915fb8adcd7ede7719174dea3bc9c04e613e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 3 Jan 2020 13:21:56 -0800 Subject: WIP --- backends/aiger/xaiger.cc | 75 ++++++------------------------------------------ 1 file changed, 8 insertions(+), 67 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 02ab47ac0..7e7a3a17e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -619,90 +619,30 @@ struct XAigerWriter // write_o_buffer(0); if (!box_list.empty() || !ff_bits.empty()) { - RTLIL::Module *holes_module = module->design->addModule("$__holes__"); + RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); log_assert(holes_module); dict cell_cache; - int port_id = 1; int box_count = 0; for (auto cell : box_list) { - RTLIL::Module* orig_box_module = module->design->module(cell->type); - log_assert(orig_box_module); - IdString derived_name = orig_box_module->derive(module->design, cell->parameters); - RTLIL::Module* box_module = module->design->module(derived_name); - if (box_module->has_processes()) - Pass::call_on_module(module->design, box_module, "proc"); - - auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); - Cell *holes_cell = r.first->second; - if (r.second && 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; - } + RTLIL::Module* box_module = module->design->module(cell->type); + log_assert(box_module); int box_inputs = 0, box_outputs = 0; - for (auto port_name : box_ports.at(cell->type)) { + for (auto port_name : box_module->ports) { RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); - RTLIL::Wire *holes_wire; - 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)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - } - if (holes_cell) - port_sig.append(holes_wire); - } - if (w->port_output) { + box_inputs += GetSize(w); + 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("$abc%s.%s", cell->name.c_str(), log_id(w->name))); - else - holes_wire = holes_module->addWire(stringf("$abc%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_sig.append(holes_wire); - else - holes_module->connect(holes_wire, State::S0); - } - } - 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); - } } // For flops only, create an extra 1-bit input that drives a new wire // called ".abc9_ff.Q" that is used below - if (box_module->get_bool_attribute("\\abc9_flop")) { - log_assert(holes_cell); - + if (box_module->get_bool_attribute("\\abc9_flop")) box_inputs++; - Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - } - Wire *w = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str())); - log_assert(w); - holes_module->connect(w, holes_wire); - } write_h_buffer(box_inputs); write_h_buffer(box_outputs); @@ -764,6 +704,7 @@ struct XAigerWriter // Cannot techmap/aigmap/check all lib_whitebox-es outside of write_xaiger // since boxes may contain parameters in which case `flatten` would have // created a new $paramod ... + Pass::call_on_module(holes_module->design, holes_module, "wbflip"); Pass::call_on_module(holes_module->design, holes_module, "flatten -wb; techmap; aigmap"); dict replace; -- cgit v1.2.3 From 559f3379e852f304a0255afcc37714b9d0da59d9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 3 Jan 2020 14:37:58 -0800 Subject: Preserve topo ordering from -prep_holes to write_xaiger --- backends/aiger/xaiger.cc | 236 ++++++++++++++++------------------------------- 1 file changed, 77 insertions(+), 159 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7e7a3a17e..ff3de65cc 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -78,7 +78,7 @@ struct XAigerWriter Module *module; SigMap sigmap; - pool input_bits, output_bits, external_bits; + pool input_bits, output_bits; dict not_map, alias_map; dict> and_map; vector ci_bits, co_bits; @@ -199,12 +199,6 @@ struct XAigerWriter } } - // TODO: Speed up toposort -- ultimately we care about - // box ordering, but not individual AIG cells - dict> bit_drivers, bit_users; - TopoSort toposort; - bool abc9_box_seen = false; - for (auto cell : module->selected_cells()) { if (cell->type == "$_NOT_") { @@ -213,9 +207,6 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_drivers[Y].insert(cell->name); continue; } @@ -228,10 +219,6 @@ struct XAigerWriter unused_bits.erase(B); undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_users[B].insert(cell->name); - bit_drivers[Y].insert(cell->name); continue; } @@ -257,22 +244,17 @@ struct XAigerWriter if (abc9_box && cell->get_bool_attribute("\\abc9_keep")) abc9_box = false; + if (abc9_box) { + int abc9_box_order = cell->attributes.at("\\abc9_box_order").as_int(); + if (GetSize(box_list) <= abc9_box_order) + box_list.resize(abc9_box_order+1); + box_list[abc9_box_order] = cell; + if (!abc9_flop) + continue; + } + for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); - - if (abc9_box) { - // Ignore inout for the sake of topographical ordering - if (port_wire->port_input && !port_wire->port_output) - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - if (port_wire->port_output) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); - - if (!abc9_flop) - continue; - } - if (port_wire->port_output) { int arrival = 0; auto it = port_wire->attributes.find("\\abc9_arrival"); @@ -286,12 +268,6 @@ struct XAigerWriter arrival_times[bit] = arrival; } } - - if (abc9_box) { - abc9_box_seen = true; - toposort.node(cell->name); - continue; - } } bool cell_known = inst_module || cell->known(); @@ -319,138 +295,56 @@ struct XAigerWriter //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } - if (abc9_box_seen) { - for (auto &it : bit_users) - if (bit_drivers.count(it.first)) - for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); - -#if 0 - toposort.analyze_loops = true; -#endif - bool no_loops YS_ATTRIBUTE(unused) = toposort.sort(); -#if 0 - unsigned i = 0; - for (auto &it : toposort.loops) { - log(" loop %d\n", i++); - for (auto cell_name : it) { - auto cell = module->cell(cell_name); - log_assert(cell); - log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str()); - } - } -#endif - log_assert(no_loops); - - for (auto cell_name : toposort.sorted) { - RTLIL::Cell *cell = module->cell(cell_name); - log_assert(cell); - - RTLIL::Module* box_module = module->design->module(cell->type); - if (!box_module || !box_module->attributes.count("\\abc9_box_id")) - continue; - - bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); - - auto r = box_ports.insert(cell->type); - 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; - for (const auto &port_name : box_module->ports) { - auto w = box_module->wire(port_name); - log_assert(w); - if (w->get_bool_attribute("\\abc9_carry")) { - if (w->port_input) { - if (carry_in != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module)); - carry_in = port_name; - } - if (w->port_output) { - if (carry_out != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module)); - carry_out = port_name; - } - } - else - r.first->second.push_back(port_name); - } + for (auto cell : box_list) { + log_assert(cell); - if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_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(box_module)); - if (carry_in != IdString()) { - r.first->second.push_back(carry_in); - r.first->second.push_back(carry_out); - } - } + RTLIL::Module* box_module = module->design->module(cell->type); + log_assert(box_module); + log_assert(box_module->attributes.count("\\abc9_box_id")); - // 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 r = box_ports.insert(cell->type); + 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; + for (const auto &port_name : box_module->ports) { auto w = box_module->wire(port_name); log_assert(w); - auto it = cell->connections_.find(port_name); - if (w->port_input) { - RTLIL::SigSpec rhs; - if (it != cell->connections_.end()) { - if (GetSize(it->second) < GetSize(w)) - it->second.append(RTLIL::SigSpec(State::S0, GetSize(w)-GetSize(it->second))); - rhs = it->second; - } - else { - rhs = RTLIL::SigSpec(State::S0, GetSize(w)); - cell->setPort(port_name, rhs); + if (w->get_bool_attribute("\\abc9_carry")) { + if (w->port_input) { + if (carry_in != IdString()) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module)); + carry_in = port_name; } - - for (auto b : rhs) { - SigBit I = sigmap(b); - if (b == RTLIL::Sx) - b = State::S0; - else if (I != b) { - if (I == RTLIL::Sx) - alias_map[b] = State::S0; - else - alias_map[b] = I; - } - co_bits.emplace_back(b); - unused_bits.erase(I); + if (w->port_output) { + if (carry_out != IdString()) + log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module)); + carry_out = port_name; } } - if (w->port_output) { - RTLIL::SigSpec rhs; - auto it = cell->connections_.find(w->name); - if (it != cell->connections_.end()) { - if (GetSize(it->second) < GetSize(w)) - it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second))); - rhs = it->second; - } - else { - Wire *wire = module->addWire(NEW_ID, GetSize(w)); - if (blackbox) - wire->set_bool_attribute(ID(abc9_padding)); - rhs = wire; - cell->setPort(port_name, rhs); - } + else + r.first->second.push_back(port_name); + } - for (const auto &b : rhs.bits()) { - SigBit O = sigmap(b); - if (O != b) - alias_map[O] = b; - ci_bits.emplace_back(b); - undriven_bits.erase(O); - } - } + if (carry_in != IdString() && carry_out == IdString()) + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_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(box_module)); + if (carry_in != IdString()) { + r.first->second.push_back(carry_in); + r.first->second.push_back(carry_out); } + } - // Connect .abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box - if (box_module->get_bool_attribute("\\abc9_flop")) { - SigSpec rhs = module->wire(stringf("%s.abc9_ff.Q", cell->name.c_str())); - if (rhs.empty()) - log_error("'%s.abc9_ff.Q' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); + bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); + // 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); + if (w->port_input) for (auto b : rhs) { SigBit I = sigmap(b); if (b == RTLIL::Sx) @@ -464,12 +358,36 @@ struct XAigerWriter co_bits.emplace_back(b); unused_bits.erase(I); } - } - - box_list.emplace_back(cell); + if (w->port_output) + for (const auto &b : rhs.bits()) { + SigBit O = sigmap(b); + if (O != b) + alias_map[O] = b; + ci_bits.emplace_back(b); + undriven_bits.erase(O); + } } - // TODO: Free memory from toposort, bit_drivers, bit_users + // Connect .abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box + if (box_module->get_bool_attribute("\\abc9_flop")) { + SigSpec rhs = module->wire(stringf("%s.abc9_ff.Q", cell->name.c_str())); + if (rhs.empty()) + log_error("'%s.abc9_ff.Q' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); + + for (auto b : rhs) { + SigBit I = sigmap(b); + if (b == RTLIL::Sx) + b = State::S0; + else if (I != b) { + if (I == RTLIL::Sx) + alias_map[b] = State::S0; + else + alias_map[b] = I; + } + co_bits.emplace_back(b); + unused_bits.erase(I); + } + } } for (auto bit : input_bits) -- cgit v1.2.3 From a819656972dd44c479422fa688874926d6239a95 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 3 Jan 2020 14:59:55 -0800 Subject: WIP --- backends/aiger/xaiger.cc | 56 ------------------------------------------------ 1 file changed, 56 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ff3de65cc..e9b4f07bf 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -336,8 +336,6 @@ struct XAigerWriter } } - bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); - // 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) { @@ -615,65 +613,11 @@ struct XAigerWriter if (holes_module) { log_push(); - // NB: fixup_ports() will sort ports by name - //holes_module->fixup_ports(); - holes_module->check(); - - // Cannot techmap/aigmap/check all lib_whitebox-es outside of write_xaiger - // since boxes may contain parameters in which case `flatten` would have - // created a new $paramod ... - Pass::call_on_module(holes_module->design, holes_module, "wbflip"); - Pass::call_on_module(holes_module->design, holes_module, "flatten -wb; techmap; aigmap"); - - 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 the combinatorial control logic that feeds the box - // (i.e. clock enable, synchronous reset, etc.) - replace.insert(std::make_pair(SigSig(port,Q), SigSig(port,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_ff.Q" - // wire (which itself is driven an 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); - continue; - } - else if (!cell->type.in("$_NOT_", "$_AND_")) - log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - ++it; - } - - for (auto &conn : holes_module->connections_) { - auto it = replace.find(conn); - if (it != replace.end()) - conn = it->second; - } - // Move into a new (temporary) design so that "clean" will only // operate (and run checks on) this one module RTLIL::Design *holes_design = new RTLIL::Design; module->design->modules_.erase(holes_module->name); holes_design->add(holes_module); - Pass::call(holes_design, "opt -purge"); std::stringstream a_buffer; XAigerWriter writer(holes_module); -- cgit v1.2.3 From 930f03e8830ed8a8023ff88207b97e757ae8496c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 3 Jan 2020 15:38:18 -0800 Subject: Call -prep_holes before aigmap; fix topo ordering --- backends/aiger/xaiger.cc | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e9b4f07bf..7ef744d04 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -199,7 +199,7 @@ struct XAigerWriter } } - for (auto cell : module->selected_cells()) { + for (auto cell : module->cells()) { if (cell->type == "$_NOT_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -613,16 +613,9 @@ struct XAigerWriter if (holes_module) { log_push(); - // Move into a new (temporary) design so that "clean" will only - // operate (and run checks on) this one module - RTLIL::Design *holes_design = new RTLIL::Design; - module->design->modules_.erase(holes_module->name); - holes_design->add(holes_module); - std::stringstream a_buffer; XAigerWriter writer(holes_module); writer.write_aiger(a_buffer, false /*ascii_mode*/); - delete holes_design; f << "a"; std::string buffer_str = a_buffer.str(); -- cgit v1.2.3 From 6556a1347ab56b022a599835071c6b3059787462 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 4 Jan 2020 09:17:01 -0800 Subject: Fix when -dff not given --- backends/aiger/xaiger.cc | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7ef744d04..32b218a22 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -239,17 +239,13 @@ struct XAigerWriter RTLIL::Module* inst_module = module->design->module(cell->type); if (inst_module) { - bool abc9_box = inst_module->attributes.count("\\abc9_box_id"); - bool abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); - if (abc9_box && cell->get_bool_attribute("\\abc9_keep")) - abc9_box = false; - - if (abc9_box) { - int abc9_box_order = cell->attributes.at("\\abc9_box_order").as_int(); - if (GetSize(box_list) <= abc9_box_order) - box_list.resize(abc9_box_order+1); - box_list[abc9_box_order] = cell; - if (!abc9_flop) + 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; + if (!inst_module->get_bool_attribute("\\abc9_flop")) continue; } @@ -542,6 +538,8 @@ struct XAigerWriter int box_count = 0; for (auto cell : box_list) { + log_assert(cell); + RTLIL::Module* box_module = module->design->module(cell->type); log_assert(box_module); @@ -611,7 +609,7 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { - log_push(); + log_module(holes_module); std::stringstream a_buffer; XAigerWriter writer(holes_module); @@ -622,8 +620,6 @@ struct XAigerWriter int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - - log_pop(); } } -- cgit v1.2.3 From b5f60e055d07579a2d4f23fc053ca030f103f377 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 5 Jan 2020 10:20:24 -0800 Subject: write_xaiger to pad, not abc9_ops -prep_holes --- backends/aiger/xaiger.cc | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 32b218a22..5aea70f3b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -332,13 +332,14 @@ 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); - if (w->port_input) + + SigSpec rhs = cell->connections_.at(port_name, SigSpec()); + if (w->port_input) { + // Add padding to fill entire port + rhs.append(SigSpec(State::Sx, GetSize(w)-GetSize(rhs))); for (auto b : rhs) { SigBit I = sigmap(b); if (b == RTLIL::Sx) @@ -352,14 +353,18 @@ struct XAigerWriter co_bits.emplace_back(b); unused_bits.erase(I); } - if (w->port_output) - for (const auto &b : rhs.bits()) { + } + if (w->port_output) { + // Add padding to fill entire port + rhs.append(SigSpec(State::Sx, GetSize(w)-GetSize(rhs))); + for (const auto &b : rhs) { SigBit O = sigmap(b); if (O != b) alias_map[O] = b; ci_bits.emplace_back(b); undriven_bits.erase(O); } + } } // Connect .abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box @@ -418,8 +423,11 @@ struct XAigerWriter for (auto &bit : ci_bits) { aig_m++, aig_i++; - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; + // State::Sx if padding + if (bit != State::Sx) { + log_assert(!aig_map.count(bit)); + aig_map[bit] = 2*aig_m; + } } for (auto bit : co_bits) { @@ -609,8 +617,6 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { - log_module(holes_module); - std::stringstream a_buffer; XAigerWriter writer(holes_module); writer.write_aiger(a_buffer, false /*ascii_mode*/); -- cgit v1.2.3 From 886c5c58834ccdb5f54dfbcb7d09908dc102e20a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 6 Jan 2020 10:23:04 -0800 Subject: write_xaiger: make more robust, update doc --- backends/aiger/xaiger.cc | 43 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1f1b9dffe..05e9678ee 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -847,17 +847,13 @@ struct XAigerWriter module->design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size()); } - void write_map(std::ostream &f, bool verbose_map) + void write_map(std::ostream &f) { dict input_lines; dict output_lines; - dict wire_lines; for (auto wire : module->wires()) { - //if (!verbose_map && wire->name[0] == '$') - // continue; - SigSpec sig = sigmap(wire); for (int i = 0; i < GetSize(wire); i++) @@ -875,14 +871,6 @@ struct XAigerWriter output_lines[o] += stringf("output %d %d %s %d\n", o - GetSize(co_bits), i, log_id(wire), init); continue; } - - if (verbose_map) { - if (aig_map.count(sig[i]) == 0) - continue; - - int a = aig_map.at(sig[i]); - wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); - } } } @@ -899,10 +887,6 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); - - wire_lines.sort(); - for (auto &it : wire_lines) - f << it.second; } }; @@ -914,8 +898,10 @@ struct XAigerBackend : public Backend { log("\n"); log(" write_xaiger [options] [filename]\n"); log("\n"); - log("Write the current design to an XAIGER file. The design must be flattened and\n"); - log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n"); + 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("\n"); log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); @@ -923,14 +909,10 @@ struct XAigerBackend : public Backend { log(" -map \n"); log(" write an extra file with port and box symbols\n"); log("\n"); - log(" -vmap \n"); - log(" like -map, but more verbose\n"); - log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; - bool verbose_map = false; std::string map_filename; log_header(design, "Executing XAIGER backend.\n"); @@ -946,11 +928,6 @@ struct XAigerBackend : public Backend { map_filename = args[++argidx]; continue; } - if (map_filename.empty() && args[argidx] == "-vmap" && argidx+1 < args.size()) { - map_filename = args[++argidx]; - verbose_map = true; - continue; - } break; } extra_args(f, filename, args, argidx, !ascii_mode); @@ -960,6 +937,14 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); + if (!design->selected_whole_module(top_module)) + log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module)); + + if (!top_module->processes.empty()) + log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", log_id(top_module)); + if (!top_module->memories.empty()) + log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module)); + XAigerWriter writer(top_module); writer.write_aiger(*f, ascii_mode); @@ -968,7 +953,7 @@ struct XAigerBackend : public Backend { mapf.open(map_filename.c_str(), std::ofstream::trunc); if (mapf.fail()) log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno)); - writer.write_map(mapf, verbose_map); + writer.write_map(mapf); } } } XAigerBackend; -- cgit v1.2.3 From aa58472a292c2cd3c0f2ba669c9dcfd608d8dc5f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 6 Jan 2020 13:34:45 -0800 Subject: Revert "write_xaiger to pad, not abc9_ops -prep_holes" This reverts commit b5f60e055d07579a2d4f23fc053ca030f103f377. --- backends/aiger/xaiger.cc | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c01adde3d..a9680525d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -318,14 +318,13 @@ 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); - - SigSpec rhs = cell->connections_.at(port_name, SigSpec()); - if (w->port_input) { - // Add padding to fill entire port - rhs.append(SigSpec(State::Sx, GetSize(w)-GetSize(rhs))); + auto rhs = cell->getPort(port_name); + if (w->port_input) for (auto b : rhs) { SigBit I = sigmap(b); if (b == RTLIL::Sx) @@ -339,18 +338,14 @@ struct XAigerWriter co_bits.emplace_back(b); unused_bits.erase(I); } - } - if (w->port_output) { - // Add padding to fill entire port - rhs.append(SigSpec(State::Sx, GetSize(w)-GetSize(rhs))); - for (const auto &b : rhs) { + if (w->port_output) + for (const auto &b : rhs.bits()) { SigBit O = sigmap(b); if (O != b) alias_map[O] = b; ci_bits.emplace_back(b); undriven_bits.erase(O); } - } } // Connect .abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box @@ -417,11 +412,8 @@ struct XAigerWriter for (auto &bit : ci_bits) { aig_m++, aig_i++; - // State::Sx if padding - if (bit != State::Sx) { - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; - } + log_assert(!aig_map.count(bit)); + aig_map[bit] = 2*aig_m; } for (auto bit : co_bits) { @@ -609,6 +601,8 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { + log_module(holes_module); + std::stringstream a_buffer; XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); -- cgit v1.2.3 From 8d0cc654a4c6cad925d20557cf299e00e27d5726 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 6 Jan 2020 15:14:38 -0800 Subject: Stray log_module --- backends/aiger/xaiger.cc | 2 -- 1 file changed, 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a9680525d..beaed696d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -601,8 +601,6 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { - log_module(holes_module); - std::stringstream a_buffer; XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); -- cgit v1.2.3 From 5f7349f26d814b8bf32a0e532b6f0fbacedcae90 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 8 Jan 2020 15:40:37 -0800 Subject: write_xaiger: holes PIs only if whitebox --- backends/aiger/xaiger.cc | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 05e9678ee..4cbf49baf 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -626,9 +626,10 @@ struct XAigerWriter if (box_module->has_processes()) Pass::call_on_module(module->design, box_module, "proc"); + bool whitebox = 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 && box_module->get_bool_attribute("\\whitebox")) { + if (r.second && whitebox) { holes_cell = holes_module->addCell(cell->name, cell->type); holes_cell->parameters = cell->parameters; r.first->second = holes_cell; @@ -641,19 +642,23 @@ struct XAigerWriter RTLIL::Wire *holes_wire; 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)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); + if (w->port_input) { + if (whitebox) + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + } + if (holes_cell) + port_sig.append(holes_wire); } - if (holes_cell) - port_sig.append(holes_wire); - } + else + box_inputs += GetSize(w); + } if (w->port_output) { box_outputs += GetSize(w); for (int i = 0; i < GetSize(w); i++) { -- cgit v1.2.3 From 7532416cd7a8c3fb41592c6677a30e0dad53813c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 8 Jan 2020 18:27:09 -0800 Subject: write_xaiger: cleanup holes generation --- backends/aiger/xaiger.cc | 169 +++++++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 80 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4cbf49baf..b6a7dbac2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -407,7 +407,7 @@ struct XAigerWriter } if (w->port_output) { RTLIL::SigSpec rhs; - auto it = cell->connections_.find(w->name); + auto it = cell->connections_.find(port_name); if (it != cell->connections_.end()) { if (GetSize(it->second) < GetSize(w)) it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second))); @@ -614,7 +614,7 @@ struct XAigerWriter RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); - dict cell_cache; + dict> cell_cache; int port_id = 1; int box_count = 0; @@ -623,86 +623,94 @@ struct XAigerWriter log_assert(orig_box_module); IdString derived_name = orig_box_module->derive(module->design, cell->parameters); RTLIL::Module* box_module = module->design->module(derived_name); - if (box_module->has_processes()) - Pass::call_on_module(module->design, box_module, "proc"); - - bool whitebox = 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 && whitebox) { - holes_cell = holes_module->addCell(cell->name, cell->type); - holes_cell->parameters = cell->parameters; - r.first->second = holes_cell; - } - int box_inputs = 0, box_outputs = 0; - for (auto port_name : box_ports.at(cell->type)) { - RTLIL::Wire *w = box_module->wire(port_name); - log_assert(w); - RTLIL::Wire *holes_wire; - RTLIL::SigSpec port_sig; - - if (w->port_input) { - if (whitebox) - for (int i = 0; i < GetSize(w); i++) { - box_inputs++; - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); + auto r = cell_cache.insert(derived_name); + auto &v = r.first->second; + if (r.second) { + if (box_module->has_processes()) + Pass::call_on_module(module->design, box_module, "proc"); + + int box_inputs = 0, box_outputs = 0; + if (box_module->get_bool_attribute("\\whitebox")) { + auto holes_cell = holes_module->addCell(cell->name, derived_name); + for (auto port_name : box_ports.at(cell->type)) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + log_assert(!w->port_input || !w->port_output); + auto &conn = holes_cell->connections_[port_name]; + if (w->port_input) { + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + RTLIL::Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + } + conn.append(holes_wire); } - if (holes_cell) - port_sig.append(holes_wire); } - else - box_inputs += GetSize(w); - } - 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("$abc%s.%s", cell->name.c_str(), log_id(w->name))); - else - holes_wire = holes_module->addWire(stringf("$abc%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_sig.append(holes_wire); - else - holes_module->connect(holes_wire, State::S0); + else if (w->port_output) { + box_outputs += GetSize(w); + conn = holes_module->addWire(stringf("%s.%s", derived_name.c_str(), log_id(port_name)), GetSize(w)); + } } + + // For flops only, create an extra 1-bit input that drives a new wire + // called ".abc9_ff.Q" that is used below + if (box_module->get_bool_attribute("\\abc9_flop")) { + box_inputs++; + Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + } + Wire *Q = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str())); + holes_module->connect(Q, holes_wire); + } + + std::get<0>(v) = holes_cell; } - 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); + else { + for (auto port_name : box_ports.at(cell->type)) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + log_assert(!w->port_input || !w->port_output); + if (w->port_input) + box_inputs += GetSize(w); + else if (w->port_output) + box_outputs += GetSize(w); + } + log_assert(std::get<0>(v) == nullptr); } + + std::get<1>(v) = box_inputs; + std::get<2>(v) = box_outputs; + std::get<3>(v) = box_module->attributes.at("\\abc9_box_id").as_int(); } - // For flops only, create an extra 1-bit input that drives a new wire - // called ".abc9_ff.Q" that is used below - if (box_module->get_bool_attribute("\\abc9_flop")) { - log_assert(holes_cell); - - box_inputs++; - Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - } - Wire *w = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str())); - holes_module->connect(w, holes_wire); + auto holes_cell = std::get<0>(v); + for (auto port_name : box_ports.at(cell->type)) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + if (!w->port_output) + continue; + Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name.c_str(), log_id(port_name)), GetSize(w)); + holes_wire->port_output = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); + if (holes_cell) // whitebox + holes_module->connect(holes_wire, holes_cell->getPort(port_name)); + else // blackbox + holes_module->connect(holes_wire, Const(State::S0, GetSize(w))); } - write_h_buffer(box_inputs); - write_h_buffer(box_outputs); - write_h_buffer(box_module->attributes.at("\\abc9_box_id").as_int()); + write_h_buffer(std::get<1>(v)); + write_h_buffer(std::get<2>(v)); + write_h_buffer(std::get<3>(v)); write_h_buffer(box_count++); } @@ -762,14 +770,14 @@ struct XAigerWriter // created a new $paramod ... Pass::call_on_module(holes_module->design, holes_module, "flatten -wb; techmap; aigmap"); - dict replace; + 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 + // 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) @@ -777,10 +785,10 @@ struct XAigerWriter 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 the combinatorial control logic that feeds the box + // 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(SigSig(port,Q), SigSig(port,D))); + 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("."); @@ -788,7 +796,7 @@ struct XAigerWriter 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_ff.Q" - // wire (which itself is driven an input port) we inserted above + // wire (which itself is driven by an 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); @@ -799,10 +807,11 @@ struct XAigerWriter ++it; } + SigMap holes_sigmap(holes_module); for (auto &conn : holes_module->connections_) { - auto it = replace.find(conn); + auto it = replace.find(sigmap(conn.second)); if (it != replace.end()) - conn = it->second; + conn.second = it->second; } // Move into a new (temporary) design so that "clean" will only -- cgit v1.2.3 From 1ccee4b95e1e7a2edf55c989d6acc7d6f63762ba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 11 Jan 2020 11:49:57 -0800 Subject: write_xaiger: sort holes by offset as well as port_id --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index b6a7dbac2..7ee5058ae 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -474,7 +474,8 @@ struct XAigerWriter if (holes_mode) { struct sort_by_port_id { bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { - return a.wire->port_id < b.wire->port_id; + return a.wire->port_id < b.wire->port_id || + (a.wire->port_id == b.wire->port_id && a.offset < b.offset); } }; input_bits.sort(sort_by_port_id()); -- cgit v1.2.3 From 295e241c074ae275e832fdde9fae6fd897170ac8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 11 Jan 2020 17:28:24 -0800 Subject: cleanup --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 212e1e561..93e0ebc8c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -93,7 +93,6 @@ struct XAigerWriter dict ordered_outputs; vector box_list; - dict> box_ports; int mkgate(int a0, int a1) { @@ -277,6 +276,7 @@ struct XAigerWriter //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } + dict> box_ports; for (auto cell : box_list) { log_assert(cell); -- 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/aiger/xaiger.cc') 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/aiger/xaiger.cc') 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/aiger/xaiger.cc') 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/aiger/xaiger.cc') 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/aiger/xaiger.cc') 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/aiger/xaiger.cc') 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/aiger/xaiger.cc') 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 From 4656f202c6f05d126c1acc79fca675e467c80840 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 14:27:29 -0800 Subject: abc9_ops: -reintegrate to not trim box padding anymore --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f9890a592..4f466d568 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -349,7 +349,7 @@ struct XAigerWriter unused_bits.erase(I); } if (w->port_output) - for (const auto &b : rhs.bits()) { + for (const auto &b : rhs) { SigBit O = sigmap(b); if (O != b) alias_map[O] = b; -- cgit v1.2.3 From 1c41dc6b95c4c0261db96c15dd1b3cce8de6491f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 16:17:27 -0800 Subject: write_xaiger: do not export flop inputs as POs --- backends/aiger/xaiger.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4f466d568..c3fc61e3b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -226,6 +226,7 @@ struct XAigerWriter } if (inst_module) { + bool abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); auto it = cell->attributes.find("\\abc9_box_seq"); if (it != cell->attributes.end()) { int abc9_box_seq = it->second.as_int(); @@ -233,7 +234,7 @@ struct XAigerWriter 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")) + if (!abc9_flop) continue; } @@ -256,6 +257,9 @@ struct XAigerWriter for (auto bit : sigmap(conn.second)) arrival_times[bit] = arrival; } + + if (abc9_flop) + continue; } } @@ -591,7 +595,7 @@ struct XAigerWriter // For flops only, create an extra 1-bit input that drives a new wire // called ".abc9_ff.Q" that is used below if (box_module->get_bool_attribute("\\abc9_flop")) - box_inputs++; + box_inputs++; std::get<0>(v) = box_inputs; std::get<1>(v) = box_outputs; -- cgit v1.2.3 From d6da9c0c0f3b59706f509b7fd96ea793491a2307 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Jan 2020 11:25:20 -0800 Subject: write_xaiger: skip abc9_flop only if abc_box_seq present --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c3fc61e3b..a9b75ecc7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -226,7 +226,7 @@ struct XAigerWriter } if (inst_module) { - bool abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); + bool abc9_flop = false; auto it = cell->attributes.find("\\abc9_box_seq"); if (it != cell->attributes.end()) { int abc9_box_seq = it->second.as_int(); @@ -234,6 +234,7 @@ struct XAigerWriter box_list.resize(abc9_box_seq+1); box_list[abc9_box_seq] = cell; // Only flop boxes may have arrival times + abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); if (!abc9_flop) continue; } -- cgit v1.2.3 From cd8f55a91100b8dcf8b4775803cbacf70f5a998c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Jan 2020 09:43:04 -0800 Subject: write_xaiger: fix for (* keep *) on flop output --- backends/aiger/xaiger.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a9b75ecc7..b72dd6890 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -222,6 +222,8 @@ struct XAigerWriter alias_map[Q] = D; auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell)); log_assert(r.second); + if (input_bits.erase(Q)) + log_assert(Q.wire->attributes.count(ID::keep)); continue; } @@ -568,9 +570,6 @@ struct XAigerWriter // write_o_buffer(0); if (!box_list.empty() || !ff_bits.empty()) { - RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); - log_assert(holes_module); - dict> cell_cache; int box_count = 0; @@ -653,6 +652,7 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); if (holes_module) { std::stringstream a_buffer; XAigerWriter writer(holes_module, true /* holes_mode */); -- cgit v1.2.3