From 8f30019b68c68258979137a9d9fbbe68794781c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 17:41:21 -0700 Subject: [PATCH 1/5] Revert "Temporarily remove 'r' extension" This reverts commit eaf3c247729365cec776e147f380ce59f7dccd4d. --- backends/aiger/xaiger.cc | 84 ++++++++++++++++++++++++++++++++--- frontends/aiger/aigerparse.cc | 18 ++++++++ 2 files changed, 95 insertions(+), 7 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d6438a297..a881b1b88 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,6 +50,7 @@ struct XAigerWriter dict> and_map; //pool initstate_bits; vector> ci_bits, co_bits; + vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -174,6 +175,7 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { @@ -250,7 +252,32 @@ struct XAigerWriter // continue; //} - if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_flop) { + SigBit d, q; + for (const auto &c : cell->connections()) { + for (auto b : c.second.bits()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + d = b; + } + if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { + SigBit O = sigmap(b); + q = O; + } + } + } + if (!abc_box_seen) + abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + + ff_bits.emplace_back(d, q); + undriven_bits.erase(q); + } + else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; } else { @@ -393,10 +420,20 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } + for (auto &f : ff_bits) { + auto bit = f.second; + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + + dict ff_aig_map; for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - aig_map[c.first] = c.second; + auto r = aig_map.insert(std::make_pair(c.first, c.second)); + if (!r.second) { + ff_aig_map[c.first] = c.second; + } } if (imode && input_bits.empty()) { @@ -471,6 +508,11 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } + for (auto &f : ff_bits) { + aig_o++; + aig_outputs.push_back(ff_aig_map.at(f.second)); + } + if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -628,7 +670,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty()) { + if (!box_list.empty() || !ff_bits.empty()) { std::stringstream h_buffer; auto write_h_buffer = [&h_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -643,10 +685,10 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + ff_bits.size() + co_bits.size()); + write_h_buffer(input_bits.size() + ff_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -699,6 +741,34 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + if (!ff_bits.empty()) { + std::stringstream r_buffer; + auto write_r_buffer = [&r_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + write_r_buffer(ff_bits.size()); + int mergeability_class = 1; + for (auto cell : ff_bits) + write_r_buffer(mergeability_class++); + + f << "r"; + std::string buffer_str = r_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + int buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + } + if (holes_module) { holes_module->fixup_ports(); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 3fa6f5c2d..4e3f5e7c9 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -360,6 +360,24 @@ void AigerReader::parse_xaiger() module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } } + else if (c == 'r') { + uint32_t dataSize = parse_xaiger_literal(f); + uint32_t flopNum = parse_xaiger_literal(f); + f.ignore(flopNum * sizeof(uint32_t)); + log_assert(inputs.size() >= flopNum); + for (auto it = inputs.end() - flopNum; it != inputs.end(); ++it) { + log_assert((*it)->port_input); + (*it)->port_input = false; + } + inputs.erase(inputs.end() - flopNum, inputs.end()); + log_assert(outputs.size() >= flopNum); + for (auto it = outputs.end() - flopNum; it != outputs.end(); ++it) { + log_assert((*it)->port_output); + (*it)->port_output = false; + } + outputs.erase(outputs.end() - flopNum, outputs.end()); + module->fixup_ports(); + } else if (c == 'n') { parse_xaiger_literal(f); f >> s; From 5f30a8795d9a3b2c4ebaaa16ecf186e35e82a04b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 17:47:05 -0700 Subject: [PATCH 2/5] Tidy up --- frontends/aiger/aigerparse.cc | 2 +- passes/techmap/abc9.cc | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4e3f5e7c9..b9ab6fc09 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -361,7 +361,7 @@ void AigerReader::parse_xaiger() } } else if (c == 'r') { - uint32_t dataSize = parse_xaiger_literal(f); + /*uint32_t dataSize =*/ parse_xaiger_literal(f); uint32_t flopNum = parse_xaiger_literal(f); f.ignore(flopNum * sizeof(uint32_t)); log_assert(inputs.size() >= flopNum); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 18f860e36..67d0981f4 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -561,11 +561,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri output_bits.insert({wire, i}); } else { - //if (w->name == "\\__dummy_o__") { - // log("Don't call ABC as there is nothing to map.\n"); - // goto cleanup; - //} - // Attempt another wideports_split here because there // exists the possibility that different bits of a port // could be an input and output, therefore parse_xiager() @@ -935,7 +930,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // log("Don't call ABC as there is nothing to map.\n"); //} -cleanup: if (cleanup) { log("Removing temp directory.\n"); From 91c3afcab723d85d3c6931561cb13ad7b70e7e5c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 13:42:06 -0700 Subject: [PATCH 3/5] Use nonblocking --- techlibs/ice40/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 40e54f9f0..40972766d 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -149,7 +149,7 @@ module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) in always @(posedge C) Q <= D; `else - always @* Q = D; + always @* Q <= D; `endif endmodule From d9c915042a610672e313f976cdbcbf9a814c380d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 13:42:35 -0700 Subject: [PATCH 4/5] Move clean from aigerparse to abc9 --- frontends/aiger/aigerparse.cc | 2 -- passes/techmap/abc9.cc | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index b9ab6fc09..904a1079d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -598,8 +598,6 @@ next_line: module->fixup_ports(); design->add(module); - Pass::call(design, "clean"); - for (auto cell : module->cells().to_vector()) { if (cell->type != "$lut") continue; auto y_port = cell->getPort("\\Y").as_bit(); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 67d0981f4..2aa19b348 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -548,6 +548,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"]; if (mapped_mod == NULL) log_error("ABC output file does not contain a module `netlist'.\n"); + Pass::call(mapped_design, "clean"); pool output_bits; for (auto &it : mapped_mod->wires_) { From ac2aff9e28a087a9a2697cd6ccf754af738903a7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 16:11:14 -0700 Subject: [PATCH 5/5] Fix abc9 with (* keep *) wires --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ tests/simple_abc9/abc9.v | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a881b1b88..7126002f6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -134,6 +134,8 @@ struct XAigerWriter init_map[initsig[i]] = initval[i] == State::S1; } + bool keep = wire->attributes.count("\\keep"); + for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -152,8 +154,10 @@ struct XAigerWriter if (wire->port_input) input_bits.insert(bit); + else if (keep) + input_bits.insert(wirebit); - if (wire->port_output) { + if (wire->port_output || keep) { if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); @@ -365,10 +369,12 @@ struct XAigerWriter for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, 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)) { + // 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)) + || wire->attributes.count("\\keep")) { + log_assert(input_bits.count(bit) && output_bits.count(bit)); RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); if (!new_wire) new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); @@ -381,7 +387,9 @@ struct XAigerWriter else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else + //log_abort(); alias_map[new_bit] = bit; + output_bits.erase(bit); output_bits.insert(new_bit); } } @@ -820,7 +828,7 @@ struct XAigerWriter { RTLIL::SigBit b(wire, i); if (input_bits.count(b)) { - int a = aig_map.at(sig[i]); + int a = aig_map.at(b); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index eca340693..f37d975ff 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -104,3 +104,41 @@ always @(io or oe) assign io[3:0] = oe ? ~latch[3:0] : 4'bz; assign io[7:4] = !oe ? {latch[4], latch[7:3]} : 4'bz; endmodule + +module abc9_test015(input a, output b, input c); +assign b = ~a; +(* keep *) wire d; +assign d = ~c; +endmodule + +module abc9_test016(input a, output b); +assign b = ~a; +(* keep *) reg c; +always @* c <= ~a; +endmodule + +module abc9_test017(input a, output b); +assign b = ~a; +(* keep *) reg c; +always @* c = b; +endmodule + +module abc9_test018(input a, output b, output c); +assign b = ~a; +(* keep *) wire [1:0] d; +assign c = &d; +endmodule + +module abc9_test019(input a, output b); +assign b = ~a; +(* keep *) reg [1:0] c; +reg d; +always @* d <= &c; +endmodule + +module abc9_test020(input a, output b); +assign b = ~a; +(* keep *) reg [1:0] c; +(* keep *) reg d; +always @* d <= &c; +endmodule