diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index cd15b6160..7a139f68f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -51,6 +51,7 @@ struct XAigerWriter //pool initstate_bits; vector> ci_bits; vector> co_bits; + vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -180,6 +181,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) { @@ -256,7 +258,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 { @@ -479,11 +506,22 @@ 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) { RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; + //auto r = aig_map.insert(std::make_pair(c.first, c.second)); + //if (!r.second) { + // ff_aig_map[std::get<0>(c)] = 2*aig_m; + //} } if (imode && input_bits.empty()) { @@ -557,6 +595,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); @@ -714,7 +757,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 @@ -729,12 +772,12 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size()); - write_h_buffer(input_bits.size() + ci_bits.size()); - log_debug("coNum = %zu\n", num_outputs + co_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - log_debug("piNum = %zu\n", input_bits.size()); - write_h_buffer(input_bits.size()); + log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); + log_debug("coNum = %zu\n", num_outputs + ff_bits.size() + co_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()+ co_bits.size()); + log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); + write_h_buffer(input_bits.size()+ ff_bits.size()); log_debug("poNum = %d\n", num_outputs); write_h_buffer(num_outputs); log_debug("boxNum = %zu\n", box_list.size()); @@ -813,6 +856,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) { // NB: fixup_ports() will sort ports by name //holes_module->fixup_ports(); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 399e46737..69404b19d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -249,6 +249,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; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f14828745..01842dbf2 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -537,11 +537,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_xaiger() @@ -752,7 +747,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"); diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index c7c5ba168..b5e10fb20 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 diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ecfb94610..cc667b919 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -294,6 +294,7 @@ struct SynthXilinxPass : public ScriptPass else run(abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); run("clean"); + // This shregmap call infers fixed length shift registers after abc // has performed any necessary retiming if (!nosrl || help_mode)