diff options
-rw-r--r-- | backends/aiger/xaiger.cc | 122 | ||||
-rw-r--r-- | frontends/aiger/aigerparse.cc | 56 | ||||
-rw-r--r-- | passes/techmap/abc9.cc | 10 | ||||
-rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 10 |
4 files changed, 156 insertions, 42 deletions
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bad9322bb..f67f7620b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -47,7 +47,7 @@ struct XAigerWriter dict<SigBit, SigBit> not_map, ff_map, alias_map; dict<SigBit, pair<SigBit, SigBit>> and_map; pool<SigBit> initstate_bits; - pool<SigBit> ci_bits, co_bits; + vector<std::pair<SigBit,int>> ci_bits, co_bits; dict<IdString, unsigned> type_map; vector<pair<int, int>> aig_gates; @@ -61,6 +61,8 @@ struct XAigerWriter dict<SigBit, int> init_inputs; int initstate_ff = 0; + vector<Cell*> box_list; + int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -211,7 +213,7 @@ struct XAigerWriter } for (const auto &c : cell->connections()) { - if (c.second.is_fully_const()) continue; + /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; @@ -219,30 +221,32 @@ struct XAigerWriter auto is_output = cell->output(c.first); log_assert(is_input || is_output); if (is_input) { - if (!w->port_input) { + /*if (!w->port_input)*/ { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - if (!output_bits.count(b)) - co_bits.insert(b); + /*if (!output_bits.count(b))*/ + co_bits.emplace_back(b, 0); } } if (is_output) { SigBit O = sigmap(b); - if (!input_bits.count(O)) - ci_bits.insert(O); + /*if (!input_bits.count(O))*/ + ci_bits.emplace_back(O, 0); } } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } - //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + + box_list.emplace_back(cell); + //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } 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 CO driven by the existing inout, and inherit existing + // 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)) { RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); @@ -256,22 +260,22 @@ struct XAigerWriter and_map[new_bit] = and_map.at(bit); else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); - co_bits.insert(new_bit); + output_bits.insert(new_bit); } } // Do some CI/CO post-processing: // Erase all POs and COs that are undriven for (auto bit : undriven_bits) { - co_bits.erase(bit); + //co_bits.erase(bit); output_bits.erase(bit); } // Erase all CIs that are also COs - for (auto bit : co_bits) - ci_bits.erase(bit); + //for (auto bit : co_bits) + // ci_bits.erase(bit); // CIs cannot be undriven - for (auto bit : ci_bits) - undriven_bits.erase(bit); + for (const auto &c : ci_bits) + undriven_bits.erase(c.first); for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -295,9 +299,10 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; - for (auto bit : ci_bits) { + for (auto &c : ci_bits) { aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; + c.second = 2*aig_m; + aig_map[c.first] = c.second; } for (auto bit : input_bits) { @@ -365,15 +370,15 @@ struct XAigerWriter if (!initstate_bits.empty() || !init_inputs.empty()) aig_latchin.push_back(1); - for (auto bit : co_bits) { - aig_o++; - ordered_outputs[bit] = aig_o-1; + for (auto &c : co_bits) { + RTLIL::SigBit bit = c.first; + c.second = aig_o++; + ordered_outputs[bit] = c.second; aig_outputs.push_back(bit2aig(bit)); } for (auto bit : output_bits) { - aig_o++; - ordered_outputs[bit] = aig_o-1; + ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -480,7 +485,7 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (input_bits.count(b) || ci_bits.count(b)) { + if (input_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) @@ -489,7 +494,7 @@ struct XAigerWriter symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); } - if (output_bits.count(b) || co_bits.count(b)) { + if (output_bits.count(b)) { int o = ordered_outputs.at(b); output_seen = !miter_mode; if (GetSize(wire) != 1) @@ -532,7 +537,52 @@ struct XAigerWriter } } - f << stringf("c\nGenerated by %s\n", yosys_version_str); + f << "c"; + + std::stringstream h_buffer; + auto write_h_buffer = [&h_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 + h_buffer.write(reinterpret_cast<const char*>(&i32_be), sizeof(i32_be)); + }; + int num_outputs = output_bits.size(); + 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(box_list.size()); + int box_id = 0; + for (auto cell : box_list) { + int box_inputs = 0, box_outputs = 0; + for (const auto &c : cell->connections()) + if (cell->input(c.first)) + box_inputs += c.second.size(); + else + box_outputs += c.second.size(); + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_id++); + write_h_buffer(0 /* OldBoxNum */); + } + std::string h_buffer_str = h_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int h_buffer_size_be = _byteswap_ulong(h_buffer_str.size()); +#else + int h_buffer_size_be = __builtin_bswap32(h_buffer_str.size()); +#endif + f << "h"; + f.write(reinterpret_cast<const char*>(&h_buffer_size_be), sizeof(h_buffer_size_be)); + f.write(h_buffer_str.data(), h_buffer_str.size()); + + f << stringf("Generated by %s\n", yosys_version_str); } void write_map(std::ostream &f, bool verbose_map, bool omode) @@ -553,14 +603,13 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (input_bits.count(b) || ci_bits.count(b)) { + if (input_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - continue; } - if (output_bits.count(b) || co_bits.count(b)) { + if (output_bits.count(b)) { int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); continue; @@ -592,6 +641,21 @@ struct XAigerWriter } } + for (const auto &c : ci_bits) { + RTLIL::SigBit b = c.first; + RTLIL::Wire *wire = b.wire; + int i = b.offset; + int a = c.second; + log_assert((a & 1) == 0); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + } + + for (const auto &c : co_bits) { + RTLIL::SigBit b = c.first; + int o = c.second; + output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(b.wire)); + } + input_lines.sort(); for (auto &it : input_lines) f << it.second; @@ -606,7 +670,7 @@ struct XAigerWriter f << it.second; log_assert(output_lines.size() == output_bits.size() + co_bits.size()); if (omode && output_lines.empty()) - f << "output 0 0 __dummy_o__\n"; + f << "output " << output_lines.size() << " 0 __dummy_o__\n"; latch_lines.sort(); for (auto &it : latch_lines) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index b752d3127..0d81cc2fd 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -446,12 +446,30 @@ next_line: log_assert(wire); log_assert(wire->port_input); - if (index == 0) - module->rename(wire, escaped_symbol); + if (index == 0) { + // Cope with the fact that a CI might be identical + // to a PI (necessary due to ABC); in those cases + // simply connect the latter to the former + RTLIL::Wire* existing = module->wire(escaped_symbol); + if (!existing) + module->rename(wire, escaped_symbol); + else { + wire->port_input = false; + module->connect(wire, existing); + } + } else if (index > 0) { - module->rename(wire, stringf("%s[%d]", escaped_symbol.c_str(), index)); - if (wideports) - wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + std::string indexed_name = stringf("%s[%d]", escaped_symbol.c_str(), index); + RTLIL::Wire* existing = module->wire(indexed_name); + if (!existing) { + module->rename(wire, indexed_name); + if (wideports) + wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + } + else { + module->connect(wire, existing); + wire->port_input = false; + } } } else if (type == "output") { @@ -460,12 +478,30 @@ next_line: log_assert(wire); log_assert(wire->port_output); - if (index == 0) - module->rename(wire, escaped_symbol); + if (index == 0) { + // Cope with the fact that a CO might be identical + // to a PO (necessary due to ABC); in those cases + // simply connect the latter to the former + RTLIL::Wire* existing = module->wire(escaped_symbol); + if (!existing) + module->rename(wire, escaped_symbol); + else { + wire->port_output = false; + module->connect(wire, existing); + } + } else if (index > 0) { - module->rename(wire, stringf("%s[%d]", escaped_symbol.c_str(), index)); - if (wideports) - wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + std::string indexed_name = stringf("%s[%d]", escaped_symbol.c_str(), index); + RTLIL::Wire* existing = module->wire(indexed_name); + if (!existing) { + module->rename(wire, indexed_name); + if (wideports) + wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + } + else { + module->connect(wire, existing); + wire->port_output = false; + } } } else diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index da3d36354..17d082833 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -407,7 +407,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(design); - Pass::call(design, stringf("write_xaiger -O -symbols %s/input.aig; ", tempdir_name.c_str())); + Pass::call(design, stringf("write_xaiger -O -map %s/input.sym %s/input.aig; ", tempdir_name.c_str(), tempdir_name.c_str())); design->selection_stack.pop_back(); @@ -523,7 +523,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bool builtin_lib = liberty_file.empty(); RTLIL::Design *mapped_design = new RTLIL::Design; //parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); - AigerReader reader(mapped_design, ifs, "\\netlist", "" /* clk_name */, "" /* map_filename */, true /* wideports */); + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); + AigerReader reader(mapped_design, ifs, "\\netlist", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); reader.parse_xaiger(); ifs.close(); @@ -1237,6 +1238,11 @@ struct Abc9Pass : public Pass { map_mux16 = true; continue; } + if (arg == "-dress") { + // TODO + //abc_dress = true; + continue; + } if (arg == "-g" && argidx+1 < args.size()) { for (auto g : split_tokens(args[++argidx], ",")) { vector<string> gate_list; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 805ae8e6e..090bcce85 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -80,6 +80,9 @@ struct SynthXilinxPass : public Pass log(" -retime\n"); log(" run 'abc' with -dff option\n"); log("\n"); + log(" -abc9\n"); + log(" use abc9 instead of abc\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); log("\n"); @@ -142,6 +145,7 @@ struct SynthXilinxPass : public Pass std::string edif_file; std::string blif_file; std::string run_from, run_to; + std::string abc = "abc"; bool flatten = false; bool retime = false; bool vpr = false; @@ -191,6 +195,10 @@ struct SynthXilinxPass : public Pass nodram = true; continue; } + if (args[argidx] == "-abc9") { + abc = "abc9"; + continue; + } break; } extra_args(args, argidx, design); @@ -267,7 +275,7 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + Pass::call(design, abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); Pass::call(design, "techmap -map +/xilinx/lut_map.v"); } |