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 ++++++++++++++++++++++++++++++++++++---- frontends/aiger/aigerparse.cc | 35 ++++- passes/techmap/abc9.cc | 88 +++++++++--- techlibs/xilinx/abc_map.v | 97 +++++++++++++ techlibs/xilinx/abc_model.v | 89 ++++++++++++ techlibs/xilinx/abc_unmap.v | 119 ++++++++++++++++ techlibs/xilinx/abc_xc7.box | 41 ++++++ techlibs/xilinx/cells_sim.v | 24 ++-- techlibs/xilinx/synth_xilinx.cc | 6 +- 9 files changed, 730 insertions(+), 68 deletions(-) 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()) { diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index e8ee487e5..7a467b91e 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -732,12 +732,19 @@ void AigerReader::parse_aiger_binary() void AigerReader::post_process() { pool seen_boxes; - unsigned ci_count = 0, co_count = 0; + pool flops; + unsigned ci_count = 0, co_count = 0, flop_count = 0; for (auto cell : boxes) { RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); + bool is_flop = false; if (seen_boxes.insert(cell->type).second) { + if (box_module->attributes.count("\\abc_flop")) { + log_assert(flop_count < flopNum); + flops.insert(cell->type); + is_flop = true; + } auto it = box_module->attributes.find("\\abc_carry"); if (it != box_module->attributes.end()) { RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; @@ -777,6 +784,8 @@ void AigerReader::post_process() carry_out->port_id = ports.size(); } } + else + is_flop = flops.count(cell->type); // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) @@ -803,7 +812,25 @@ void AigerReader::post_process() rhs.append(wire); } - cell->setPort(port_name, rhs); + if (!is_flop || port_name != "\\$pastQ") + cell->setPort(port_name, rhs); + } + + if (is_flop) { + RTLIL::Wire *d = outputs[outputs.size() - flopNum + flop_count]; + log_assert(d); + log_assert(d->port_output); + d->port_output = false; + + RTLIL::Wire *q = inputs[piNum - flopNum + flop_count]; + log_assert(q); + log_assert(q->port_input); + q->port_input = false; + + flop_count++; + module->connect(q, d); + cell->set_bool_attribute("\\abc_flop"); + continue; } } @@ -907,6 +934,10 @@ void AigerReader::post_process() } } log_debug(" -> %s\n", log_id(wire)); + int init; + mf >> init; + if (init < 2) + wire->attributes["\\init"] = init; } else if (type == "box") { RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 919c4ce53..29929f80b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -551,7 +551,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri dict abc_box; vector boxes; for (auto cell : module->selected_cells()) { - if (cell->type.in(ID($_AND_), ID($_NOT_))) { + if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC_FF_))) { module->remove(cell); continue; } @@ -651,6 +651,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell->attributes = mapped_cell->attributes; } + auto abc_flop = mapped_cell->attributes.count("\\abc_flop"); for (auto &conn : mapped_cell->connections()) { RTLIL::SigSpec newsig; for (auto c : conn.second.chunks()) { @@ -663,15 +664,17 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } cell->setPort(conn.first, newsig); - if (cell->input(conn.first)) { - for (auto i : newsig) - bit2sinks[i].push_back(cell); - for (auto i : conn.second) - bit_users[i].insert(mapped_cell->name); + if (!abc_flop) { + if (cell->input(conn.first)) { + for (auto i : newsig) + bit2sinks[i].push_back(cell); + for (auto i : conn.second) + bit_users[i].insert(mapped_cell->name); + } + if (cell->output(conn.first)) + for (auto i : conn.second) + bit_drivers[i].insert(mapped_cell->name); } - if (cell->output(conn.first)) - for (auto i : conn.second) - bit_drivers[i].insert(mapped_cell->name); } } @@ -1167,6 +1170,7 @@ struct Abc9Pass : public Pass { assign_map.set(mod); if (!dff_mode || !clk_str.empty()) { + design->selection_stack.emplace_back(false); RTLIL::Selection& sel = design->selection_stack.back(); sel.select(mod); @@ -1194,6 +1198,13 @@ struct Abc9Pass : public Pass { std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; + pool seen_cells; + struct flop_data_t { + IdString clk_port; + IdString en_port; + }; + dict flop_data; + for (auto cell : all_cells) { clkdomain_t key; @@ -1214,20 +1225,57 @@ struct Abc9Pass : public Pass { } } - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) - { - key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); + decltype(flop_data)::iterator it; + if (seen_cells.insert(cell->type).second) { + RTLIL::Module* inst_module = design->module(cell->type); + if (!inst_module) + continue; + + if (!inst_module->attributes.count("\\abc_flop")) + continue; + + IdString abc_flop_clk, abc_flop_en; + for (auto port_name : inst_module->ports) { + auto wire = inst_module->wire(port_name); + log_assert(wire); + if (wire->attributes.count("\\abc_flop_clk")) { + if (abc_flop_clk != IdString()) + log_error("More than one port has the 'abc_flop_clk' attribute set on module '%s'.\n", log_id(cell->type)); + abc_flop_clk = port_name; + } + if (wire->attributes.count("\\abc_flop_en")) { + if (abc_flop_en != IdString()) + log_error("More than one port has the 'abc_flop_en' attribute set on module '%s'.\n", log_id(cell->type)); + abc_flop_en = port_name; + } + } + + if (abc_flop_clk == IdString()) + log_error("'abc_flop_clk' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); + if (abc_flop_en == IdString()) + log_error("'abc_flop_en' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); + + it = flop_data.insert(std::make_pair(cell->type, flop_data_t{abc_flop_clk, abc_flop_en})).first; } - else - if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - { - bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); - bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E)))); + else { + it = flop_data.find(cell->type); + if (it == flop_data.end()) + continue; } - else - continue; + const auto &data = it->second; + + auto jt = cell->parameters.find("\\CLK_POLARITY"); + if (jt == cell->parameters.end()) + log_error("'CLK_POLARITY' is not a parameter on module '%s'.\n", log_id(cell->type)); + bool this_clk_pol = jt->second.as_bool(); + + jt = cell->parameters.find("\\EN_POLARITY"); + if (jt == cell->parameters.end()) + log_error("'EN_POLARITY' is not a parameter on module '%s'.\n", log_id(cell->type)); + bool this_en_pol = jt->second.as_bool(); + + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(data.clk_port)), this_en_pol, assign_map(cell->getPort(data.en_port))); unassigned_cells.erase(cell); expand_queue.insert(cell); diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 121862692..a760b3d6d 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -20,6 +20,103 @@ // ============================================================================ +module FDRE (output reg Q, input C, CE, D, R); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_R_INVERTED = 1'b0; + wire \$nextQ ; + \$__ABC_FDRE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_R_INVERTED(IS_R_INVERTED), + .CLK_POLARITY(!IS_C_INVERTED), + .EN_POLARITY(1'b1) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .R(R) + ); + \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(Q)); +endmodule +module FDRE_1 (output reg Q, input C, CE, D, R); + parameter [0:0] INIT = 1'b0; + wire \$nextQ ; + \$__ABC_FDRE_1 #( + .INIT(|0), + .CLK_POLARITY(1'b0), + .EN_POLARITY(1'b1) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .R(R) + ); + \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(Q)); +endmodule + +module FDCE (output reg Q, input C, CE, D, CLR); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_CLR_INVERTED = 1'b0; + wire \$nextQ , \$currQ ; + \$__ABC_FDCE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_CLR_INVERTED(IS_CLR_INVERTED), + .CLK_POLARITY(!IS_C_INVERTED), + .EN_POLARITY(1'b1) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .CLR(CLR) + ); + \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); + \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(CLR), .Y(Q)); +endmodule +module FDCE_1 (output reg Q, input C, CE, D, CLR); + parameter [0:0] INIT = 1'b0; + wire \$nextQ , \$currQ ; + \$__ABC_FDCE_1 #( + .INIT(INIT), + .CLK_POLARITY(1'b0), + .EN_POLARITY(1'b1) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .CLR(CLR) + ); + \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); + \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(CLR), .Y(Q)); +endmodule + +module FDPE (output reg Q, input C, CE, D, PRE); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_PRE_INVERTED = 1'b0; + wire \$nextQ , \$currQ ; + \$__ABC_FDPE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_PRE_INVERTED(IS_PRE_INVERTED), + .CLK_POLARITY(!IS_C_INVERTED), + .EN_POLARITY(1'b1) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .PRE(PRE) + ); + \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); + \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(PRE), .Y(Q)); +endmodule +module FDPE_1 (output reg Q, input C, CE, D, PRE); + parameter [0:0] INIT = 1'b0; + wire \$nextQ , \$currQ ; + \$__ABC_FDPE_1 #( + .INIT(INIT), + .CLK_POLARITY(1'b0), + .EN_POLARITY(1'b1) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .PRE(PRE) + ); + \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); + \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(PRE), .Y(Q)); +endmodule + module RAM32X1D ( output DPO, SPO, input D, diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index e3e9686b5..7162bd213 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -26,6 +26,94 @@ module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); : (S0 ? I1 : I0); endmodule +module \$__ABC_FF_ (input C, D, output Q); +endmodule + +(* abc_box_id = 1000 *) +module \$__ABC_ASYNC (input A, S, output Y); +endmodule + +(* abc_box_id=1001, lib_whitebox, abc_flop *) +module \$__ABC_FDRE ((* abc_flop_q, abc_arrival=303 *) output Q, + (* abc_flop_clk *) input C, + (* abc_flop_en *) input CE, + (* abc_flop_d *) input D, + input R, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_R_INVERTED = 1'b0; + parameter CLK_POLARITY = !IS_C_INVERTED; + parameter EN_POLARITY = 1'b1; + assign Q = (R ^ IS_R_INVERTED) ? 1'b0 : (CE ? (D ^ IS_D_INVERTED) : \$pastQ ); +endmodule + +(* abc_box_id=1002, lib_whitebox, abc_flop *) +module \$__ABC_FDRE_1 ((* abc_flop_q, abc_arrival=303 *) output Q, + (* abc_flop_clk *) input C, + (* abc_flop_en *) input CE, + (* abc_flop_d *) input D, + input R, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter CLK_POLARITY = 1'b0; + parameter EN_POLARITY = 1'b1; + assign Q = R ? 1'b0 : (CE ? D : \$pastQ ); +endmodule + +(* abc_box_id=1003, lib_whitebox, abc_flop *) +module \$__ABC_FDCE ((* abc_flop_q, abc_arrival=303 *) output Q, + (* abc_flop_clk *) input C, + (* abc_flop_en *) input CE, + (* abc_flop_d *) input D, + input CLR, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_CLR_INVERTED = 1'b0; + parameter CLK_POLARITY = !IS_C_INVERTED; + parameter EN_POLARITY = 1'b1; + assign Q = (CE && !(CLR ^ IS_CLR_INVERTED)) ? (D ^ IS_D_INVERTED) : \$pastQ ; +endmodule + +(* abc_box_id=1004, lib_whitebox, abc_flop *) +module \$__ABC_FDCE_1 ((* abc_flop_q, abc_arrival=303 *) output Q, + (* abc_flop_clk *) input C, + (* abc_flop_en *) input CE, + (* abc_flop_d *) input D, + input CLR, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter CLK_POLARITY = 1'b0; + parameter EN_POLARITY = 1'b1; + assign Q = (CE && !CLR) ? D : \$pastQ ; +endmodule + +(* abc_box_id=1005, lib_whitebox, abc_flop *) +module \$__ABC_FDPE ((* abc_flop_q, abc_arrival=303 *) output Q, + (* abc_flop_clk *) input C, + (* abc_flop_en *) input CE, + (* abc_flop_d *) input D, + input PRE, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_PRE_INVERTED = 1'b0; + parameter CLK_POLARITY = !IS_C_INVERTED; + parameter EN_POLARITY = 1'b1; + assign Q = (CE && !(PRE ^ IS_PRE_INVERTED)) ? (D ^ IS_D_INVERTED) : \$pastQ ; +endmodule + +(* abc_box_id=1006, lib_whitebox, abc_flop *) +module \$__ABC_FDPE_1 ((* abc_flop_q, abc_arrival=303 *) output Q, + (* abc_flop_clk *) input C, + (* abc_flop_en *) input CE, + (* abc_flop_d *) input D, + input PRE, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter CLK_POLARITY = 1'b0; + parameter EN_POLARITY = 1'b1; + assign Q = (CE && !PRE) ? D : \$pastQ ; +endmodule + (* abc_box_id=2000 *) module \$__ABC_LUTMUX6 (input A, input [5:0] S, output Y); endmodule @@ -33,6 +121,7 @@ endmodule module \$__ABC_LUTMUX7 (input A, input [6:0] S, output Y); endmodule + module \$__ABC_RAM32X1D ( // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 (* abc_arrival=1153 *) output DPO, SPO, diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index 779fc5aac..d00d27e2e 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -20,6 +20,125 @@ // ============================================================================ +module \$__ABC_ASYNC (input A, S, output Y); + assign Y = A; +endmodule + +module \$__ABC_FDRE (output Q, + input C, + input CE, + input D, + input R, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_R_INVERTED = 1'b0; + parameter CLK_POLARITY = !IS_C_INVERTED; + parameter EN_POLARITY = 1'b1; + + FDRE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_R_INVERTED(IS_R_INVERTED), + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .R(R) + ); +endmodule + +module \$__ABC_FDRE_1 (output Q, + input C, + input CE, + input D, + input R, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter CLK_POLARITY = 1'b0; + parameter EN_POLARITY = 1'b1; + assign Q = R ? 1'b0 : (CE ? D : \$pastQ ); + + FDRE_1 #( + .INIT(INIT), + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .R(R) + ); +endmodule + +module \$__ABC_FDCE (output Q, + input C, + input CE, + input D, + input CLR, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_CLR_INVERTED = 1'b0; + parameter CLK_POLARITY = !IS_C_INVERTED; + parameter EN_POLARITY = 1'b1; + + FDCE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_CLR_INVERTED(IS_CLR_INVERTED), + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR) + ); +endmodule + +module \$__ABC_FDCE_1 (output Q, + input C, + input CE, + input D, + input CLR, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter CLK_POLARITY = 1'b0; + parameter EN_POLARITY = 1'b1; + + FDCE_1 #( + .INIT(INIT), + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR) + ); +endmodule + +module \$__ABC_FDPE (output Q, + input C, + input CE, + input D, + input PRE, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_PRE_INVERTED = 1'b0; + parameter CLK_POLARITY = !IS_C_INVERTED; + parameter EN_POLARITY = 1'b1; + + FDPE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_PRE_INVERTED(IS_PRE_INVERTED), + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE) + ); +endmodule + +module \$__ABC_FDPE_1 (output Q, + input C, + input CE, + input D, + input PRE, \$pastQ ); + parameter [0:0] INIT = 1'b0; + parameter CLK_POLARITY = 1'b0; + parameter EN_POLARITY = 1'b1; + + FDPE_1 #( + .INIT(INIT), + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE) + ); +endmodule + module \$__ABC_LUTMUX6 (input A, input [5:0] S, output Y); assign Y = A; endmodule diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 61b89b8af..c08af6320 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -38,6 +38,47 @@ CARRY4 4 1 10 8 592 540 520 356 - 512 548 292 - 228 580 526 507 398 385 508 528 378 380 114 +# Box to emulate async behaviour of FD[CP]* +# Inputs: A S +# Outputs: Y +$__ABC_ASYNC 1000 0 2 1 +0 764 + +# The following FD*.{CE,R,CLR,PRE) are offset by 46ps to +# reflect the -46ps Tsu +# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L237-L251 +# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L265-L277 + +# Inputs: C CE D R \$pastQ +# Outputs: Q +FDRE 1001 1 5 1 +0 151 0 446 0 + +# Inputs: C CE D R \$pastQ +# Outputs: Q +FDRE_1 1002 1 5 1 +0 151 0 446 0 + +# Inputs: C CE CLR D \$pastQ +# Outputs: Q +FDCE 1003 1 5 1 +0 151 806 0 0 + +# Inputs: C CE CLR D \$pastQ +# Outputs: Q +FDCE_1 1004 1 5 1 +0 151 806 0 0 + +# Inputs: C CE D PRE \$pastQ +# Outputs: Q +FDPE 1005 1 5 1 +0 151 0 806 0 + +# Inputs: C CE D PRE \$pastQ +# Outputs: Q +FDPE_1 1006 1 5 1 +0 151 0 806 0 + # SLICEM/A6LUT # Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} # Inputs: A S0 S1 S2 S3 S4 S5 diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index d879a56ee..1ab718ccc 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -211,8 +211,7 @@ endmodule `endif -module FDRE ((* abc_arrival=303 *) output reg Q, - input C, CE, D, R); +module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -224,8 +223,7 @@ module FDRE ((* abc_arrival=303 *) output reg Q, endcase endgenerate endmodule -module FDSE ((* abc_arrival=303 *) output reg Q, - input C, CE, D, S); +module FDSE (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -237,8 +235,7 @@ module FDSE ((* abc_arrival=303 *) output reg Q, endcase endgenerate endmodule -module FDCE ((* abc_arrival=303 *) output reg Q, - input C, CE, D, CLR); +module FDCE (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -252,8 +249,7 @@ module FDCE ((* abc_arrival=303 *) output reg Q, endcase endgenerate endmodule -module FDPE ((* abc_arrival=303 *) output reg Q, - input C, CE, D, PRE); +module FDPE (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -267,29 +263,25 @@ module FDPE ((* abc_arrival=303 *) output reg Q, endcase endgenerate endmodule -module FDRE_1 ((* abc_arrival=303 *) output reg Q, - input C, CE, D, R); +module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; initial Q <= INIT; always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; endmodule -module FDSE_1 ((* abc_arrival=303 *) output reg Q, - input C, CE, D, S); +module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; initial Q <= INIT; always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; endmodule -module FDCE_1 ((* abc_arrival=303 *) output reg Q, - input C, CE, D, CLR); +module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; initial Q <= INIT; always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; endmodule -module FDPE_1 ((* abc_arrival=303 *) output reg Q, - input C, CE, D, PRE); +module FDPE_1 (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; initial Q <= INIT; always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b9c4df82f..d28cd2428 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -379,6 +379,8 @@ struct SynthXilinxPass : public ScriptPass std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v"; if (widemux > 0) techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux); + if (abc9) + techmap_args += " -map +/xilinx/ff_map.v"; run("techmap " + techmap_args); run("clean"); } @@ -409,9 +411,11 @@ struct SynthXilinxPass : public ScriptPass // has performed any necessary retiming if (!nosrl || help_mode) run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')"); - std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/ff_map.v"; + std::string techmap_args = "-map +/xilinx/lut_map.v"; if (abc9) techmap_args += " -map +/xilinx/abc_unmap.v"; + else + techmap_args += " -map +/xilinx/ff_map.v"; run("techmap " + techmap_args); run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); -- cgit v1.2.3 From 11cb5fab004c005c6d674494b1486ee501037c5c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Sep 2019 17:00:19 -0700 Subject: Fix typo --- kernel/rtlil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 1d380135b..f42f5430f 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1528,7 +1528,7 @@ std::vector RTLIL::Module::selected_wires() const std::vector RTLIL::Module::selected_cells() const { std::vector result; - result.reserve(wires_.size()); + result.reserve(cells_.size()); for (auto &it : cells_) if (design->selected(this, it.second)) result.push_back(it.second); -- cgit v1.2.3 From fe722b737ce3dfd359d4f37fb558371c07e6a19c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Sep 2019 17:44:01 -0700 Subject: Add -select option to aigmap --- passes/techmap/aigmap.cc | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc index 1d5e1286b..2ecb2f35a 100644 --- a/passes/techmap/aigmap.cc +++ b/passes/techmap/aigmap.cc @@ -27,6 +27,7 @@ struct AigmapPass : public Pass { AigmapPass() : Pass("aigmap", "map logic to and-inverter-graph circuit") { } void help() YS_OVERRIDE { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" aigmap [options] [selection]\n"); log("\n"); @@ -36,10 +37,15 @@ struct AigmapPass : public Pass { log(" -nand\n"); log(" Enable creation of $_NAND_ cells\n"); log("\n"); + log(" -select\n"); + log(" Overwrite replaced cells in the current selection with new $_AND_,\n"); + log(" $_NOT_, and $_NAND_, cells\n"); + + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - bool nand_mode = false; + bool nand_mode = false, select_mode = false; log_header(design, "Executing AIGMAP pass (map logic to AIG).\n"); @@ -50,6 +56,10 @@ struct AigmapPass : public Pass { nand_mode = true; continue; } + if (args[argidx] == "-select") { + select_mode = true; + continue; + } break; } extra_args(args, argidx, design); @@ -62,6 +72,7 @@ struct AigmapPass : public Pass { dict stat_not_replaced; int orig_num_cells = GetSize(module->cells()); + pool new_sel; for (auto cell : module->selected_cells()) { Aig aig(cell); @@ -75,6 +86,8 @@ struct AigmapPass : public Pass { if (aig.name.empty()) { not_replaced_count++; stat_not_replaced[cell->type]++; + if (select_mode) + new_sel.insert(cell->name); continue; } @@ -95,19 +108,33 @@ struct AigmapPass : public Pass { SigBit A = sigs.at(node.left_parent); SigBit B = sigs.at(node.right_parent); if (nand_mode && node.inverter) { - bit = module->NandGate(NEW_ID, A, B); + bit = module->addWire(NEW_ID); + auto gate = module->addNandGate(NEW_ID, A, B, bit); + if (select_mode) + new_sel.insert(gate->name); + goto skip_inverter; } else { pair key(node.left_parent, node.right_parent); if (and_cache.count(key)) bit = and_cache.at(key); - else - bit = module->AndGate(NEW_ID, A, B); + else { + bit = module->addWire(NEW_ID); + auto gate = module->addAndGate(NEW_ID, A, B, bit); + if (select_mode) + new_sel.insert(gate->name); + } } } - if (node.inverter) - bit = module->NotGate(NEW_ID, bit); + if (node.inverter) { + SigBit new_bit = module->addWire(NEW_ID); + auto gate = module->addNotGate(NEW_ID, bit, new_bit); + bit = new_bit; + if (select_mode) + new_sel.insert(gate->name); + + } skip_inverter: for (auto &op : node.outports) @@ -142,6 +169,13 @@ struct AigmapPass : public Pass { for (auto cell : replaced_cells) module->remove(cell); + + if (select_mode) { + log_assert(!design->selection_stack.empty()); + RTLIL::Selection& sel = design->selection_stack.back(); + sel.selected_members[module->name] = std::move(new_sel); + } + } } } AigmapPass; -- 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(-) 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 313d2478e922f33685ee744c5b287ae3bf530645 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Sep 2019 18:41:04 -0700 Subject: Split ABC9 based on clocking only, add "abc_mergeability" attr for en --- passes/techmap/abc9.cc | 116 ++++++++++++------------------------------------- 1 file changed, 28 insertions(+), 88 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 97d4c5ef3..64841d873 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -68,9 +68,6 @@ int map_autoidx; SigMap assign_map; RTLIL::Module *module; -bool clk_polarity, en_polarity; -RTLIL::SigSpec clk_sig, en_sig; - inline std::string remap_name(RTLIL::IdString abc_name) { return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1); @@ -244,7 +241,7 @@ struct abc_output_filter }; void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, - bool cleanup, vector lut_costs, bool dff_mode, std::string clk_str, + bool cleanup, vector lut_costs, bool /*dff_mode*/, std::string /*clk_str*/, bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, bool show_tempdir, std::string box_file, std::string lut_file, std::string wire_delay, const dict &box_lookup @@ -253,39 +250,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri module = current_module; map_autoidx = autoidx++; - if (clk_str != "$") - { - clk_polarity = true; - clk_sig = RTLIL::SigSpec(); - - en_polarity = true; - en_sig = RTLIL::SigSpec(); - } - - if (!clk_str.empty() && clk_str != "$") - { - if (clk_str.find(',') != std::string::npos) { - int pos = clk_str.find(','); - std::string en_str = clk_str.substr(pos+1); - clk_str = clk_str.substr(0, pos); - if (en_str[0] == '!') { - en_polarity = false; - en_str = en_str.substr(1); - } - if (module->wires_.count(RTLIL::escape_id(en_str)) != 0) - en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0)); - } - if (clk_str[0] == '!') { - clk_polarity = false; - clk_str = clk_str.substr(1); - } - if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0) - clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0)); - } - - if (dff_mode && clk_sig.empty()) - log_cmd_error("Clock domain %s not found.\n", clk_str.c_str()); - std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; if (!cleanup) tempdir_name[0] = tempdir_name[4] = '_'; @@ -357,18 +321,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri fprintf(f, "%s\n", abc_script.c_str()); fclose(f); - if (dff_mode || !clk_str.empty()) - { - if (clk_sig.size() == 0) - log("No%s clock domain found. Not extracting any FF cells.\n", clk_str.empty() ? "" : " matching"); - else { - log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); - if (en_sig.size() != 0) - log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); - log("\n"); - } - } - bool count_output = false; for (auto port_name : module->ports) { RTLIL::Wire *port_wire = module->wire(port_name); @@ -383,13 +335,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (count_output) { - design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = design->selection_stack.back(); - sel.select(module); - handle_loops(design); - Pass::call(design, "aigmap"); + Pass::call(design, "aigmap -select"); //log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", // count_gates, GetSize(signal_list), count_input, count_output); @@ -414,8 +362,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri design->remove(design->module(ID($__abc9__))); #endif - design->selection_stack.pop_back(); - // Now 'unexpose' those wires by undoing // the expose operation -- remove them from PO/PI // and re-connecting them back together @@ -909,7 +855,7 @@ struct Abc9Pass : public Pass { #endif std::string script_file, clk_str, box_file, lut_file; std::string delay_target, lutin_shared = "-S 1", wire_delay; - bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; + bool fast_mode = false, /*dff_mode = false,*/ keepff = false, cleanup = true; bool show_tempdir = false; vector lut_costs; markgroups = false; @@ -1118,20 +1064,6 @@ struct Abc9Pass : public Pass { assign_map.set(mod); - if (!dff_mode || !clk_str.empty()) { - - design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = design->selection_stack.back(); - sel.select(mod); - - abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, false, clk_str, keepff, - delay_target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay, box_lookup); - - design->selection_stack.pop_back(); - continue; - } - CellTypes ct(design); std::vector all_cells = mod->selected_cells(); @@ -1141,8 +1073,8 @@ struct Abc9Pass : public Pass { std::set expand_queue_up, next_expand_queue_up; std::set expand_queue_down, next_expand_queue_down; - typedef tuple clkdomain_t; - std::map> assigned_cells; + typedef pair clkdomain_t; + std::map> assigned_cells; std::map assigned_cells_reverse; std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; @@ -1154,9 +1086,12 @@ struct Abc9Pass : public Pass { IdString en_port; }; dict flop_data; + typedef clkdomain_t endomain_t; + std::map mergeability_class; for (auto cell : all_cells) { clkdomain_t key; + endomain_t key2; for (auto &conn : cell->connections()) for (auto bit : conn.second) { @@ -1175,6 +1110,7 @@ struct Abc9Pass : public Pass { } } + // TODO: Generate this outside decltype(flop_data)::iterator it; if (seen_cells.insert(cell->type).second) { RTLIL::Module* inst_module = design->module(cell->type); @@ -1225,15 +1161,20 @@ struct Abc9Pass : public Pass { log_error("'EN_POLARITY' is not a parameter on module '%s'.\n", log_id(cell->type)); bool this_en_pol = jt->second.as_bool(); - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(data.clk_port)), this_en_pol, assign_map(cell->getPort(data.en_port))); + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(data.clk_port))); unassigned_cells.erase(cell); expand_queue.insert(cell); expand_queue_up.insert(cell); expand_queue_down.insert(cell); - assigned_cells[key].push_back(cell); + assigned_cells[key].insert(cell->name); assigned_cells_reverse[cell] = key; + + key2 = endomain_t(this_en_pol, assign_map(cell->getPort(data.en_port))); + auto r = mergeability_class.emplace(key2, mergeability_class.size() + 1); + auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc_mergeability), r.first->second)); + log_assert(r2.second); } while (!expand_queue_up.empty() || !expand_queue_down.empty()) @@ -1249,7 +1190,7 @@ struct Abc9Pass : public Pass { if (unassigned_cells.count(c)) { unassigned_cells.erase(c); next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c); + assigned_cells[key].insert(c->name); assigned_cells_reverse[c] = key; expand_queue.insert(c); } @@ -1266,7 +1207,7 @@ struct Abc9Pass : public Pass { if (unassigned_cells.count(c)) { unassigned_cells.erase(c); next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c); + assigned_cells[key].insert(c->name); assigned_cells_reverse[c] = key; expand_queue.insert(c); } @@ -1289,7 +1230,7 @@ struct Abc9Pass : public Pass { if (unassigned_cells.count(c)) { unassigned_cells.erase(c); next_expand_queue.insert(c); - assigned_cells[key].push_back(c); + assigned_cells[key].insert(c->name); assigned_cells_reverse[c] = key; } bit_to_cell[bit].clear(); @@ -1299,28 +1240,27 @@ struct Abc9Pass : public Pass { expand_queue.swap(next_expand_queue); } - clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); + clkdomain_t key(true, RTLIL::SigSpec()); for (auto cell : unassigned_cells) { - assigned_cells[key].push_back(cell); + assigned_cells[key].insert(cell->name); assigned_cells_reverse[cell] = key; } log_header(design, "Summary of detected clock domains:\n"); for (auto &it : assigned_cells) - log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), - std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), - std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + log(" %d cells in clk=%s%s\n", GetSize(it.second), + std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first))); + design->selection_stack.emplace_back(false); for (auto &it : assigned_cells) { - clk_polarity = std::get<0>(it.first); - clk_sig = assign_map(std::get<1>(it.first)); - en_polarity = std::get<2>(it.first); - en_sig = assign_map(std::get<3>(it.first)); - abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$", + RTLIL::Selection& sel = design->selection_stack.back(); + sel.selected_members[mod->name] = std::move(it.second); + abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, false, "$", keepff, delay_target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, wire_delay, box_lookup); assign_map.set(mod); } + design->selection_stack.pop_back(); } assign_map.clear(); -- 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(-) 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 6b9f90de789b1d0daf93ac1d2b608b057e7ca272 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Sep 2019 17:00:19 -0700 Subject: Fix typo --- kernel/rtlil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 1d380135b..f42f5430f 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1528,7 +1528,7 @@ std::vector RTLIL::Module::selected_wires() const std::vector RTLIL::Module::selected_cells() const { std::vector result; - result.reserve(wires_.size()); + result.reserve(cells_.size()); for (auto &it : cells_) if (design->selected(this, it.second)) result.push_back(it.second); -- 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 ++++++++++++--------- frontends/aiger/aigerparse.cc | 19 ++- passes/techmap/abc9.cc | 143 +++++++++---------- techlibs/xilinx/abc_map.v | 77 ++++++----- techlibs/xilinx/abc_model.v | 90 +----------- techlibs/xilinx/abc_unmap.v | 122 +---------------- techlibs/xilinx/abc_xc7.box | 22 ++- techlibs/xilinx/cells_sim.v | 294 +++++++++++++++++++++++++++++++++------- techlibs/xilinx/synth_xilinx.cc | 4 +- 9 files changed, 485 insertions(+), 441 deletions(-) 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)); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7a467b91e..439311230 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -740,7 +740,7 @@ void AigerReader::post_process() bool is_flop = false; if (seen_boxes.insert(cell->type).second) { - if (box_module->attributes.count("\\abc_flop")) { + if (box_module->attributes.count("\\abc9_flop")) { log_assert(flop_count < flopNum); flops.insert(cell->type); is_flop = true; @@ -811,12 +811,18 @@ void AigerReader::post_process() } rhs.append(wire); } - - if (!is_flop || port_name != "\\$pastQ") - cell->setPort(port_name, rhs); + cell->setPort(port_name, rhs); } if (is_flop) { + Wire* port = box_module->wire("\\$currQ"); + log_assert(port); + log_assert(co_count < outputs.size()); + Wire *wire = outputs[co_count++]; + log_assert(wire); + log_assert(wire->port_output); + wire->port_output = false; + RTLIL::Wire *d = outputs[outputs.size() - flopNum + flop_count]; log_assert(d); log_assert(d->port_output); @@ -827,9 +833,10 @@ void AigerReader::post_process() log_assert(q->port_input); q->port_input = false; + auto ff = module->addCell(NEW_ID, "$__ABC_FF_"); + ff->setPort("\\D", d); + ff->setPort("\\Q", q); flop_count++; - module->connect(q, d); - cell->set_bool_attribute("\\abc_flop"); continue; } } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 64841d873..a5d823139 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -536,8 +536,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell_stats[mapped_cell->type]++; RTLIL::Cell *existing_cell = nullptr; - if (mapped_cell->type == ID($lut)) { - if (GetSize(mapped_cell->getPort(ID::A)) == 1 && mapped_cell->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) { + if (mapped_cell->type.in(ID($lut), ID($__ABC_FF_))) { + if (mapped_cell->type == ID($lut) && + GetSize(mapped_cell->getPort(ID::A)) == 1 && + mapped_cell->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) { SigSpec my_a = module->wires_.at(remap_name(mapped_cell->getPort(ID::A).as_wire()->name)); SigSpec my_y = module->wires_.at(remap_name(mapped_cell->getPort(ID::Y).as_wire()->name)); module->connect(my_y, my_a); @@ -564,7 +566,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell->attributes = mapped_cell->attributes; } - auto abc_flop = mapped_cell->attributes.count("\\abc_flop"); + RTLIL::Module* box_module = design->module(mapped_cell->type); + auto abc_flop = box_module && box_module->attributes.count("\\abc9_flop"); for (auto &conn : mapped_cell->connections()) { RTLIL::SigSpec newsig; for (auto c : conn.second.chunks()) { @@ -1073,29 +1076,18 @@ struct Abc9Pass : public Pass { std::set expand_queue_up, next_expand_queue_up; std::set expand_queue_down, next_expand_queue_down; - typedef pair clkdomain_t; - std::map> assigned_cells; - std::map assigned_cells_reverse; + std::map> assigned_cells; + std::map assigned_cells_reverse; std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; - pool seen_cells; - struct flop_data_t { - IdString clk_port; - IdString en_port; - }; - dict flop_data; - typedef clkdomain_t endomain_t; + typedef std::pair endomain_t; std::map mergeability_class; for (auto cell : all_cells) { - clkdomain_t key; - endomain_t key2; - for (auto &conn : cell->connections()) - for (auto bit : conn.second) { - bit = assign_map(bit); + for (auto bit : assign_map(conn.second)) if (bit.wire != nullptr) { cell_to_bit[cell].insert(bit); bit_to_cell[bit].insert(cell); @@ -1108,72 +1100,68 @@ struct Abc9Pass : public Pass { bit_to_cell_up[bit].insert(cell); } } - } - - // TODO: Generate this outside - decltype(flop_data)::iterator it; - if (seen_cells.insert(cell->type).second) { - RTLIL::Module* inst_module = design->module(cell->type); - if (!inst_module) - continue; - - if (!inst_module->attributes.count("\\abc_flop")) - continue; - - IdString abc_flop_clk, abc_flop_en; - for (auto port_name : inst_module->ports) { - auto wire = inst_module->wire(port_name); - log_assert(wire); - if (wire->attributes.count("\\abc_flop_clk")) { - if (abc_flop_clk != IdString()) - log_error("More than one port has the 'abc_flop_clk' attribute set on module '%s'.\n", log_id(cell->type)); - abc_flop_clk = port_name; - } - if (wire->attributes.count("\\abc_flop_en")) { - if (abc_flop_en != IdString()) - log_error("More than one port has the 'abc_flop_en' attribute set on module '%s'.\n", log_id(cell->type)); - abc_flop_en = port_name; - } - } - if (abc_flop_clk == IdString()) - log_error("'abc_flop_clk' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); - if (abc_flop_en == IdString()) - log_error("'abc_flop_en' attribute not found on any ports on module '%s'.\n", log_id(cell->type)); + auto inst_module = design->module(cell->type); + if (!inst_module || !inst_module->attributes.count("\\abc9_flop")) + continue; - it = flop_data.insert(std::make_pair(cell->type, flop_data_t{abc_flop_clk, abc_flop_en})).first; - } - else { - it = flop_data.find(cell->type); - if (it == flop_data.end()) - continue; + auto derived_name = inst_module->derive(design, cell->parameters); + auto derived_module = design->module(derived_name); + log_assert(derived_module); + Pass::call_on_module(design, derived_module, "proc"); + SigMap derived_sigmap(derived_module); + + Wire *currQ = derived_module->wire("\\$currQ"); + if (currQ == NULL) + log_error("'\\$currQ' is not a wire present in module '%s'.\n", log_id(cell->type)); + log_assert(!currQ->port_output); + if (!currQ->port_input) { + currQ->port_input = true; + derived_module->ports.push_back(currQ->name); + currQ->port_id = GetSize(derived_module->ports); +#ifndef NDEBUG + derived_module->check(); +#endif } - const auto &data = it->second; - - auto jt = cell->parameters.find("\\CLK_POLARITY"); - if (jt == cell->parameters.end()) - log_error("'CLK_POLARITY' is not a parameter on module '%s'.\n", log_id(cell->type)); - bool this_clk_pol = jt->second.as_bool(); - - jt = cell->parameters.find("\\EN_POLARITY"); - if (jt == cell->parameters.end()) - log_error("'EN_POLARITY' is not a parameter on module '%s'.\n", log_id(cell->type)); - bool this_en_pol = jt->second.as_bool(); + SigSpec pattern; + SigSpec with; + for (auto &conn : cell->connections()) { + Wire *first = derived_module->wire(conn.first); + log_assert(first); + SigSpec second = assign_map(conn.second); + log_assert(GetSize(first) == GetSize(second)); + pattern.append(first); + with.append(second); + } - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(data.clk_port))); + Wire *abc9_clock_wire = derived_module->wire("\\$abc9_clock"); + if (abc9_clock_wire == NULL) + log_error("'\\$abc9_clock' is not a wire present in module '%s'.\n", log_id(cell->type)); + SigSpec abc9_clock = derived_sigmap(abc9_clock_wire); + abc9_clock.replace(pattern, with); + for (const auto &c : abc9_clock.chunks()) + log_assert(!c.wire || c.wire->module == mod); + + Wire *abc9_control_wire = derived_module->wire("\\$abc9_control"); + if (abc9_control_wire == NULL) + log_error("'\\$abc9_control' is not a wire present in module '%s'.\n", log_id(cell->type)); + SigSpec abc9_control = derived_sigmap(abc9_control_wire); + abc9_control.replace(pattern, with); + for (const auto &c : abc9_control.chunks()) + log_assert(!c.wire || c.wire->module == mod); unassigned_cells.erase(cell); expand_queue.insert(cell); expand_queue_up.insert(cell); expand_queue_down.insert(cell); - assigned_cells[key].insert(cell->name); - assigned_cells_reverse[cell] = key; + assigned_cells[abc9_clock].insert(cell->name); + assigned_cells_reverse[cell] = abc9_clock; - key2 = endomain_t(this_en_pol, assign_map(cell->getPort(data.en_port))); - auto r = mergeability_class.emplace(key2, mergeability_class.size() + 1); - auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc_mergeability), r.first->second)); + endomain_t key(cell->type, abc9_control); + auto r = mergeability_class.emplace(key, mergeability_class.size() + 1); + auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); log_assert(r2.second); } @@ -1182,7 +1170,7 @@ struct Abc9Pass : public Pass { if (!expand_queue_up.empty()) { RTLIL::Cell *cell = *expand_queue_up.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); + SigSpec key = assigned_cells_reverse.at(cell); expand_queue_up.erase(cell); for (auto bit : cell_to_bit_up[cell]) @@ -1199,7 +1187,7 @@ struct Abc9Pass : public Pass { if (!expand_queue_down.empty()) { RTLIL::Cell *cell = *expand_queue_down.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); + SigSpec key = assigned_cells_reverse.at(cell); expand_queue_down.erase(cell); for (auto bit : cell_to_bit_down[cell]) @@ -1222,7 +1210,7 @@ struct Abc9Pass : public Pass { while (!expand_queue.empty()) { RTLIL::Cell *cell = *expand_queue.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); + SigSpec key = assigned_cells_reverse.at(cell); expand_queue.erase(cell); for (auto bit : cell_to_bit.at(cell)) { @@ -1240,7 +1228,7 @@ struct Abc9Pass : public Pass { expand_queue.swap(next_expand_queue); } - clkdomain_t key(true, RTLIL::SigSpec()); + SigSpec key; for (auto cell : unassigned_cells) { assigned_cells[key].insert(cell->name); assigned_cells_reverse[cell] = key; @@ -1248,8 +1236,7 @@ struct Abc9Pass : public Pass { log_header(design, "Summary of detected clock domains:\n"); for (auto &it : assigned_cells) - log(" %d cells in clk=%s%s\n", GetSize(it.second), - std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first))); + log(" %d cells in clk=%s\n", GetSize(it.second), log_signal(it.first)); design->selection_stack.emplace_back(false); for (auto &it : assigned_cells) { diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 9f96d16be..056f66bbb 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -26,27 +26,23 @@ module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; wire \$nextQ ; - \$__ABC_FDRE #( + FDRE #( .INIT(INIT), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), - .IS_R_INVERTED(IS_R_INVERTED), - .CLK_POLARITY(!IS_C_INVERTED), - .EN_POLARITY(1'b1) + .IS_R_INVERTED(IS_R_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .R(R) + .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .R(R) ); \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(Q)); endmodule module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; wire \$nextQ ; - \$__ABC_FDRE_1 #( - .INIT(|0), - .CLK_POLARITY(1'b0), - .EN_POLARITY(1'b1) + FDRE_1 #( + .INIT(|0), ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .R(R) + .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .R(R) ); \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(Q)); endmodule @@ -57,28 +53,24 @@ module FDCE (output reg Q, input C, CE, D, CLR); parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; wire \$nextQ , \$currQ ; - \$__ABC_FDCE #( + FDCE #( .INIT(INIT), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), - .IS_CLR_INVERTED(IS_CLR_INVERTED), - .CLK_POLARITY(!IS_C_INVERTED), - .EN_POLARITY(1'b1) + .IS_CLR_INVERTED(IS_CLR_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .CLR(CLR) + .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .CLR(CLR) ); \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); - \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(CLR), .Y(Q)); + \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); endmodule module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; wire \$nextQ , \$currQ ; - \$__ABC_FDCE_1 #( - .INIT(INIT), - .CLK_POLARITY(1'b0), - .EN_POLARITY(1'b1) + FDCE_1 #( + .INIT(INIT) ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .CLR(CLR) + .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .CLR(CLR) ); \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(CLR), .Y(Q)); @@ -90,33 +82,56 @@ module FDPE (output reg Q, input C, CE, D, PRE); parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; wire \$nextQ , \$currQ ; - \$__ABC_FDPE #( + FDPE #( .INIT(INIT), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), .IS_PRE_INVERTED(IS_PRE_INVERTED), - .CLK_POLARITY(!IS_C_INVERTED), - .EN_POLARITY(1'b1) ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .PRE(PRE) + .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .PRE(PRE) ); \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); - \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(PRE), .Y(Q)); + \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); endmodule module FDPE_1 (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; wire \$nextQ , \$currQ ; - \$__ABC_FDPE_1 #( - .INIT(INIT), - .CLK_POLARITY(1'b0), - .EN_POLARITY(1'b1) + FDPE_1 #( + .INIT(INIT) ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$pastQ (Q), .C(C), .CE(CE), .PRE(PRE) + .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .PRE(PRE) ); \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(PRE), .Y(Q)); endmodule +module FDSE (output reg Q, input C, CE, D, S); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_S_INVERTED = 1'b0; + wire \$nextQ ; + FDSE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_S_INVERTED(IS_S_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .S(S) + ); + \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(Q)); +endmodule +module FDSE_1 (output reg Q, input C, CE, D, S); + parameter [0:0] INIT = 1'b0; + wire \$nextQ ; + FDSE_1 #( + .INIT(|0), + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .S(S) + ); + \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(Q)); +endmodule + module RAM32X1D ( output DPO, SPO, input D, diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index d94ddb7e5..a2914464d 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -26,97 +26,9 @@ module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); : (S0 ? I1 : I0); endmodule -module \$__ABC_FF_ (input C, D, output Q); +module \$__ABC_FF_ (input D, output Q); endmodule (* abc_box_id = 1000 *) module \$__ABC_ASYNC (input A, S, output Y); endmodule - -(* abc_box_id=1001, lib_whitebox, abc_flop *) -module \$__ABC_FDRE ((* abc_flop_q, abc_arrival=303 *) output Q, - (* abc_flop_clk *) input C, - (* abc_flop_en *) input CE, - (* abc_flop_d *) input D, - input R, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_R_INVERTED = 1'b0; - parameter CLK_POLARITY = !IS_C_INVERTED; - parameter EN_POLARITY = 1'b1; - assign Q = (R ^ IS_R_INVERTED) ? 1'b0 : (CE ? (D ^ IS_D_INVERTED) : \$pastQ ); -endmodule - -(* abc_box_id=1002, lib_whitebox, abc_flop *) -module \$__ABC_FDRE_1 ((* abc_flop_q, abc_arrival=303 *) output Q, - (* abc_flop_clk *) input C, - (* abc_flop_en *) input CE, - (* abc_flop_d *) input D, - input R, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter CLK_POLARITY = 1'b0; - parameter EN_POLARITY = 1'b1; - assign Q = R ? 1'b0 : (CE ? D : \$pastQ ); -endmodule - -(* abc_box_id=1003, lib_whitebox, abc_flop *) -module \$__ABC_FDCE ((* abc_flop_q, abc_arrival=303 *) output Q, - (* abc_flop_clk *) input C, - (* abc_flop_en *) input CE, - (* abc_flop_d *) input D, - input CLR, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_CLR_INVERTED = 1'b0; - parameter CLK_POLARITY = !IS_C_INVERTED; - parameter EN_POLARITY = 1'b1; - assign Q = (CE && !(CLR ^ IS_CLR_INVERTED)) ? (D ^ IS_D_INVERTED) : \$pastQ ; -endmodule - -(* abc_box_id=1004, lib_whitebox, abc_flop *) -module \$__ABC_FDCE_1 ((* abc_flop_q, abc_arrival=303 *) output Q, - (* abc_flop_clk *) input C, - (* abc_flop_en *) input CE, - (* abc_flop_d *) input D, - input CLR, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter CLK_POLARITY = 1'b0; - parameter EN_POLARITY = 1'b1; - assign Q = (CE && !CLR) ? D : \$pastQ ; -endmodule - -(* abc_box_id=1005, lib_whitebox, abc_flop *) -module \$__ABC_FDPE ((* abc_flop_q, abc_arrival=303 *) output Q, - (* abc_flop_clk *) input C, - (* abc_flop_en *) input CE, - (* abc_flop_d *) input D, - input PRE, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_PRE_INVERTED = 1'b0; - parameter CLK_POLARITY = !IS_C_INVERTED; - parameter EN_POLARITY = 1'b1; - assign Q = (CE && !(PRE ^ IS_PRE_INVERTED)) ? (D ^ IS_D_INVERTED) : \$pastQ ; -endmodule - -(* abc_box_id=1006, lib_whitebox, abc_flop *) -module \$__ABC_FDPE_1 ((* abc_flop_q, abc_arrival=303 *) output Q, - (* abc_flop_clk *) input C, - (* abc_flop_en *) input CE, - (* abc_flop_d *) input D, - input PRE, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter CLK_POLARITY = 1'b0; - parameter EN_POLARITY = 1'b1; - assign Q = (CE && !PRE) ? D : \$pastQ ; -endmodule - -(* abc_box_id=2000 *) -module \$__ABC_LUT6 (input A, input [5:0] S, output Y); -endmodule -(* abc_box_id=2001 *) -module \$__ABC_LUT7 (input A, input [6:0] S, output Y); -endmodule diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index c24571747..bf8253adb 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -24,124 +24,6 @@ module \$__ABC_ASYNC (input A, S, output Y); assign Y = A; endmodule -module \$__ABC_FDRE (output Q, - input C, - input CE, - input D, - input R, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_R_INVERTED = 1'b0; - parameter CLK_POLARITY = !IS_C_INVERTED; - parameter EN_POLARITY = 1'b1; - - FDRE #( - .INIT(INIT), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_R_INVERTED(IS_R_INVERTED), - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .R(R) - ); -endmodule - -module \$__ABC_FDRE_1 (output Q, - input C, - input CE, - input D, - input R, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter CLK_POLARITY = 1'b0; - parameter EN_POLARITY = 1'b1; - assign Q = R ? 1'b0 : (CE ? D : \$pastQ ); - - FDRE_1 #( - .INIT(INIT), - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .R(R) - ); -endmodule - -module \$__ABC_FDCE (output Q, - input C, - input CE, - input D, - input CLR, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_CLR_INVERTED = 1'b0; - parameter CLK_POLARITY = !IS_C_INVERTED; - parameter EN_POLARITY = 1'b1; - - FDCE #( - .INIT(INIT), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_CLR_INVERTED(IS_CLR_INVERTED), - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR) - ); -endmodule - -module \$__ABC_FDCE_1 (output Q, - input C, - input CE, - input D, - input CLR, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter CLK_POLARITY = 1'b0; - parameter EN_POLARITY = 1'b1; - - FDCE_1 #( - .INIT(INIT), - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR) - ); -endmodule - -module \$__ABC_FDPE (output Q, - input C, - input CE, - input D, - input PRE, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_PRE_INVERTED = 1'b0; - parameter CLK_POLARITY = !IS_C_INVERTED; - parameter EN_POLARITY = 1'b1; - - FDPE #( - .INIT(INIT), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_PRE_INVERTED(IS_PRE_INVERTED), - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE) - ); -endmodule - -module \$__ABC_FDPE_1 (output Q, - input C, - input CE, - input D, - input PRE, \$pastQ ); - parameter [0:0] INIT = 1'b0; - parameter CLK_POLARITY = 1'b0; - parameter EN_POLARITY = 1'b1; - - FDPE_1 #( - .INIT(INIT), - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE) - ); -endmodule - -module \$__ABC_LUT6 (input A, input [5:0] S, output Y); - assign Y = A; -endmodule -module \$__ABC_LUT7 (input A, input [6:0] S, output Y); - assign Y = A; +module \$__ABC_FF_ (input D, output Q); + assign Q = D; endmodule diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index aebb8b975..daaa4d16f 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -52,36 +52,46 @@ $__ABC_ASYNC 1000 0 2 1 # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L237-L251 # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L265-L277 -# Inputs: C CE D R \$pastQ +# Inputs: C CE D R \$currQ # Outputs: Q FDRE 1001 1 5 1 0 151 0 446 0 -# Inputs: C CE D R \$pastQ +# Inputs: C CE D R \$currQ # Outputs: Q FDRE_1 1002 1 5 1 0 151 0 446 0 -# Inputs: C CE CLR D \$pastQ +# Inputs: C CE CLR D \$currQ # Outputs: Q FDCE 1003 1 5 1 0 151 806 0 0 -# Inputs: C CE CLR D \$pastQ +# Inputs: C CE CLR D \$currQ # Outputs: Q FDCE_1 1004 1 5 1 0 151 806 0 0 -# Inputs: C CE D PRE \$pastQ +# Inputs: C CE D PRE \$currQ # Outputs: Q FDPE 1005 1 5 1 0 151 0 806 0 -# Inputs: C CE D PRE \$pastQ +# Inputs: C CE D PRE \$currQ # Outputs: Q FDPE_1 1006 1 5 1 0 151 0 806 0 +# Inputs: C CE D S \$currQ +# Outputs: Q +FDSE 1007 1 5 1 +0 151 0 446 0 + +# Inputs: C CE D S \$currQ +# Outputs: Q +FDSE_1 1008 1 5 1 +0 151 0 446 0 + # SLICEM/A6LUT # Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} # Necessary since RAMD* and SRL* have both combinatorial (i.e. diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index ef4340d10..ee9d48684 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -240,6 +240,7 @@ endmodule // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L238-L250 +(* abc_box_id=1001, lib_whitebox, abc9_flop *) module FDRE ( (* abc_arrival=303 *) output reg Q, @@ -257,35 +258,72 @@ module FDRE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; initial Q <= INIT; + wire \$currQ ; + reg \$nextQ ; + always @* if (R == !IS_R_INVERTED) \$nextQ = 1'b0; else if (CE) \$nextQ = D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; +`ifdef _ABC + // `abc9' requires that complex flops be split into a combinatorial + // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `\$currQ' wire. + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] \$abc9_clock = {C, IS_C_INVERTED}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] \$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; + always @* Q = \$nextQ ; +`else + assign \$currQ = Q; generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 1'b0: always @(posedge C) Q <= \$nextQ ; + 1'b1: always @(negedge C) Q <= \$nextQ ; endcase endgenerate +`endif endmodule -module FDSE ( +(* abc_box_id=1002, lib_whitebox, abc9_flop *) +module FDRE_1 ( (* abc_arrival=303 *) output reg Q, (* clkbuf_sink *) - (* invertible_pin = "IS_C_INVERTED" *) input C, - input CE, - (* invertible_pin = "IS_D_INVERTED" *) - input D, - (* invertible_pin = "IS_S_INVERTED" *) - input S + input CE, D, R ); - parameter [0:0] INIT = 1'b1; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_S_INVERTED = 1'b0; + parameter [0:0] INIT = 1'b0; initial Q <= INIT; - generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase endgenerate + wire \$currQ ; + reg \$nextQ ; + always @* if (R) Q <= 1'b0; else if (CE) Q <= D; else \$nextQ = \$currQ ; +`ifdef _ABC + // `abc9' requires that complex flops be split into a combinatorial + // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `\$currQ' wire. + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] \$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] \$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; + always @* Q = \$nextQ ; +`else + assign \$currQ = Q; + always @(negedge C) Q <= \$nextQ ; +`endif endmodule +(* abc_box_id=1003, lib_whitebox, abc9_flop *) module FDCE ( (* abc_arrival=303 *) output reg Q, @@ -303,14 +341,78 @@ module FDCE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; initial Q <= INIT; + wire \$currQ ; + reg \$nextQ ; + always @* if (CE) Q <= D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; +`ifdef _ABC + // `abc9' requires that complex flops be split into a combinatorial + // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `\$currQ' wire. + // Since this is an async flop, async behaviour is also dealt with + // using the $_ABC_ASYNC box by abc_map.v + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] \$abc9_clock = {C, IS_C_INVERTED}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] \$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; + always @* Q = \$nextQ ; +`else + assign \$currQ = Q; generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) - 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= \$nextQ ; + 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= \$nextQ ; + 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= \$nextQ ; + 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= \$nextQ ; endcase endgenerate +`endif endmodule +(* abc_box_id=1004, lib_whitebox, abc9_flop *) +module FDCE_1 ( + (* abc_arrival=303 *) + output reg Q, + (* clkbuf_sink *) + input C, + input CE, D, CLR +); + parameter [0:0] INIT = 1'b0; + initial Q <= INIT; + wire \$currQ ; + reg \$nextQ ; + always @* if (CE) Q <= D; else \$nextQ = \$currQ ; +`ifdef _ABC + // `abc9' requires that complex flops be split into a combinatorial + // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `\$currQ' wire. + // Since this is an async flop, async behaviour is also dealt with + // using the $_ABC_ASYNC box by abc_map.v + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] \$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] \$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; + always @* Q = \$nextQ ; +`else + assign \$currQ = Q; + always @(negedge C, posedge CLR) if (CLR == !IS_CLR_INVERTED) Q <= 1'b0; else Q <= \$nextQ ; +`endif +endmodule + +(* abc_box_id=1005, lib_whitebox, abc9_flop *) module FDPE ( (* abc_arrival=303 *) output reg Q, @@ -328,60 +430,158 @@ module FDPE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; initial Q <= INIT; + wire \$currQ ; + reg \$nextQ ; + always @* if (CE) Q <= D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; +`ifdef _ABC + // `abc9' requires that complex flops be split into a combinatorial + // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `\$currQ' wire. + // Since this is an async flop, async behaviour is also dealt with + // using the $_ABC_ASYNC box by abc_map.v + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] \$abc9_clock = {C, IS_C_INVERTED}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] \$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; + always @* Q = \$nextQ ; +`else + assign \$currQ = Q; generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) - 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= \$nextQ ; + 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= \$nextQ ; + 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= \$nextQ ; + 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= \$nextQ ; endcase endgenerate +`endif endmodule -module FDRE_1 ( - (* abc_arrival=303 *) - output reg Q, - (* clkbuf_sink *) - input C, - input CE, D, R -); - parameter [0:0] INIT = 1'b0; - initial Q <= INIT; - always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; -endmodule - -module FDSE_1 ( +(* abc_box_id=1006, lib_whitebox, abc9_flop *) +module FDPE_1 ( (* abc_arrival=303 *) output reg Q, (* clkbuf_sink *) input C, - input CE, D, S + input CE, D, PRE ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; - always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; + wire \$currQ ; + reg \$nextQ ; + always @* if (CE) Q <= D; else \$nextQ = \$currQ ; +`ifdef _ABC + // `abc9' requires that complex flops be split into a combinatorial + // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `\$currQ' wire. + // Since this is an async flop, async behaviour is also dealt with + // using the $_ABC_ASYNC box by abc_map.v + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] \$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] \$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; + always @* Q = \$nextQ ; +`else + assign \$currQ = Q; + always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else Q <= \$nextQ ; +`endif endmodule -module FDCE_1 ( +(* abc_box_id=1007, lib_whitebox, abc9_flop *) +module FDSE ( (* abc_arrival=303 *) output reg Q, (* clkbuf_sink *) + (* invertible_pin = "IS_C_INVERTED" *) input C, - input CE, D, CLR + input CE, + (* invertible_pin = "IS_D_INVERTED" *) + input D, + (* invertible_pin = "IS_S_INVERTED" *) + input S ); - parameter [0:0] INIT = 1'b0; + parameter [0:0] INIT = 1'b1; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_S_INVERTED = 1'b0; initial Q <= INIT; - always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; + wire \$currQ ; + reg \$nextQ ; + always @* if (S == !IS_S_INVERTED) \$nextQ = 1'b1; else if (CE) \$nextQ = D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; +`ifdef _ABC + // `abc9' requires that complex flops be split into a combinatorial + // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `\$currQ' wire. + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] \$abc9_clock = {C, IS_C_INVERTED}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] \$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; + always @* Q = \$nextQ ; +`else + assign \$currQ = Q; + generate case (|IS_C_INVERTED) + 1'b0: always @(posedge C) Q <= \$nextQ ; + 1'b1: always @(negedge C) Q <= \$nextQ ; + endcase endgenerate +`endif endmodule -module FDPE_1 ( +(* abc_box_id=1008, lib_whitebox, abc9_flop *) +module FDSE_1 ( (* abc_arrival=303 *) output reg Q, (* clkbuf_sink *) input C, - input CE, D, PRE + input CE, D, S ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; - always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; + wire \$currQ ; + reg \$nextQ ; + always @* if (S) \$nextQ = 1'b1; else if (CE) \$nextQ = D; else \$nextQ = \$currQ ; +`ifdef _ABC + // `abc9' requires that complex flops be split into a combinatorial + // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `\$currQ' wire. + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] \$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] \$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; + always @* Q = \$nextQ ; +`else + assign \$currQ = Q; + always @(negedge C) Q <= \$nextQ ; +`endif endmodule module RAM32X1D ( diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 888b5ed7b..f5143ca82 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -276,9 +276,9 @@ struct SynthXilinxPass : public ScriptPass if (check_label("begin")) { if (vpr) - run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); + run("read_verilog -lib -D_ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); else - run("read_verilog -lib +/xilinx/cells_sim.v"); + run("read_verilog -lib -D_ABC +/xilinx/cells_sim.v"); if (help_mode) run("read_verilog -lib +/xilinx/{family}_cells_xtra.v"); -- cgit v1.2.3 From 5a4011e8c9d2c7c94ccaa6ff80a1ca1290e1053b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 29 Sep 2019 09:58:00 -0700 Subject: Fix "scc" call inside abc9 to consider all wires --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index a5d823139..ce27f7eea 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -75,7 +75,7 @@ inline std::string remap_name(RTLIL::IdString abc_name) void handle_loops(RTLIL::Design *design) { - Pass::call(design, "scc -set_attr abc_scc_id {}"); + Pass::call(design, "scc -set_attr abc_scc_id {} % w:*"); // For every unique SCC found, (arbitrarily) find the first // cell in the component, and select (and mark) all its output -- cgit v1.2.3 From 18ebb86edbade4a94833dead59d69fddd980f5bd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 29 Sep 2019 11:25:34 -0700 Subject: FDCE_1 does not have IS_CLR_INVERTED --- techlibs/xilinx/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index ee9d48684..cf39bd45b 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -408,7 +408,7 @@ module FDCE_1 ( always @* Q = \$nextQ ; `else assign \$currQ = Q; - always @(negedge C, posedge CLR) if (CLR == !IS_CLR_INVERTED) Q <= 1'b0; else Q <= \$nextQ ; + always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else Q <= \$nextQ ; `endif endmodule -- cgit v1.2.3 From f6203e6bd65f7383f14a15e926fc4b8f5f9a3edf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 29 Sep 2019 21:55:53 -0700 Subject: Missing endmodule --- techlibs/xilinx/abc_model.v | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index b302e46f6..8255804c2 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -35,6 +35,7 @@ endmodule (* abc_box_id = 1000 *) module \$__ABC_ASYNC (input A, S, output Y); +endmodule // Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} // Necessary since RAMD* and SRL* have both combinatorial (i.e. -- 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(-) 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 ++++++++++++-------- passes/techmap/abc9.cc | 37 ++++++++++++++++--------------------- 2 files changed, 28 insertions(+), 29 deletions(-) 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"); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 0276283a5..33f608d29 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -65,16 +65,15 @@ PRIVATE_NAMESPACE_BEGIN bool markgroups; int map_autoidx; -SigMap assign_map; -RTLIL::Module *module; inline std::string remap_name(RTLIL::IdString abc_name) { return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1); } -void handle_loops(RTLIL::Design *design) +void handle_loops(RTLIL::Design *design, RTLIL::Module *module) { + // FIXME: Do not run on all modules in design!?! Pass::call(design, "scc -set_attr abc_scc_id {} % w:*"); // For every unique SCC found, (arbitrarily) find the first @@ -240,14 +239,13 @@ struct abc_output_filter } }; -void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, +void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file, bool cleanup, vector lut_costs, bool /*dff_mode*/, std::string /*clk_str*/, bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, bool show_tempdir, std::string box_file, std::string lut_file, std::string wire_delay, const dict &box_lookup ) { - module = current_module; map_autoidx = autoidx++; std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; @@ -335,7 +333,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (count_output) { - handle_loops(design); + handle_loops(design, module); Pass::call(design, "aigmap -select"); @@ -862,8 +860,6 @@ struct Abc9Pass : public Pass { log_header(design, "Executing ABC9 pass (technology mapping using ABC9).\n"); log_push(); - assign_map.clear(); - #ifdef ABCEXTERNAL std::string exe_file = ABCEXTERNAL; #else @@ -1068,21 +1064,21 @@ struct Abc9Pass : public Pass { } } - for (auto mod : design->selected_modules()) + for (auto module : design->selected_modules()) { - if (mod->attributes.count(ID(abc_box_id))) + if (module->attributes.count(ID(abc_box_id))) continue; - if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); + if (module->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(module)); continue; } - assign_map.set(mod); + SigMap assign_map(module); CellTypes ct(design); - std::vector all_cells = mod->selected_cells(); + std::vector all_cells = module->selected_cells(); std::set unassigned_cells(all_cells.begin(), all_cells.end()); std::set expand_queue, next_expand_queue; @@ -1154,7 +1150,7 @@ struct Abc9Pass : public Pass { SigSpec abc9_clock = derived_sigmap(abc9_clock_wire); abc9_clock.replace(pattern, with); for (const auto &c : abc9_clock.chunks()) - log_assert(!c.wire || c.wire->module == mod); + log_assert(!c.wire || c.wire->module == module); Wire *abc9_control_wire = derived_module->wire("\\$abc9_control"); if (abc9_control_wire == NULL) @@ -1162,7 +1158,7 @@ struct Abc9Pass : public Pass { SigSpec abc9_control = derived_sigmap(abc9_control_wire); abc9_control.replace(pattern, with); for (const auto &c : abc9_control.chunks()) - log_assert(!c.wire || c.wire->module == mod); + log_assert(!c.wire || c.wire->module == module); unassigned_cells.erase(cell); expand_queue.insert(cell); @@ -1252,19 +1248,18 @@ struct Abc9Pass : public Pass { log(" %d cells in clk=%s\n", GetSize(it.second), log_signal(it.first)); design->selection_stack.emplace_back(false); + design->selected_active_module = module->name.str(); for (auto &it : assigned_cells) { RTLIL::Selection& sel = design->selection_stack.back(); - sel.selected_members[mod->name] = std::move(it.second); - abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, false, "$", + sel.selected_members[module->name] = std::move(it.second); + abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, false, "$", keepff, delay_target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, wire_delay, box_lookup); - assign_map.set(mod); } design->selection_stack.pop_back(); + design->selected_active_module.clear(); } - assign_map.clear(); - log_pop(); } } Abc9Pass; -- 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(-) 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 e0aa772663a95fb5417d9fbe64f27ac8c7395bf0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 15:19:02 -0700 Subject: Add comment --- passes/techmap/abc9.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 33f608d29..6e424d517 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1117,6 +1117,7 @@ struct Abc9Pass : public Pass { auto derived_name = inst_module->derive(design, cell->parameters); auto derived_module = design->module(derived_name); log_assert(derived_module); + // FIXME: call once Pass::call_on_module(design, derived_module, "proc"); SigMap derived_sigmap(derived_module); -- 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(-) 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 5e9ae90cbba4e9c2abfe5d6a1b90c2256aae1615 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 15:39:24 -0700 Subject: Add explanation to abc_map.v --- techlibs/xilinx/abc_map.v | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index cb252b828..6a0e18abe 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -18,8 +18,24 @@ * */ +// The following techmapping rules are intended to be run (with -max_iter 1) +// before invoking the `abc9` pass in order to transform the design into +// a format that it understands. +// +// For example, (complex) flip-flops are expected to be described as an +// combinatorial box (containing all control logic such as clock enable +// or synchronous resets) followed by a basic D-Q flop. + // ============================================================================ +// The purpose of the following FD* rules are to wrap the flop (which, when +// called with the `_ABC' macro set captures contains only its combinatorial +// behaviour) with: +// (a) a special $__ABC_FF_ in front of the FD*'s output, indicating to abc9 +// the location of its basic D-Q flop +// (b) a special \$currQ connection that feeds back into the (combinatorial) +// FD* cell to facilitate clock-enable behaviour -- note that \$currQ +// isn't a real input port, it is one that is understood only by abc9 module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; -- 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 +- passes/techmap/techmap.cc | 8 +++ techlibs/xilinx/abc_map.v | 69 ++++++++++--------- techlibs/xilinx/cells_sim.v | 160 ++++++++++++++++++++++---------------------- 4 files changed, 129 insertions(+), 114 deletions(-) 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; diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 08a1af2d5..c2dc9b959 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -256,6 +256,14 @@ struct TechmapWorker if (w->attributes.count(ID(src))) w->add_strpool_attribute(ID(src), extra_src_attrs); } + + + if (it.second->name.begins_with("\\_TECHMAP_REPLACE_")) { + IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), it.second->name.c_str() + strlen("\\_TECHMAP_REPLACE_")); + Wire *replace_w = module->addWire(replace_name, it.second); + module->connect(replace_w, w); + } + design->select(module, w); } diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 6a0e18abe..4eec77df9 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -33,34 +33,35 @@ // behaviour) with: // (a) a special $__ABC_FF_ in front of the FD*'s output, indicating to abc9 // the location of its basic D-Q flop -// (b) a special \$currQ connection that feeds back into the (combinatorial) -// FD* cell to facilitate clock-enable behaviour -- note that \$currQ -// isn't a real input port, it is one that is understood only by abc9 +// (b) a special TECHMAP_REPLACE_.$currQwire that will be used for feedback +// into the (combinatorial) FD* cell to facilitate clock-enable behaviour module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; - wire \$nextQ ; + wire $nextQ; FDRE #( .INIT(INIT), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), .IS_R_INVERTED(IS_R_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .R(R) + .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) ); - \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(Q)); + wire _TECHMAP_REPLACE_.$currQ = Q; + \$__ABC_FF_ abc_dff (.D($nextQ), .Q(Q)); endmodule module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; - wire \$nextQ ; + wire $nextQ; FDRE_1 #( .INIT(|0), ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .R(R) + .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) ); - \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(Q)); + wire _TECHMAP_REPLACE_.$currQ = Q; + \$__ABC_FF_ abc_dff (.D($nextQ), .Q(Q)); endmodule module FDCE (output reg Q, input C, CE, D, CLR); @@ -68,28 +69,30 @@ module FDCE (output reg Q, input C, CE, D, CLR); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; - wire \$nextQ , \$currQ ; + wire $currQ, $nextQ; FDCE #( .INIT(INIT), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), .IS_CLR_INVERTED(IS_CLR_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .CLR(CLR) + .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) ); - \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); - \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); + wire _TECHMAP_REPLACE_.$currQ = Q; + \$__ABC_FF_ abc_dff (.D($nextQ), .Q($currQ)); + \$__ABC_ASYNC abc_async (.A($currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); endmodule module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; - wire \$nextQ , \$currQ ; + wire $nextQ, $currQ; FDCE_1 #( .INIT(INIT) ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .CLR(CLR) + .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) ); - \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); - \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(CLR), .Y(Q)); + wire _TECHMAP_REPLACE_.$currQ = Q; + \$__ABC_FF_ abc_dff (.D($nextQ), .Q($currQ)); + \$__ABC_ASYNC abc_async (.A($currQ), .S(CLR), .Y(Q)); endmodule module FDPE (output reg Q, input C, CE, D, PRE); @@ -97,28 +100,30 @@ module FDPE (output reg Q, input C, CE, D, PRE); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; - wire \$nextQ , \$currQ ; + wire $nextQ, $currQ; FDPE #( .INIT(INIT), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), .IS_PRE_INVERTED(IS_PRE_INVERTED), ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .PRE(PRE) + .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) ); - \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); - \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); + wire _TECHMAP_REPLACE_.$currQ = Q; + \$__ABC_FF_ abc_dff (.D($nextQ), .Q($currQ)); + \$__ABC_ASYNC abc_async (.A($currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); endmodule module FDPE_1 (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; - wire \$nextQ , \$currQ ; + wire $nextQ, $currQ; FDPE_1 #( .INIT(INIT) ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .PRE(PRE) + .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) ); - \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(\$currQ )); - \$__ABC_ASYNC abc_async (.A(\$currQ ), .S(PRE), .Y(Q)); + wire _TECHMAP_REPLACE_.$currQ = Q; + \$__ABC_FF_ abc_dff (.D($nextQ), .Q($currQ)); + \$__ABC_ASYNC abc_async (.A($currQ), .S(PRE), .Y(Q)); endmodule module FDSE (output reg Q, input C, CE, D, S); @@ -126,26 +131,28 @@ module FDSE (output reg Q, input C, CE, D, S); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; - wire \$nextQ ; + wire $nextQ; FDSE #( .INIT(INIT), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), .IS_S_INVERTED(IS_S_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .S(S) + .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) ); - \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(Q)); + wire _TECHMAP_REPLACE_.$currQ = Q; + \$__ABC_FF_ abc_dff (.D($nextQ), .Q(Q)); endmodule module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; - wire \$nextQ ; + wire $nextQ; FDSE_1 #( .INIT(|0), ) _TECHMAP_REPLACE_ ( - .D(D), .Q(\$nextQ ), .\$currQ (Q), .C(C), .CE(CE), .S(S) + .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) ); - \$__ABC_FF_ abc_dff (.D(\$nextQ ), .Q(Q)); + wire _TECHMAP_REPLACE_.$currQ = Q; + \$__ABC_FF_ abc_dff (.D($nextQ), .Q(Q)); endmodule module RAM32X1D ( diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 3aa686e81..7ab28b0aa 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -258,31 +258,31 @@ module FDRE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (R == !IS_R_INVERTED) \$nextQ = 1'b0; else if (CE) \$nextQ = D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; + wire $currQ; + reg $nextQ; + always @* if (R == !IS_R_INVERTED) $nextQ = 1'b0; else if (CE) $nextQ = D ^ IS_D_INVERTED; else $nextQ = $currQ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) // In order to achieve clock-enable behaviour, the current value // of the sequential output is required which Yosys will - // connect to the special `\$currQ' wire. + // connect to the special `$currQ' wire. // Special signal indicating clock domain // (used to partition the module so that `abc9' only performs // sequential synthesis (reachability analysis) correctly on // one domain at a time) - wire [1:0] \$abc9_clock = {C, IS_C_INVERTED}; + wire [1:0] $abc9_clock = {C, IS_C_INVERTED}; // Special signal indicating control domain // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) - wire [3:0] \$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; - always @* Q = \$nextQ ; + wire [3:0] $abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; + always @* Q = $nextQ; `else - assign \$currQ = Q; + assign $currQ = Q; generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) Q <= \$nextQ ; - 1'b1: always @(negedge C) Q <= \$nextQ ; + 1'b0: always @(posedge C) Q <= $nextQ; + 1'b1: always @(negedge C) Q <= $nextQ; endcase endgenerate `endif endmodule @@ -297,29 +297,29 @@ module FDRE_1 ( ); parameter [0:0] INIT = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (R) Q <= 1'b0; else if (CE) Q <= D; else \$nextQ = \$currQ ; + wire $currQ; + reg $nextQ; + always @* if (R) Q <= 1'b0; else if (CE) Q <= D; else $nextQ = $currQ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) // In order to achieve clock-enable behaviour, the current value // of the sequential output is required which Yosys will - // connect to the special `\$currQ' wire. + // connect to the special `$currQ' wire. // Special signal indicating clock domain // (used to partition the module so that `abc9' only performs // sequential synthesis (reachability analysis) correctly on // one domain at a time) - wire [1:0] \$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [1:0] $abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; // Special signal indicating control domain // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) - wire [3:0] \$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; - always @* Q = \$nextQ ; + wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; + always @* Q = $nextQ; `else - assign \$currQ = Q; - always @(negedge C) Q <= \$nextQ ; + assign $currQ = Q; + always @(negedge C) Q <= $nextQ; `endif endmodule @@ -341,15 +341,15 @@ module FDCE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (CE) Q <= D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; + wire $currQ; + reg $nextQ; + always @* if (CE) Q <= D ^ IS_D_INVERTED; else $nextQ = $currQ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) // In order to achieve clock-enable behaviour, the current value // of the sequential output is required which Yosys will - // connect to the special `\$currQ' wire. + // connect to the special `$currQ' wire. // Since this is an async flop, async behaviour is also dealt with // using the $_ABC_ASYNC box by abc_map.v @@ -357,19 +357,19 @@ module FDCE ( // (used to partition the module so that `abc9' only performs // sequential synthesis (reachability analysis) correctly on // one domain at a time) - wire [1:0] \$abc9_clock = {C, IS_C_INVERTED}; + wire [1:0] $abc9_clock = {C, IS_C_INVERTED}; // Special signal indicating control domain // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) - wire [3:0] \$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; - always @* Q = \$nextQ ; + wire [3:0] $abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; + always @* Q = $nextQ; `else - assign \$currQ = Q; + assign $currQ = Q; generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) - 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= \$nextQ ; - 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= \$nextQ ; - 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= \$nextQ ; - 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= \$nextQ ; + 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= $nextQ; + 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= $nextQ; + 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= $nextQ; + 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= $nextQ; endcase endgenerate `endif endmodule @@ -384,15 +384,15 @@ module FDCE_1 ( ); parameter [0:0] INIT = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (CE) Q <= D; else \$nextQ = \$currQ ; + wire $currQ; + reg $nextQ; + always @* if (CE) Q <= D; else $nextQ = $currQ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) // In order to achieve clock-enable behaviour, the current value // of the sequential output is required which Yosys will - // connect to the special `\$currQ' wire. + // connect to the special `$currQ' wire. // Since this is an async flop, async behaviour is also dealt with // using the $_ABC_ASYNC box by abc_map.v @@ -400,15 +400,15 @@ module FDCE_1 ( // (used to partition the module so that `abc9' only performs // sequential synthesis (reachability analysis) correctly on // one domain at a time) - wire [1:0] \$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [1:0] $abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; // Special signal indicating control domain // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) - wire [3:0] \$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; - always @* Q = \$nextQ ; + wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; + always @* Q = $nextQ; `else - assign \$currQ = Q; - always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else Q <= \$nextQ ; + assign $currQ = Q; + always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else Q <= $nextQ; `endif endmodule @@ -430,15 +430,15 @@ module FDPE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (CE) Q <= D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; + wire $currQ; + reg $nextQ; + always @* if (CE) Q <= D ^ IS_D_INVERTED; else $nextQ = $currQ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) // In order to achieve clock-enable behaviour, the current value // of the sequential output is required which Yosys will - // connect to the special `\$currQ' wire. + // connect to the special `$currQ' wire. // Since this is an async flop, async behaviour is also dealt with // using the $_ABC_ASYNC box by abc_map.v @@ -446,19 +446,19 @@ module FDPE ( // (used to partition the module so that `abc9' only performs // sequential synthesis (reachability analysis) correctly on // one domain at a time) - wire [1:0] \$abc9_clock = {C, IS_C_INVERTED}; + wire [1:0] $abc9_clock = {C, IS_C_INVERTED}; // Special signal indicating control domain // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) - wire [3:0] \$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; - always @* Q = \$nextQ ; + wire [3:0] $abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; + always @* Q = $nextQ; `else - assign \$currQ = Q; + assign $currQ = Q; generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) - 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= \$nextQ ; - 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= \$nextQ ; - 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= \$nextQ ; - 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= \$nextQ ; + 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= $nextQ; + 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= $nextQ; + 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= $nextQ; + 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= $nextQ; endcase endgenerate `endif endmodule @@ -473,15 +473,15 @@ module FDPE_1 ( ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (CE) Q <= D; else \$nextQ = \$currQ ; + wire $currQ; + reg $nextQ; + always @* if (CE) Q <= D; else $nextQ = $currQ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) // In order to achieve clock-enable behaviour, the current value // of the sequential output is required which Yosys will - // connect to the special `\$currQ' wire. + // connect to the special `$currQ' wire. // Since this is an async flop, async behaviour is also dealt with // using the $_ABC_ASYNC box by abc_map.v @@ -489,15 +489,15 @@ module FDPE_1 ( // (used to partition the module so that `abc9' only performs // sequential synthesis (reachability analysis) correctly on // one domain at a time) - wire [1:0] \$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [1:0] $abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; // Special signal indicating control domain // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) - wire [3:0] \$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; - always @* Q = \$nextQ ; + wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; + always @* Q = $nextQ; `else - assign \$currQ = Q; - always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else Q <= \$nextQ ; + assign $currQ = Q; + always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else Q <= $nextQ; `endif endmodule @@ -519,31 +519,31 @@ module FDSE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (S == !IS_S_INVERTED) \$nextQ = 1'b1; else if (CE) \$nextQ = D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; + wire $currQ; + reg $nextQ; + always @* if (S == !IS_S_INVERTED) $nextQ = 1'b1; else if (CE) $nextQ = D ^ IS_D_INVERTED; else $nextQ = $currQ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) // In order to achieve clock-enable behaviour, the current value // of the sequential output is required which Yosys will - // connect to the special `\$currQ' wire. + // connect to the special `$currQ' wire. // Special signal indicating clock domain // (used to partition the module so that `abc9' only performs // sequential synthesis (reachability analysis) correctly on // one domain at a time) - wire [1:0] \$abc9_clock = {C, IS_C_INVERTED}; + wire [1:0] $abc9_clock = {C, IS_C_INVERTED}; // Special signal indicating control domain // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) - wire [3:0] \$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; - always @* Q = \$nextQ ; + wire [3:0] $abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; + always @* Q = $nextQ; `else - assign \$currQ = Q; + assign $currQ = Q; generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) Q <= \$nextQ ; - 1'b1: always @(negedge C) Q <= \$nextQ ; + 1'b0: always @(posedge C) Q <= $nextQ; + 1'b1: always @(negedge C) Q <= $nextQ; endcase endgenerate `endif endmodule @@ -558,29 +558,29 @@ module FDSE_1 ( ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (S) \$nextQ = 1'b1; else if (CE) \$nextQ = D; else \$nextQ = \$currQ ; + wire $currQ; + reg $nextQ; + always @* if (S) $nextQ = 1'b1; else if (CE) $nextQ = D; else $nextQ = $currQ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) // In order to achieve clock-enable behaviour, the current value // of the sequential output is required which Yosys will - // connect to the special `\$currQ' wire. + // connect to the special `$currQ' wire. // Special signal indicating clock domain // (used to partition the module so that `abc9' only performs // sequential synthesis (reachability analysis) correctly on // one domain at a time) - wire [1:0] \$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [1:0] $abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; // Special signal indicating control domain // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) - wire [3:0] \$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; - always @* Q = \$nextQ ; + wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; + always @* Q = $nextQ; `else - assign \$currQ = Q; - always @(negedge C) Q <= \$nextQ ; + assign $currQ = Q; + always @(negedge C) Q <= $nextQ; `endif endmodule -- cgit v1.2.3 From f9bb3352944275acc6e82eaf53aebf3c964f68c4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 16:36:42 -0700 Subject: Cleanup $currQ from aigerparse --- frontends/aiger/aigerparse.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index d40f33447..594bf60ce 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -817,8 +817,6 @@ void AigerReader::post_process() } if (is_flop) { - Wire* port = box_module->wire("\\$currQ"); - log_assert(port); log_assert(co_count < outputs.size()); Wire *wire = outputs[co_count++]; log_assert(wire); -- cgit v1.2.3 From 390b960c8c646018c1f6cddfec5fc2d528d42fa4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 16:37:29 -0700 Subject: Resolve FIXME on calling proc just once --- passes/techmap/abc9.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 6e424d517..ce057566c 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1117,8 +1117,8 @@ struct Abc9Pass : public Pass { auto derived_name = inst_module->derive(design, cell->parameters); auto derived_module = design->module(derived_name); log_assert(derived_module); - // FIXME: call once - Pass::call_on_module(design, derived_module, "proc"); + if (derived_module->has_processes()) + Pass::call_on_module(design, derived_module, "proc"); SigMap derived_sigmap(derived_module); Wire *currQ = derived_module->wire("\\$currQ"); -- 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 ++++++++++++++++++++++++ passes/techmap/abc9.cc | 13 ------------- 2 files changed, 24 insertions(+), 13 deletions(-) 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()); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index ce057566c..777ec6ac8 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1121,19 +1121,6 @@ struct Abc9Pass : public Pass { Pass::call_on_module(design, derived_module, "proc"); SigMap derived_sigmap(derived_module); - Wire *currQ = derived_module->wire("\\$currQ"); - if (currQ == NULL) - log_error("'\\$currQ' is not a wire present in module '%s'.\n", log_id(cell->type)); - log_assert(!currQ->port_output); - if (!currQ->port_input) { - currQ->port_input = true; - derived_module->ports.push_back(currQ->name); - currQ->port_id = GetSize(derived_module->ports); -#ifndef NDEBUG - derived_module->check(); -#endif - } - SigSpec pattern; SigSpec with; for (auto &conn : cell->connections()) { -- cgit v1.2.3 From 03ebe43e3edce03d3dc24f80c05e16cdb7b76748 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 1 Oct 2019 13:05:56 -0700 Subject: Escape Verilog identifiers for legality outside of Yosys --- techlibs/xilinx/cells_sim.v | 96 ++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 7ab28b0aa..84139cd9c 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -258,9 +258,9 @@ module FDRE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; initial Q <= INIT; - wire $currQ; - reg $nextQ; - always @* if (R == !IS_R_INVERTED) $nextQ = 1'b0; else if (CE) $nextQ = D ^ IS_D_INVERTED; else $nextQ = $currQ; + wire \$currQ ; + reg \$nextQ ; + always @* if (R == !IS_R_INVERTED) $nextQ = 1'b0; else if (CE) $nextQ = D ^ IS_D_INVERTED; else $nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -277,12 +277,12 @@ module FDRE ( // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) wire [3:0] $abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; - always @* Q = $nextQ; + always @* Q = \$nextQ ; `else assign $currQ = Q; generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) Q <= $nextQ; - 1'b1: always @(negedge C) Q <= $nextQ; + 1'b0: always @(posedge C) Q <= \$nextQ ; + 1'b1: always @(negedge C) Q <= \$nextQ ; endcase endgenerate `endif endmodule @@ -297,9 +297,9 @@ module FDRE_1 ( ); parameter [0:0] INIT = 1'b0; initial Q <= INIT; - wire $currQ; - reg $nextQ; - always @* if (R) Q <= 1'b0; else if (CE) Q <= D; else $nextQ = $currQ; + wire \$currQ ; + reg \$nextQ ; + always @* if (R) Q <= 1'b0; else if (CE) Q <= D; else $nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -316,10 +316,10 @@ module FDRE_1 ( // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; - always @* Q = $nextQ; + always @* Q = \$nextQ ; `else assign $currQ = Q; - always @(negedge C) Q <= $nextQ; + always @(negedge C) Q <= \$nextQ ; `endif endmodule @@ -341,9 +341,9 @@ module FDCE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; initial Q <= INIT; - wire $currQ; - reg $nextQ; - always @* if (CE) Q <= D ^ IS_D_INVERTED; else $nextQ = $currQ; + wire \$currQ ; + reg \$nextQ ; + always @* if (CE) Q <= D ^ IS_D_INVERTED; else $nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -362,14 +362,14 @@ module FDCE ( // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) wire [3:0] $abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; - always @* Q = $nextQ; + always @* Q = \$nextQ ; `else assign $currQ = Q; generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) - 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= $nextQ; - 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= $nextQ; - 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= $nextQ; - 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= $nextQ; + 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= \$nextQ ; + 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= \$nextQ ; + 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= \$nextQ ; + 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= \$nextQ ; endcase endgenerate `endif endmodule @@ -384,9 +384,9 @@ module FDCE_1 ( ); parameter [0:0] INIT = 1'b0; initial Q <= INIT; - wire $currQ; - reg $nextQ; - always @* if (CE) Q <= D; else $nextQ = $currQ; + wire \$currQ ; + reg \$nextQ ; + always @* if (CE) Q <= D; else $nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -405,10 +405,10 @@ module FDCE_1 ( // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; - always @* Q = $nextQ; + always @* Q = \$nextQ ; `else assign $currQ = Q; - always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else Q <= $nextQ; + always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else Q <= \$nextQ ; `endif endmodule @@ -430,9 +430,9 @@ module FDPE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; initial Q <= INIT; - wire $currQ; - reg $nextQ; - always @* if (CE) Q <= D ^ IS_D_INVERTED; else $nextQ = $currQ; + wire \$currQ ; + reg \$nextQ ; + always @* if (CE) Q <= D ^ IS_D_INVERTED; else $nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -451,14 +451,14 @@ module FDPE ( // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) wire [3:0] $abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; - always @* Q = $nextQ; + always @* Q = \$nextQ ; `else assign $currQ = Q; generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) - 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= $nextQ; - 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= $nextQ; - 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= $nextQ; - 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= $nextQ; + 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= \$nextQ ; + 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= \$nextQ ; + 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= \$nextQ ; + 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= \$nextQ ; endcase endgenerate `endif endmodule @@ -473,9 +473,9 @@ module FDPE_1 ( ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; - wire $currQ; - reg $nextQ; - always @* if (CE) Q <= D; else $nextQ = $currQ; + wire \$currQ ; + reg \$nextQ ; + always @* if (CE) Q <= D; else $nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -494,10 +494,10 @@ module FDPE_1 ( // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; - always @* Q = $nextQ; + always @* Q = \$nextQ ; `else assign $currQ = Q; - always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else Q <= $nextQ; + always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else Q <= \$nextQ ; `endif endmodule @@ -519,9 +519,9 @@ module FDSE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; initial Q <= INIT; - wire $currQ; - reg $nextQ; - always @* if (S == !IS_S_INVERTED) $nextQ = 1'b1; else if (CE) $nextQ = D ^ IS_D_INVERTED; else $nextQ = $currQ; + wire \$currQ ; + reg \$nextQ ; + always @* if (S == !IS_S_INVERTED) $nextQ = 1'b1; else if (CE) $nextQ = D ^ IS_D_INVERTED; else $nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -538,12 +538,12 @@ module FDSE ( // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) wire [3:0] $abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; - always @* Q = $nextQ; + always @* Q = \$nextQ ; `else assign $currQ = Q; generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) Q <= $nextQ; - 1'b1: always @(negedge C) Q <= $nextQ; + 1'b0: always @(posedge C) Q <= \$nextQ ; + 1'b1: always @(negedge C) Q <= \$nextQ ; endcase endgenerate `endif endmodule @@ -558,9 +558,9 @@ module FDSE_1 ( ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; - wire $currQ; - reg $nextQ; - always @* if (S) $nextQ = 1'b1; else if (CE) $nextQ = D; else $nextQ = $currQ; + wire \$currQ ; + reg \$nextQ ; + always @* if (S) $nextQ = 1'b1; else if (CE) $nextQ = D; else $nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -577,10 +577,10 @@ module FDSE_1 ( // (which, combined with this spell type, encodes to `abc9' // which flops may be merged together) wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; - always @* Q = $nextQ; + always @* Q = \$nextQ ; `else assign $currQ = Q; - always @(negedge C) Q <= $nextQ; + always @(negedge C) Q <= \$nextQ ; `endif endmodule -- cgit v1.2.3 From 5299884f049e73c395fdff090b345b15d54aab1e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 1 Oct 2019 13:41:08 -0700 Subject: More fixes --- techlibs/xilinx/cells_sim.v | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 84139cd9c..04aa60f91 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -260,7 +260,7 @@ module FDRE ( initial Q <= INIT; wire \$currQ ; reg \$nextQ ; - always @* if (R == !IS_R_INVERTED) $nextQ = 1'b0; else if (CE) $nextQ = D ^ IS_D_INVERTED; else $nextQ = \$currQ ; + always @* if (R == !IS_R_INVERTED) \$nextQ = 1'b0; else if (CE) \$nextQ = D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -279,7 +279,7 @@ module FDRE ( wire [3:0] $abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; always @* Q = \$nextQ ; `else - assign $currQ = Q; + assign \$currQ = Q; generate case (|IS_C_INVERTED) 1'b0: always @(posedge C) Q <= \$nextQ ; 1'b1: always @(negedge C) Q <= \$nextQ ; @@ -299,7 +299,7 @@ module FDRE_1 ( initial Q <= INIT; wire \$currQ ; reg \$nextQ ; - always @* if (R) Q <= 1'b0; else if (CE) Q <= D; else $nextQ = \$currQ ; + always @* if (R) Q <= 1'b0; else if (CE) Q <= D; else \$nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -318,7 +318,7 @@ module FDRE_1 ( wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; always @* Q = \$nextQ ; `else - assign $currQ = Q; + assign \$currQ = Q; always @(negedge C) Q <= \$nextQ ; `endif endmodule @@ -343,7 +343,7 @@ module FDCE ( initial Q <= INIT; wire \$currQ ; reg \$nextQ ; - always @* if (CE) Q <= D ^ IS_D_INVERTED; else $nextQ = \$currQ ; + always @* if (CE) Q <= D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -364,7 +364,7 @@ module FDCE ( wire [3:0] $abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; always @* Q = \$nextQ ; `else - assign $currQ = Q; + assign \$currQ = Q; generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= \$nextQ ; 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= \$nextQ ; @@ -386,7 +386,7 @@ module FDCE_1 ( initial Q <= INIT; wire \$currQ ; reg \$nextQ ; - always @* if (CE) Q <= D; else $nextQ = \$currQ ; + always @* if (CE) Q <= D; else \$nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -407,7 +407,7 @@ module FDCE_1 ( wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; always @* Q = \$nextQ ; `else - assign $currQ = Q; + assign \$currQ = Q; always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else Q <= \$nextQ ; `endif endmodule @@ -432,7 +432,7 @@ module FDPE ( initial Q <= INIT; wire \$currQ ; reg \$nextQ ; - always @* if (CE) Q <= D ^ IS_D_INVERTED; else $nextQ = \$currQ ; + always @* if (CE) Q <= D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -453,7 +453,7 @@ module FDPE ( wire [3:0] $abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; always @* Q = \$nextQ ; `else - assign $currQ = Q; + assign \$currQ = Q; generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= \$nextQ ; 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= \$nextQ ; @@ -475,7 +475,7 @@ module FDPE_1 ( initial Q <= INIT; wire \$currQ ; reg \$nextQ ; - always @* if (CE) Q <= D; else $nextQ = \$currQ ; + always @* if (CE) Q <= D; else \$nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -496,7 +496,7 @@ module FDPE_1 ( wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; always @* Q = \$nextQ ; `else - assign $currQ = Q; + assign \$currQ = Q; always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else Q <= \$nextQ ; `endif endmodule @@ -521,7 +521,7 @@ module FDSE ( initial Q <= INIT; wire \$currQ ; reg \$nextQ ; - always @* if (S == !IS_S_INVERTED) $nextQ = 1'b1; else if (CE) $nextQ = D ^ IS_D_INVERTED; else $nextQ = \$currQ ; + always @* if (S == !IS_S_INVERTED) \$nextQ = 1'b1; else if (CE) \$nextQ = D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -540,7 +540,7 @@ module FDSE ( wire [3:0] $abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; always @* Q = \$nextQ ; `else - assign $currQ = Q; + assign \$currQ = Q; generate case (|IS_C_INVERTED) 1'b0: always @(posedge C) Q <= \$nextQ ; 1'b1: always @(negedge C) Q <= \$nextQ ; @@ -560,7 +560,7 @@ module FDSE_1 ( initial Q <= INIT; wire \$currQ ; reg \$nextQ ; - always @* if (S) $nextQ = 1'b1; else if (CE) $nextQ = D; else $nextQ = \$currQ ; + always @* if (S) \$nextQ = 1'b1; else if (CE) \$nextQ = D; else \$nextQ = \$currQ ; `ifdef _ABC // `abc9' requires that complex flops be split into a combinatorial // box (this module) feeding a simple flop ($_ABC_FF_ in abc_map.v) @@ -579,7 +579,7 @@ module FDSE_1 ( wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; always @* Q = \$nextQ ; `else - assign $currQ = Q; + assign \$currQ = Q; always @(negedge C) Q <= \$nextQ ; `endif endmodule -- cgit v1.2.3 From 655f1b2ac559f73a7d781ae25afd1ab3b898afc0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 3 Oct 2019 10:11:25 -0700 Subject: English --- techlibs/xilinx/abc_map.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 4eec77df9..db996fbc3 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -29,11 +29,11 @@ // ============================================================================ // The purpose of the following FD* rules are to wrap the flop (which, when -// called with the `_ABC' macro set captures contains only its combinatorial +// called with the `_ABC' macro set captures only its combinatorial // behaviour) with: // (a) a special $__ABC_FF_ in front of the FD*'s output, indicating to abc9 -// the location of its basic D-Q flop -// (b) a special TECHMAP_REPLACE_.$currQwire that will be used for feedback +// the connectivity of its basic D-Q flop +// (b) a special TECHMAP_REPLACE_.$currQ wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; -- 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 +- frontends/aiger/aigerparse.cc | 2 +- passes/techmap/abc9.cc | 4 ++-- passes/techmap/techmap.cc | 8 -------- techlibs/xilinx/abc9_map.v | 18 +++++++++--------- techlibs/xilinx/abc9_unmap.v | 1 + 6 files changed, 14 insertions(+), 21 deletions(-) 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()); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 77a49c34f..4b66af3ad 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -833,7 +833,7 @@ void AigerReader::post_process() log_assert(q->port_input); q->port_input = false; - auto ff = module->addCell(NEW_ID, "$__ABC_FF_"); + auto ff = module->addCell(NEW_ID, "$__ABC9_FF_"); ff->setPort("\\D", d); ff->setPort("\\Q", q); flop_count++; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 87235f1a7..0dbe70a68 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -459,7 +459,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip dict abc9_box; vector boxes; for (auto cell : module->selected_cells()) { - if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC_FF_))) { + if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) { module->remove(cell); continue; } @@ -533,7 +533,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip cell_stats[mapped_cell->type]++; RTLIL::Cell *existing_cell = nullptr; - if (mapped_cell->type.in(ID($lut), ID($__ABC_FF_))) { + if (mapped_cell->type.in(ID($lut), ID($__ABC9_FF_))) { if (mapped_cell->type == ID($lut) && GetSize(mapped_cell->getPort(ID::A)) == 1 && mapped_cell->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) { diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index a07a2f280..0c57733d4 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -256,14 +256,6 @@ struct TechmapWorker if (w->attributes.count(ID(src))) w->add_strpool_attribute(ID(src), extra_src_attrs); } - - - if (it.second->name.begins_with("\\_TECHMAP_REPLACE_")) { - IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), it.second->name.c_str() + strlen("\\_TECHMAP_REPLACE_")); - Wire *replace_w = module->addWire(replace_name, it.second); - module->connect(replace_w, w); - } - design->select(module, w); if (it.second->name.begins_with("\\_TECHMAP_REPLACE_.")) { diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 0b81be15f..05063f86d 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -31,7 +31,7 @@ // The purpose of the following FD* rules are to wrap the flop (which, when // called with the `_ABC' macro set captures only its combinatorial // behaviour) with: -// (a) a special $__ABC_FF_ in front of the FD*'s output, indicating to abc9 +// (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 // the connectivity of its basic D-Q flop // (b) a special TECHMAP_REPLACE_.$currQ wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour @@ -50,7 +50,7 @@ module FDRE (output reg Q, input C, CE, D, R); .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) ); wire _TECHMAP_REPLACE_.$currQ = Q; - \$__ABC_FF_ abc_dff (.D($nextQ), .Q(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); endmodule module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; @@ -61,7 +61,7 @@ module FDRE_1 (output reg Q, input C, CE, D, R); .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) ); wire _TECHMAP_REPLACE_.$currQ = Q; - \$__ABC_FF_ abc_dff (.D($nextQ), .Q(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); endmodule module FDCE (output reg Q, input C, CE, D, CLR); @@ -79,7 +79,7 @@ module FDCE (output reg Q, input C, CE, D, CLR); .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) ); wire _TECHMAP_REPLACE_.$currQ = Q; - \$__ABC_FF_ abc_dff (.D($nextQ), .Q($currQ)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); \$__ABC_ASYNC abc_async (.A($currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); endmodule module FDCE_1 (output reg Q, input C, CE, D, CLR); @@ -91,7 +91,7 @@ module FDCE_1 (output reg Q, input C, CE, D, CLR); .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) ); wire _TECHMAP_REPLACE_.$currQ = Q; - \$__ABC_FF_ abc_dff (.D($nextQ), .Q($currQ)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); \$__ABC_ASYNC abc_async (.A($currQ), .S(CLR), .Y(Q)); endmodule @@ -110,7 +110,7 @@ module FDPE (output reg Q, input C, CE, D, PRE); .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) ); wire _TECHMAP_REPLACE_.$currQ = Q; - \$__ABC_FF_ abc_dff (.D($nextQ), .Q($currQ)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); \$__ABC_ASYNC abc_async (.A($currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); endmodule module FDPE_1 (output reg Q, input C, CE, D, PRE); @@ -122,7 +122,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) ); wire _TECHMAP_REPLACE_.$currQ = Q; - \$__ABC_FF_ abc_dff (.D($nextQ), .Q($currQ)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); \$__ABC_ASYNC abc_async (.A($currQ), .S(PRE), .Y(Q)); endmodule @@ -141,7 +141,7 @@ module FDSE (output reg Q, input C, CE, D, S); .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) ); wire _TECHMAP_REPLACE_.$currQ = Q; - \$__ABC_FF_ abc_dff (.D($nextQ), .Q(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); endmodule module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; @@ -152,7 +152,7 @@ module FDSE_1 (output reg Q, input C, CE, D, S); .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) ); wire _TECHMAP_REPLACE_.$currQ = Q; - \$__ABC_FF_ abc_dff (.D($nextQ), .Q(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); endmodule module RAM32X1D ( diff --git a/techlibs/xilinx/abc9_unmap.v b/techlibs/xilinx/abc9_unmap.v index f97b0bc66..21fe78d08 100644 --- a/techlibs/xilinx/abc9_unmap.v +++ b/techlibs/xilinx/abc9_unmap.v @@ -26,6 +26,7 @@ endmodule module \$__ABC9_FF_ (input D, output Q); assign Q = D; +endmodule module \$__ABC9_LUT6 (input A, input [5:0] S, output Y); assign Y = A; -- cgit v1.2.3 From d4212d128b5985cf09f5e7f14bc06e7323e644ac Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 4 Oct 2019 17:27:05 -0700 Subject: Use read_args for read_verilog --- techlibs/xilinx/synth_xilinx.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 16b607aac..caeeb3266 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -283,10 +283,13 @@ struct SynthXilinxPass : public ScriptPass ff_map_file = "+/xilinx/xc7_ff_map.v"; if (check_label("begin")) { + std::string read_args; if (vpr) - run("read_verilog -lib -D_ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); - else - run("read_verilog -lib -D_ABC +/xilinx/cells_sim.v"); + read_args += " -D_EXPLICIT_CARRY"; + if (abc9) + read_args += " -D_ABC9"; + read_args += " -lib +/xilinx/cells_sim.v"; + run("read_verilog" + read_args); if (help_mode) run("read_verilog -lib +/xilinx/{family}_cells_xtra.v"); -- cgit v1.2.3 From f0cadb0de801391083f6cc91d842e8137396b820 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 4 Oct 2019 17:52:19 -0700 Subject: Fix from merge --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 6c8527811..e9cdaf524 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1251,7 +1251,7 @@ struct Abc9Pass : public Pass { abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, false, "$", keepff, delay_target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, wire_delay, box_lookup, nomfs); - assign_map.set(mod); + assign_map.set(module); } design->selection_stack.pop_back(); design->selected_active_module.clear(); -- cgit v1.2.3 From a2ef93f03a1f75c25329c66d0e7d69da71e88e1f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 4 Oct 2019 17:56:38 -0700 Subject: abc -> abc9 --- techlibs/xilinx/synth_xilinx.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 6c598acf2..07f3d9a8a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -481,13 +481,13 @@ struct SynthXilinxPass : public ScriptPass "will use timing for 'xc7' instead.\n", family.c_str()); run("techmap -map +/xilinx/abc9_map.v -max_iter 1"); run("read_verilog -icells -lib +/xilinx/abc9_model.v"); - std::string abc9_opts = " -box +/xilinx/abc_xc7.box"; + std::string abc9_opts = " -box +/xilinx/abc9_xc7.box"; abc9_opts += stringf(" -W %d", XC7_WIRE_DELAY); abc9_opts += " -nomfs"; if (nowidelut) - abc9_opts += " -lut +/xilinx/abc_xc7_nowide.lut"; + abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut"; else - abc9_opts += " -lut +/xilinx/abc_xc7.lut"; + abc9_opts += " -lut +/xilinx/abc9_xc7.lut"; run("abc9" + abc9_opts); } else { -- 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(+) 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 +++++++++++++---------- passes/techmap/abc9.cc | 36 ++----- techlibs/xilinx/abc9_map.v | 199 ++++++++++++++++++++++++++++++++++---- techlibs/xilinx/abc9_model.v | 5 +- techlibs/xilinx/abc9_xc7.box | 2 +- techlibs/xilinx/cells_sim.v | 224 ++++--------------------------------------- 6 files changed, 276 insertions(+), 308 deletions(-) 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"; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index e9cdaf524..2ceaacf87 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1122,39 +1122,15 @@ struct Abc9Pass : public Pass { if (!inst_module || !inst_module->attributes.count("\\abc9_flop")) continue; - auto derived_name = inst_module->derive(design, cell->parameters); - auto derived_module = design->module(derived_name); - log_assert(derived_module); - if (derived_module->has_processes()) - Pass::call_on_module(design, derived_module, "proc"); - SigMap derived_sigmap(derived_module); - - SigSpec pattern; - SigSpec with; - for (auto &conn : cell->connections()) { - Wire *first = derived_module->wire(conn.first); - log_assert(first); - SigSpec second = assign_map(conn.second); - log_assert(GetSize(first) == GetSize(second)); - pattern.append(first); - with.append(second); - } - - Wire *abc9_clock_wire = derived_module->wire("\\$abc9_clock"); + Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); if (abc9_clock_wire == NULL) - log_error("'\\$abc9_clock' is not a wire present in module '%s'.\n", log_id(cell->type)); - SigSpec abc9_clock = derived_sigmap(abc9_clock_wire); - abc9_clock.replace(pattern, with); - for (const auto &c : abc9_clock.chunks()) - log_assert(!c.wire || c.wire->module == module); + log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + SigSpec abc9_clock = assign_map(abc9_clock_wire); - Wire *abc9_control_wire = derived_module->wire("\\$abc9_control"); + Wire *abc9_control_wire = module->wire(stringf("%s.$abc9_control", cell->name.c_str())); if (abc9_control_wire == NULL) - log_error("'\\$abc9_control' is not a wire present in module '%s'.\n", log_id(cell->type)); - SigSpec abc9_control = derived_sigmap(abc9_control_wire); - abc9_control.replace(pattern, with); - for (const auto &c : abc9_control.chunks()) - log_assert(!c.wire || c.wire->module == module); + log_error("'%s$abc9_control' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + SigSpec abc9_control = assign_map(abc9_control_wire); unassigned_cells.erase(cell); expand_queue.insert(cell); diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 05063f86d..ef7a1a09f 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -49,8 +49,57 @@ module FDRE (output reg Q, input C, CE, D, R); ) _TECHMAP_REPLACE_ ( .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) ); - wire _TECHMAP_REPLACE_.$currQ = Q; + // `abc9' requires that complex flops be split into a combinatorial box + // feeding a simple flop ($_ABC9_FF_). + // Yosys will automatically analyse the simulation model (described in + // cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in + // order to extract the combinatorial control logic left behind. + // Specifically, a simulation model similar to the one below: + // + // ++===================================++ + // || Sim model || + // || /\/\/\/\ || + // D -->>-----< > +------+ || + // R -->>-----< Comb. > |$_DFF_| || + // CE -->>-----< logic >-----| [NP]_|---+---->>-- Q + // || +--< > +------+ | || + // || | \/\/\/\/ | || + // || | | || + // || +----------------------------+ || + // || || + // ++===================================++ + // + // is transformed into: + // + // ++==================++ + // || Comb box || + // || || + // || /\/\/\/\ || + // D -->>-----< > || +------+ + // R -->>-----< Comb. > || |$_ABC_| + // CE -->>-----< logic >--->>-- $nextQ --| FF_ |--+-->> Q + // $currQ +-->>-----< > || +------+ | + // | || \/\/\/\/ || | + // | || || | + // | ++==================++ | + // | | + // +----------------------------------------------+ \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; + // Special signal indicating control domain + // (which, combined with this cell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; + // Special signal indicating the current value of the flip-flop + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `$currQ' wire. + wire _TECHMAP_REPLACE_.$currQ = Q; endmodule module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; @@ -60,8 +109,22 @@ module FDRE_1 (output reg Q, input C, CE, D, R); ) _TECHMAP_REPLACE_ ( .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) ); - wire _TECHMAP_REPLACE_.$currQ = Q; \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; + // Special signal indicating the current value of the flip-flop + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `$currQ' wire. + wire _TECHMAP_REPLACE_.$currQ = Q; endmodule module FDCE (output reg Q, input C, CE, D, CLR); @@ -69,18 +132,38 @@ module FDCE (output reg Q, input C, CE, D, CLR); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; - wire $currQ, $nextQ; + wire $nextQ, $currQ; FDCE #( .INIT(INIT), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), .IS_CLR_INVERTED(IS_CLR_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) + .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(IS_CLR_INVERTED) + // ^^^ Note that async + // control is disabled + // and captured by + // $__ABC9_ASYNC below ); - wire _TECHMAP_REPLACE_.$currQ = Q; \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); - \$__ABC_ASYNC abc_async (.A($currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); + // Since this is an async flop, async behaviour is also dealt with + // using the $_ABC9_ASYNC box by abc9_map.v + \$__ABC9_ASYNC abc_async (.A($currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; + // Special signal indicating the current value of the flip-flop + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `$currQ' wire. + wire _TECHMAP_REPLACE_.$currQ = $currQ; endmodule module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; @@ -88,11 +171,29 @@ module FDCE_1 (output reg Q, input C, CE, D, CLR); FDCE_1 #( .INIT(INIT) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) + .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(1'b0) + // ^^^ Note that async + // control is disabled + // and captured by + // $__ABC9_ASYNC below ); - wire _TECHMAP_REPLACE_.$currQ = Q; \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); - \$__ABC_ASYNC abc_async (.A($currQ), .S(CLR), .Y(Q)); + \$__ABC9_ASYNC abc_async (.A($currQ), .S(CLR), .Y(Q)); + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; + // Special signal indicating the current value of the flip-flop + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `$currQ' wire. + wire _TECHMAP_REPLACE_.$currQ = $currQ; endmodule module FDPE (output reg Q, input C, CE, D, PRE); @@ -107,11 +208,29 @@ module FDPE (output reg Q, input C, CE, D, PRE); .IS_D_INVERTED(IS_D_INVERTED), .IS_PRE_INVERTED(IS_PRE_INVERTED), ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) + .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(IS_PRE_INVERTED) + // ^^^ Note that async + // control is disabled + // and captured by + // $__ABC9_ASYNC below ); - wire _TECHMAP_REPLACE_.$currQ = Q; \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); - \$__ABC_ASYNC abc_async (.A($currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); + \$__ABC9_ASYNC abc_async (.A($currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; + // Special signal indicating the current value of the flip-flop + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `$currQ' wire. + wire _TECHMAP_REPLACE_.$currQ = $currQ; endmodule module FDPE_1 (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; @@ -119,11 +238,29 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); FDPE_1 #( .INIT(INIT) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) + .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(1'b0) + // ^^^ Note that async + // control is disabled + // and captured by + // $__ABC9_ASYNC below ); - wire _TECHMAP_REPLACE_.$currQ = Q; \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); - \$__ABC_ASYNC abc_async (.A($currQ), .S(PRE), .Y(Q)); + \$__ABC9_ASYNC abc_async (.A($currQ), .S(PRE), .Y(Q)); + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; + // Special signal indicating the current value of the flip-flop + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `$currQ' wire. + wire _TECHMAP_REPLACE_.$currQ = $currQ; endmodule module FDSE (output reg Q, input C, CE, D, S); @@ -140,8 +277,22 @@ module FDSE (output reg Q, input C, CE, D, S); ) _TECHMAP_REPLACE_ ( .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) ); - wire _TECHMAP_REPLACE_.$currQ = Q; \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; + // Special signal indicating the current value of the flip-flop + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `$currQ' wire. + wire _TECHMAP_REPLACE_.$currQ = Q; endmodule module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; @@ -151,8 +302,22 @@ module FDSE_1 (output reg Q, input C, CE, D, S); ) _TECHMAP_REPLACE_ ( .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) ); - wire _TECHMAP_REPLACE_.$currQ = Q; \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); + + // Special signal indicating clock domain + // (used to partition the module so that `abc9' only performs + // sequential synthesis (reachability analysis) correctly on + // one domain at a time) + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + // Special signal indicating control domain + // (which, combined with this spell type, encodes to `abc9' + // which flops may be merged together) + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; + // Special signal indicating the current value of the flip-flop + // In order to achieve clock-enable behaviour, the current value + // of the sequential output is required which Yosys will + // connect to the special `$currQ' wire. + wire _TECHMAP_REPLACE_.$currQ = Q; endmodule module RAM32X1D ( diff --git a/techlibs/xilinx/abc9_model.v b/techlibs/xilinx/abc9_model.v index 74b5cf66a..c17d6744a 100644 --- a/techlibs/xilinx/abc9_model.v +++ b/techlibs/xilinx/abc9_model.v @@ -30,11 +30,8 @@ module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); : (S0 ? I1 : I0); endmodule -module \$__ABC_FF_ (input D, output Q); -endmodule - (* abc_box_id = 1000 *) -module \$__ABC_ASYNC (input A, S, output Y); +module \$__ABC9_ASYNC (input A, S, output Y); endmodule // Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index 6814b101f..24b1898a4 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -44,7 +44,7 @@ CARRY4 4 1 10 8 # Box to emulate async behaviour of FD[CP]* # Inputs: A S # Outputs: Y -$__ABC_ASYNC 1000 0 2 1 +$__ABC9_ASYNC 1000 0 2 1 0 764 # The following FD*.{CE,R,CLR,PRE) are offset by 46ps to diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 309ee500a..35d9aac96 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -258,33 +258,10 @@ module FDRE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (R == !IS_R_INVERTED) \$nextQ = 1'b0; else if (CE) \$nextQ = D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; -`ifdef _ABC9 - // `abc9' requires that complex flops be split into a combinatorial - // box (this module) feeding a simple flop ($_ABC9_FF_ in abc9_map.v) - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. - - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) - wire [1:0] $abc9_clock = {C, IS_C_INVERTED}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) - wire [3:0] $abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; - always @* Q = \$nextQ ; -`else - assign \$currQ = Q; generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) Q <= \$nextQ ; - 1'b1: always @(negedge C) Q <= \$nextQ ; + 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate -`endif endmodule (* abc9_box_id=1002, lib_whitebox, abc9_flop *) @@ -297,30 +274,7 @@ module FDRE_1 ( ); parameter [0:0] INIT = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (R) Q <= 1'b0; else if (CE) Q <= D; else \$nextQ = \$currQ ; -`ifdef _ABC9 - // `abc9' requires that complex flops be split into a combinatorial - // box (this module) feeding a simple flop ($_ABC9_FF_ in abc9_map.v) - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. - - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) - wire [1:0] $abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) - wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; - always @* Q = \$nextQ ; -`else - assign \$currQ = Q; - always @(negedge C) Q <= \$nextQ ; -`endif + always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; endmodule (* abc9_box_id=1003, lib_whitebox, abc9_flop *) @@ -341,37 +295,12 @@ module FDCE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (CE) Q <= D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; -`ifdef _ABC9 - // `abc9' requires that complex flops be split into a combinatorial - // box (this module) feeding a simple flop ($_ABC9_FF_ in abc9_map.v) - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. - // Since this is an async flop, async behaviour is also dealt with - // using the $_ABC9_ASYNC box by abc9_map.v - - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) - wire [1:0] $abc9_clock = {C, IS_C_INVERTED}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) - wire [3:0] $abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; - always @* Q = \$nextQ ; -`else - assign \$currQ = Q; generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) - 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= \$nextQ ; - 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= \$nextQ ; - 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else Q <= \$nextQ ; - 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else Q <= \$nextQ ; + 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate -`endif endmodule (* abc9_box_id=1004, lib_whitebox, abc9_flop *) @@ -384,32 +313,7 @@ module FDCE_1 ( ); parameter [0:0] INIT = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (CE) Q <= D; else \$nextQ = \$currQ ; -`ifdef _ABC9 - // `abc9' requires that complex flops be split into a combinatorial - // box (this module) feeding a simple flop ($_ABC9_FF_ in abc9_map.v) - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. - // Since this is an async flop, async behaviour is also dealt with - // using the $_ABC9_ASYNC box by abc9_map.v - - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) - wire [1:0] $abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) - wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; - always @* Q = \$nextQ ; -`else - assign \$currQ = Q; - always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else Q <= \$nextQ ; -`endif + always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; endmodule (* abc9_box_id=1005, lib_whitebox, abc9_flop *) @@ -430,37 +334,12 @@ module FDPE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (CE) Q <= D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; -`ifdef _ABC9 - // `abc9' requires that complex flops be split into a combinatorial - // box (this module) feeding a simple flop ($_ABC9_FF_ in abc9_map.v) - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. - // Since this is an async flop, async behaviour is also dealt with - // using the $_ABC9_ASYNC box by abc9_map.v - - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) - wire [1:0] $abc9_clock = {C, IS_C_INVERTED}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) - wire [3:0] $abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; - always @* Q = \$nextQ ; -`else - assign \$currQ = Q; generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) - 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= \$nextQ ; - 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= \$nextQ ; - 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= \$nextQ ; - 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= \$nextQ ; + 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= Q ; + 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= Q ; + 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= Q ; + 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= Q ; endcase endgenerate -`endif endmodule (* abc9_box_id=1006, lib_whitebox, abc9_flop *) @@ -473,32 +352,7 @@ module FDPE_1 ( ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (CE) Q <= D; else \$nextQ = \$currQ ; -`ifdef _ABC9 - // `abc9' requires that complex flops be split into a combinatorial - // box (this module) feeding a simple flop ($_ABC9_FF_ in abc9_map.v) - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. - // Since this is an async flop, async behaviour is also dealt with - // using the $_ABC9_ASYNC box by abc9_map.v - - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) - wire [1:0] $abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) - wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; - always @* Q = \$nextQ ; -`else - assign \$currQ = Q; - always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else Q <= \$nextQ ; -`endif + always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule (* abc9_box_id=1007, lib_whitebox, abc9_flop *) @@ -519,33 +373,10 @@ module FDSE ( parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (S == !IS_S_INVERTED) \$nextQ = 1'b1; else if (CE) \$nextQ = D ^ IS_D_INVERTED; else \$nextQ = \$currQ ; -`ifdef _ABC9 - // `abc9' requires that complex flops be split into a combinatorial - // box (this module) feeding a simple flop ($_ABC9_FF_ in abc9_map.v) - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. - - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) - wire [1:0] $abc9_clock = {C, IS_C_INVERTED}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) - wire [3:0] $abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; - always @* Q = \$nextQ ; -`else - assign \$currQ = Q; generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) Q <= \$nextQ ; - 1'b1: always @(negedge C) Q <= \$nextQ ; + 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate -`endif endmodule (* abc9_box_id=1008, lib_whitebox, abc9_flop *) @@ -558,30 +389,7 @@ module FDSE_1 ( ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; - wire \$currQ ; - reg \$nextQ ; - always @* if (S) \$nextQ = 1'b1; else if (CE) \$nextQ = D; else \$nextQ = \$currQ ; -`ifdef _ABC9 - // `abc9' requires that complex flops be split into a combinatorial - // box (this module) feeding a simple flop ($_ABC9_FF_ in abc9_map.v) - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. - - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) - wire [1:0] $abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) - wire [3:0] $abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; - always @* Q = \$nextQ ; -`else - assign \$currQ = Q; - always @(negedge C) Q <= \$nextQ ; -`endif + always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; endmodule module LDCE ( -- 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(-) 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(+) 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(-) 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 1dc22607c38486d9e1a2b56f749d1eca35d405d2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 7 Oct 2019 12:21:52 -0700 Subject: Remove -D_ABC9 --- techlibs/xilinx/synth_xilinx.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 07f3d9a8a..a99aef7c7 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -286,8 +286,6 @@ struct SynthXilinxPass : public ScriptPass std::string read_args; if (vpr) read_args += " -D_EXPLICIT_CARRY"; - if (abc9) - read_args += " -D_ABC9"; read_args += " -lib +/xilinx/cells_sim.v"; run("read_verilog" + read_args); -- cgit v1.2.3 From bae3d8705d844912699b0ed502630040ce4efa85 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 7 Oct 2019 12:54:45 -0700 Subject: Update comments in abc9_map.v --- techlibs/xilinx/abc9_map.v | 188 ++++++++++++++------------------------------- 1 file changed, 57 insertions(+), 131 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index ef7a1a09f..feaf979ad 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -28,12 +28,53 @@ // ============================================================================ -// The purpose of the following FD* rules are to wrap the flop (which, when -// called with the `_ABC' macro set captures only its combinatorial -// behaviour) with: +// `abc9' requires that complex flops be split into a combinatorial box +// feeding a simple flop ($_ABC9_FF_). +// Yosys will automatically analyse the simulation model (described in +// cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in +// order to extract the combinatorial control logic left behind. +// Specifically, a simulation model similar to the one below: +// +// ++===================================++ +// || Sim model || +// || /\/\/\/\ || +// D -->>-----< > +------+ || +// R -->>-----< Comb. > |$_DFF_| || +// CE -->>-----< logic >-----| [NP]_|---+---->>-- Q +// || +--< > +------+ | || +// || | \/\/\/\/ | || +// || | | || +// || +----------------------------+ || +// || || +// ++===================================++ +// +// is transformed into: +// +// ++==================++ +// || Comb box || +// || || +// || /\/\/\/\ || +// D -->>-----< > || +------+ +// R -->>-----< Comb. > || |$_ABC_| +// CE -->>-----< logic >--->>-- $nextQ --| FF_ |--+-->> Q +// $currQ +-->>-----< > || +------+ | +// | || \/\/\/\/ || | +// | || || | +// | ++==================++ | +// | | +// +----------------------------------------------+ +// +// The purpose of the following FD* rules are to wrap the flop with: // (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 // the connectivity of its basic D-Q flop -// (b) a special TECHMAP_REPLACE_.$currQ wire that will be used for feedback +// (b) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock +// domain (used when partitioning the module so that `abc9' only +// performs sequential synthesis (with reachability analysis) correctly on +// one domain at a time) +// (c) a special _TECHMAP_REPLACE_.$abc9_control that captures the control +// domain (which, combined with this cell type, encodes to `abc9' which +// flops may be merged together) +// (d) a special _TECHMAP_REPLACE_.$currQ wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; @@ -49,56 +90,11 @@ module FDRE (output reg Q, input C, CE, D, R); ) _TECHMAP_REPLACE_ ( .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) ); - // `abc9' requires that complex flops be split into a combinatorial box - // feeding a simple flop ($_ABC9_FF_). - // Yosys will automatically analyse the simulation model (described in - // cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in - // order to extract the combinatorial control logic left behind. - // Specifically, a simulation model similar to the one below: - // - // ++===================================++ - // || Sim model || - // || /\/\/\/\ || - // D -->>-----< > +------+ || - // R -->>-----< Comb. > |$_DFF_| || - // CE -->>-----< logic >-----| [NP]_|---+---->>-- Q - // || +--< > +------+ | || - // || | \/\/\/\/ | || - // || | | || - // || +----------------------------+ || - // || || - // ++===================================++ - // - // is transformed into: - // - // ++==================++ - // || Comb box || - // || || - // || /\/\/\/\ || - // D -->>-----< > || +------+ - // R -->>-----< Comb. > || |$_ABC_| - // CE -->>-----< logic >--->>-- $nextQ --| FF_ |--+-->> Q - // $currQ +-->>-----< > || +------+ | - // | || \/\/\/\/ || | - // | || || | - // | ++==================++ | - // | | - // +----------------------------------------------+ \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) + // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - // Special signal indicating control domain - // (which, combined with this cell type, encodes to `abc9' - // which flops may be merged together) wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; - // Special signal indicating the current value of the flip-flop - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. wire _TECHMAP_REPLACE_.$currQ = Q; endmodule module FDRE_1 (output reg Q, input C, CE, D, R); @@ -111,19 +107,9 @@ module FDRE_1 (output reg Q, input C, CE, D, R); ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) + // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; - // Special signal indicating the current value of the flip-flop - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. wire _TECHMAP_REPLACE_.$currQ = Q; endmodule @@ -142,7 +128,7 @@ module FDCE (output reg Q, input C, CE, D, CLR); .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(IS_CLR_INVERTED) // ^^^ Note that async // control is disabled - // and captured by + // here but captured by // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); @@ -150,19 +136,9 @@ module FDCE (output reg Q, input C, CE, D, CLR); // using the $_ABC9_ASYNC box by abc9_map.v \$__ABC9_ASYNC abc_async (.A($currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) + // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; - // Special signal indicating the current value of the flip-flop - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. wire _TECHMAP_REPLACE_.$currQ = $currQ; endmodule module FDCE_1 (output reg Q, input C, CE, D, CLR); @@ -174,25 +150,15 @@ module FDCE_1 (output reg Q, input C, CE, D, CLR); .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(1'b0) // ^^^ Note that async // control is disabled - // and captured by + // here but captured by // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); \$__ABC9_ASYNC abc_async (.A($currQ), .S(CLR), .Y(Q)); - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) + // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; - // Special signal indicating the current value of the flip-flop - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. wire _TECHMAP_REPLACE_.$currQ = $currQ; endmodule @@ -211,25 +177,15 @@ module FDPE (output reg Q, input C, CE, D, PRE); .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(IS_PRE_INVERTED) // ^^^ Note that async // control is disabled - // and captured by + // here but captured by // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); \$__ABC9_ASYNC abc_async (.A($currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) + // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; - // Special signal indicating the current value of the flip-flop - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. wire _TECHMAP_REPLACE_.$currQ = $currQ; endmodule module FDPE_1 (output reg Q, input C, CE, D, PRE); @@ -241,25 +197,15 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(1'b0) // ^^^ Note that async // control is disabled - // and captured by + // here but captured by // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); \$__ABC9_ASYNC abc_async (.A($currQ), .S(PRE), .Y(Q)); - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) + // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; - // Special signal indicating the current value of the flip-flop - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. wire _TECHMAP_REPLACE_.$currQ = $currQ; endmodule @@ -279,19 +225,9 @@ module FDSE (output reg Q, input C, CE, D, S); ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) + // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; - // Special signal indicating the current value of the flip-flop - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. wire _TECHMAP_REPLACE_.$currQ = Q; endmodule module FDSE_1 (output reg Q, input C, CE, D, S); @@ -304,19 +240,9 @@ module FDSE_1 (output reg Q, input C, CE, D, S); ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); - // Special signal indicating clock domain - // (used to partition the module so that `abc9' only performs - // sequential synthesis (reachability analysis) correctly on - // one domain at a time) + // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - // Special signal indicating control domain - // (which, combined with this spell type, encodes to `abc9' - // which flops may be merged together) wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; - // Special signal indicating the current value of the flip-flop - // In order to achieve clock-enable behaviour, the current value - // of the sequential output is required which Yosys will - // connect to the special `$currQ' wire. wire _TECHMAP_REPLACE_.$currQ = Q; endmodule -- 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(-) 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 2cb2116b4c4d94c08be1fa087dca217eb6c0f7b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 7 Oct 2019 15:03:44 -0700 Subject: Use "abc9_period" attribute for delay target --- passes/techmap/abc9.cc | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2ceaacf87..34cdd3c3e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -852,8 +852,17 @@ struct Abc9Pass : public Pass { log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); log("ABC on logic snippets extracted from your design. You will not get any useful\n"); log("output when passing an ABC script that writes a file. Instead write your full\n"); - log("design as BLIF file with write_blif and then load that into ABC externally if\n"); - log("you want to use ABC to convert your design into another format.\n"); + log("design as an XAIGER file with write_xaiger and then load that into ABC externally\n"); + log("if you want to use ABC to convert your design into another format.\n"); + log("\n"); + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("Delay targets can also be specified on a per clock basis by attaching a\n"); + log("'(* abc9_period = *)' attribute onto clock wires (specifically, onto wires\n"); + log("that appear inside any special '$abc9_clock' wires inserted by abc9_map.v). This\n"); + log("can be achieved by modifying the source directly, or through a `setattr`\n"); + log("invocation. Since such attributes cannot yet be propagated through a\n"); + log("hierarchical design (whether or not it has been uniquified) it is recommended\n"); + log("that the design be flattened when using this feature.\n"); log("\n"); log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); log("\n"); @@ -1222,10 +1231,22 @@ struct Abc9Pass : public Pass { design->selection_stack.emplace_back(false); design->selected_active_module = module->name.str(); for (auto &it : assigned_cells) { + std::string target = delay_target; + if (target.empty()) { + for (auto b : assign_map(it.first)) + if (b.wire) { + auto jt = b.wire->attributes.find("\\abc9_period"); + if (jt != b.wire->attributes.end()) { + target = stringf("-D %d", jt->second.as_int()); + log("Target period = %s ps for clock domain %s\n", target.c_str(), log_signal(it.first)); + break; + } + } + } RTLIL::Selection& sel = design->selection_stack.back(); sel.selected_members[module->name] = std::move(it.second); abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, false, "$", - keepff, delay_target, lutin_shared, fast_mode, show_tempdir, + keepff, target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, wire_delay, box_lookup, nomfs); assign_map.set(module); } -- 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 ++++---- techlibs/xilinx/abc9_map.v | 92 +++++++++++++++++++++++----------------------- 2 files changed, 54 insertions(+), 54 deletions(-) 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; diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index feaf979ad..ee319a8e3 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -35,34 +35,34 @@ // order to extract the combinatorial control logic left behind. // Specifically, a simulation model similar to the one below: // -// ++===================================++ -// || Sim model || -// || /\/\/\/\ || -// D -->>-----< > +------+ || -// R -->>-----< Comb. > |$_DFF_| || -// CE -->>-----< logic >-----| [NP]_|---+---->>-- Q -// || +--< > +------+ | || -// || | \/\/\/\/ | || -// || | | || -// || +----------------------------+ || -// || || -// ++===================================++ +// ++===================================++ +// || Sim model || +// || /\/\/\/\ || +// D -->>-----< > +------+ || +// R -->>-----< Comb. > |$_DFF_| || +// CE -->>-----< logic >-----| [NP]_|---+---->>-- Q +// || +--< > +------+ | || +// || | \/\/\/\/ | || +// || | | || +// || +----------------------------+ || +// || || +// ++===================================++ // // is transformed into: // -// ++==================++ -// || Comb box || -// || || -// || /\/\/\/\ || -// D -->>-----< > || +------+ -// R -->>-----< Comb. > || |$_ABC_| -// CE -->>-----< logic >--->>-- $nextQ --| FF_ |--+-->> Q -// $currQ +-->>-----< > || +------+ | -// | || \/\/\/\/ || | -// | || || | -// | ++==================++ | -// | | -// +----------------------------------------------+ +// ++==================++ +// || Comb box || +// || || +// || /\/\/\/\ || +// D -->>-----< > || +------+ +// R -->>-----< Comb. > || |$_ABC_| +// CE -->>-----< logic >--->>-- $nextQ --| FF_ |--+-->> Q +// $abc9_currQ +-->>-----< > || +------+ | +// | || \/\/\/\/ || | +// | || || | +// | ++==================++ | +// | | +// +----------------------------------------------+ // // The purpose of the following FD* rules are to wrap the flop with: // (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 @@ -74,7 +74,7 @@ // (c) a special _TECHMAP_REPLACE_.$abc9_control that captures the control // domain (which, combined with this cell type, encodes to `abc9' which // flops may be merged together) -// (d) a special _TECHMAP_REPLACE_.$currQ wire that will be used for feedback +// (d) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; @@ -95,7 +95,7 @@ module FDRE (output reg Q, input C, CE, D, R); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; - wire _TECHMAP_REPLACE_.$currQ = Q; + wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; @@ -110,7 +110,7 @@ module FDRE_1 (output reg Q, input C, CE, D, R); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; - wire _TECHMAP_REPLACE_.$currQ = Q; + wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module FDCE (output reg Q, input C, CE, D, CLR); @@ -118,7 +118,7 @@ module FDCE (output reg Q, input C, CE, D, CLR); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; - wire $nextQ, $currQ; + wire $nextQ, $abc9_currQ; FDCE #( .INIT(INIT), .IS_C_INVERTED(IS_C_INVERTED), @@ -131,19 +131,19 @@ module FDCE (output reg Q, input C, CE, D, CLR); // here but captured by // $__ABC9_ASYNC below ); - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); // Since this is an async flop, async behaviour is also dealt with // using the $_ABC9_ASYNC box by abc9_map.v - \$__ABC9_ASYNC abc_async (.A($currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); + \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; - wire _TECHMAP_REPLACE_.$currQ = $currQ; + wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; - wire $nextQ, $currQ; + wire $nextQ, $abc9_currQ; FDCE_1 #( .INIT(INIT) ) _TECHMAP_REPLACE_ ( @@ -153,13 +153,13 @@ module FDCE_1 (output reg Q, input C, CE, D, CLR); // here but captured by // $__ABC9_ASYNC below ); - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); - \$__ABC9_ASYNC abc_async (.A($currQ), .S(CLR), .Y(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); + \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(Q)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; - wire _TECHMAP_REPLACE_.$currQ = $currQ; + wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDPE (output reg Q, input C, CE, D, PRE); @@ -167,7 +167,7 @@ module FDPE (output reg Q, input C, CE, D, PRE); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; - wire $nextQ, $currQ; + wire $nextQ, $abc9_currQ; FDPE #( .INIT(INIT), .IS_C_INVERTED(IS_C_INVERTED), @@ -180,17 +180,17 @@ module FDPE (output reg Q, input C, CE, D, PRE); // here but captured by // $__ABC9_ASYNC below ); - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); - \$__ABC9_ASYNC abc_async (.A($currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); + \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; - wire _TECHMAP_REPLACE_.$currQ = $currQ; + wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDPE_1 (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; - wire $nextQ, $currQ; + wire $nextQ, $abc9_currQ; FDPE_1 #( .INIT(INIT) ) _TECHMAP_REPLACE_ ( @@ -200,13 +200,13 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); // here but captured by // $__ABC9_ASYNC below ); - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($currQ)); - \$__ABC9_ASYNC abc_async (.A($currQ), .S(PRE), .Y(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); + \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(Q)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; - wire _TECHMAP_REPLACE_.$currQ = $currQ; + wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDSE (output reg Q, input C, CE, D, S); @@ -228,7 +228,7 @@ module FDSE (output reg Q, input C, CE, D, S); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; - wire _TECHMAP_REPLACE_.$currQ = Q; + wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; @@ -243,7 +243,7 @@ module FDSE_1 (output reg Q, input C, CE, D, S); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; - wire _TECHMAP_REPLACE_.$currQ = Q; + wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module RAM32X1D ( -- cgit v1.2.3 From 4f0818275fe44c451be59235616061be8ff5e382 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 7 Oct 2019 15:58:55 -0700 Subject: Cleanup --- techlibs/xilinx/abc9_map.v | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index ee319a8e3..95546db37 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -25,11 +25,6 @@ // For example, (complex) flip-flops are expected to be described as an // combinatorial box (containing all control logic such as clock enable // or synchronous resets) followed by a basic D-Q flop. - -// ============================================================================ - -// `abc9' requires that complex flops be split into a combinatorial box -// feeding a simple flop ($_ABC9_FF_). // Yosys will automatically analyse the simulation model (described in // cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in // order to extract the combinatorial control logic left behind. @@ -55,8 +50,8 @@ // || || // || /\/\/\/\ || // D -->>-----< > || +------+ -// R -->>-----< Comb. > || |$_ABC_| -// CE -->>-----< logic >--->>-- $nextQ --| FF_ |--+-->> Q +// R -->>-----< Comb. > || |$__ABC| +// CE -->>-----< logic >--->>-- $nextQ --| _FF_ |--+-->> Q // $abc9_currQ +-->>-----< > || +------+ | // | || \/\/\/\/ || | // | || || | -- cgit v1.2.3 From 344619079d42e541fee8dc370318d9927cd6fb95 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Nov 2019 16:57:07 -0800 Subject: Do not drop async control signals in abc_map.v --- techlibs/xilinx/abc9_map.v | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 95546db37..fc224e832 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -120,10 +120,11 @@ module FDCE (output reg Q, input C, CE, D, CLR); .IS_D_INVERTED(IS_D_INVERTED), .IS_CLR_INVERTED(IS_CLR_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(IS_CLR_INVERTED) + .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) // ^^^ Note that async - // control is disabled - // here but captured by + // control is not directly + // supported by abc9 but its + // behaviour is captured by // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); @@ -142,10 +143,11 @@ module FDCE_1 (output reg Q, input C, CE, D, CLR); FDCE_1 #( .INIT(INIT) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(1'b0) + .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) // ^^^ Note that async - // control is disabled - // here but captured by + // control is not directly + // supported by abc9 but its + // behaviour is captured by // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); @@ -169,10 +171,11 @@ module FDPE (output reg Q, input C, CE, D, PRE); .IS_D_INVERTED(IS_D_INVERTED), .IS_PRE_INVERTED(IS_PRE_INVERTED), ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(IS_PRE_INVERTED) + .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) // ^^^ Note that async - // control is disabled - // here but captured by + // control is not directly + // supported by abc9 but its + // behaviour is captured by // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); @@ -189,10 +192,11 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); FDPE_1 #( .INIT(INIT) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(1'b0) + .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) // ^^^ Note that async - // control is disabled - // here but captured by + // control is not directly + // supported by abc9 but its + // behaviour is captured by // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); -- 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(-) 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 90c5ca330c5e6c8eb45ad0b755b0049a34dc7534 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Nov 2019 16:57:58 -0800 Subject: Add two tests --- tests/simple_abc9/abc9.v | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 64b625efe..58596d701 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -267,3 +267,15 @@ module abc9_test026(output [3:0] o, p); assign o = { 1'b1, 1'bx }; assign p = { 1'b1, 1'bx, 1'b0 }; endmodule + +module abc9_test029(input clk, d, r, output reg q); +always @(posedge clk or posedge r) + if (r) q <= 1'b0; + else q <= d; +endmodule + +module abc9_test030(input clk, d, r, output reg q); +always @(negedge clk or posedge r) + if (r) q <= 1'b1; + else q <= d; +endmodule -- cgit v1.2.3 From 1cc106452fb25d082ca9491c24df97cc51d4b992 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Nov 2019 17:05:14 -0800 Subject: Add a equiv test too --- tests/various/abc9.v | 7 +++++++ tests/various/abc9.ys | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/tests/various/abc9.v b/tests/various/abc9.v index 30ebd4e26..e53dcdb21 100644 --- a/tests/various/abc9.v +++ b/tests/various/abc9.v @@ -9,3 +9,10 @@ wire w; unknown u(~i, w); unknown2 u2(w, o); endmodule + +module abc9_test031(input clk, d, r, output reg q); +initial q = 1'b0; +always @(negedge clk or negedge r) + if (r) q <= 1'b0; + else q <= d; +endmodule diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index 5c9a4075d..9e732bdc8 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -22,3 +22,19 @@ abc9 -lut 4 select -assert-count 1 t:$lut r:LUT=2'b01 r:WIDTH=1 %i %i select -assert-count 1 t:unknown select -assert-none t:$lut t:unknown %% t: %D + +design -load read +hierarchy -top abc9_test031 +proc +async2sync +design -save gold + +abc9 -lut 4 +check +design -stash gate + +design -import gold -as gold +design -import gate -as gate + +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -seq 10 -verify -prove-asserts -show-ports miter -- cgit v1.2.3 From df63d75ff35e1441360a4b28a12b32b3d00f1190 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Nov 2019 11:26:59 -0800 Subject: Fix INIT values --- techlibs/xilinx/abc9_map.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 95546db37..d2c0abeb6 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -96,7 +96,7 @@ module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; wire $nextQ; FDRE_1 #( - .INIT(|0), + .INIT(INIT), ) _TECHMAP_REPLACE_ ( .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) ); @@ -205,7 +205,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); endmodule module FDSE (output reg Q, input C, CE, D, S); - parameter [0:0] INIT = 1'b0; + parameter [0:0] INIT = 1'b1; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; @@ -226,10 +226,10 @@ module FDSE (output reg Q, input C, CE, D, S); wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module FDSE_1 (output reg Q, input C, CE, D, S); - parameter [0:0] INIT = 1'b0; + parameter [0:0] INIT = 1'b1; wire $nextQ; FDSE_1 #( - .INIT(|0), + .INIT(INIT), ) _TECHMAP_REPLACE_ ( .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) ); -- cgit v1.2.3 From cd9e830b67fdffcae88dba095548995a30988fa4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Nov 2019 13:28:55 -0800 Subject: Add multi clock test --- tests/simple_abc9/abc9.v | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 64b625efe..1844bac20 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -267,3 +267,8 @@ module abc9_test026(output [3:0] o, p); assign o = { 1'b1, 1'bx }; assign p = { 1'b1, 1'bx, 1'b0 }; endmodule + +module abc9_test029(input clk1, clk2, input d, output reg q1, q2); +always @(posedge clk1) q1 <= d; +always @(negedge clk2) q2 <= q1; +endmodule -- cgit v1.2.3 From af3055fe8354e0a082bd8415448fcbeb5ee435f6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Nov 2019 14:30:56 -0800 Subject: Add blackbox model for $__ABC9_FF_ so that clock partitioning works --- techlibs/xilinx/abc9_model.v | 3 +++ 1 file changed, 3 insertions(+) diff --git a/techlibs/xilinx/abc9_model.v b/techlibs/xilinx/abc9_model.v index c17d6744a..cc0e5ec41 100644 --- a/techlibs/xilinx/abc9_model.v +++ b/techlibs/xilinx/abc9_model.v @@ -30,6 +30,9 @@ module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); : (S0 ? I1 : I0); endmodule +module \$__ABC9_FF_ (input D, output Q); +endmodule + (* abc_box_id = 1000 *) module \$__ABC9_ASYNC (input A, S, output Y); endmodule -- cgit v1.2.3 From 729c6b93e8eb863aa9436239efea5f5678673b4f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Nov 2019 14:32:01 -0800 Subject: endomain -> ctrldomain --- passes/techmap/abc9.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 34cdd3c3e..8d4ff4025 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1108,8 +1108,8 @@ struct Abc9Pass : public Pass { std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; - typedef std::pair endomain_t; - std::map mergeability_class; + typedef std::pair ctrldomain_t; + std::map mergeability_class; for (auto cell : all_cells) { for (auto &conn : cell->connections()) @@ -1149,7 +1149,7 @@ struct Abc9Pass : public Pass { assigned_cells[abc9_clock].insert(cell->name); assigned_cells_reverse[cell] = abc9_clock; - endomain_t key(cell->type, abc9_control); + ctrldomain_t key(cell->type, abc9_control); auto r = mergeability_class.emplace(key, mergeability_class.size() + 1); auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); log_assert(r2.second); -- cgit v1.2.3 From a5767474830756319ce0fff53b81573701ec0cd2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Nov 2019 15:40:46 -0800 Subject: Consistent log message, ignore 's' extension --- frontends/aiger/aigerparse.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4b66af3ad..9374f1ab3 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -432,7 +432,7 @@ void AigerReader::parse_xaiger(const dict &box_lookup) else if (c == 'r') { uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); flopNum = parse_xaiger_literal(f); - log_debug("flopNum: %u\n", flopNum); + log_debug("flopNum = %u\n", flopNum); log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); f.ignore(flopNum * sizeof(uint32_t)); } @@ -464,9 +464,10 @@ void AigerReader::parse_xaiger(const dict &box_lookup) boxes.emplace_back(cell); } } - else if (c == 'a' || c == 'i' || c == 'o') { + else if (c == 'a' || c == 'i' || c == 'o' || c == 's') { uint32_t dataSize = parse_xaiger_literal(f); f.ignore(dataSize); + log_debug("ignoring '%c'\n", c); } else { break; -- cgit v1.2.3 From 911a152b39959137b26e68581a6cacbcabb4ab1d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Nov 2019 16:13:28 -0800 Subject: Add test --- tests/simple_abc9/abc9.v | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 1844bac20..13c505eec 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -268,7 +268,12 @@ assign o = { 1'b1, 1'bx }; assign p = { 1'b1, 1'bx, 1'b0 }; endmodule -module abc9_test029(input clk1, clk2, input d, output reg q1, q2); +module abc9_test029(input clk1, clk2, d, output reg q1, q2); always @(posedge clk1) q1 <= d; always @(negedge clk2) q2 <= q1; endmodule + +module abc9_test030(input clk, d, output reg q1, q2); +always @(posedge clk) q1 <= d; +always @(posedge clk) q2 <= q1; +endmodule -- cgit v1.2.3 From c4ec42ac38bd5678d9f3018d3921a3f0f4239986 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Nov 2019 16:17:03 -0800 Subject: When expanding upwards, do not capture $__ABC9_{FF,ASYNC}_ Since they should be captured downwards from the owning flop --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8d4ff4025..4b6ec6e11 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1165,7 +1165,7 @@ struct Abc9Pass : public Pass { for (auto bit : cell_to_bit_up[cell]) for (auto c : bit_to_cell_up[bit]) - if (unassigned_cells.count(c)) { + if (unassigned_cells.count(c) && !c->type.in("$__ABC9_FF_", "$__ABC9_ASYNC_")) { unassigned_cells.erase(c); next_expand_queue_up.insert(c); assigned_cells[key].insert(c->name); -- 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(-) 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 39fdcb892b1b65363fdf7c1bc6d9e2612c1c38e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Nov 2019 16:27:34 -0800 Subject: async2sync -> clk2fflogic --- tests/various/abc9.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index 9e732bdc8..f7a3f1fa0 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -26,7 +26,7 @@ select -assert-none t:$lut t:unknown %% t: %D design -load read hierarchy -top abc9_test031 proc -async2sync +clk2fflogic design -save gold abc9 -lut 4 -- cgit v1.2.3 From 6841e3b1c2b2bc3124810f3a8f96ed00a96e954c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Nov 2019 16:33:20 -0800 Subject: Another sloppy mistake! --- tests/various/abc9.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/various/abc9.v b/tests/various/abc9.v index 85828bf30..f0b3f6837 100644 --- a/tests/various/abc9.v +++ b/tests/various/abc9.v @@ -13,6 +13,6 @@ endmodule module abc9_test032(input clk, d, r, output reg q); initial q = 1'b0; always @(negedge clk or negedge r) - if (r) q <= 1'b0; + if (!r) q <= 1'b0; else q <= d; endmodule -- cgit v1.2.3 From c761fa49b73e9ad3680b05e89442adb6fb22b543 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 12:37:57 -0800 Subject: Missing endmodule --- tests/simple_abc9/abc9.v | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 596a52501..6bdd3bc32 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -288,3 +288,4 @@ endmodule module abc9_test033(input clk, d, output reg q1, q2); always @(posedge clk) q1 <= d; always @(posedge clk) q2 <= q1; +endmodule -- 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(-) 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 856a3dc98dcebdfdd331a5394a4556c00b4fcb8c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 15:33:51 -0800 Subject: New 'clkpart' to {,un}partition design according to clock/enable --- passes/techmap/clkpart.cc | 268 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 passes/techmap/clkpart.cc diff --git a/passes/techmap/clkpart.cc b/passes/techmap/clkpart.cc new file mode 100644 index 000000000..4fa729250 --- /dev/null +++ b/passes/techmap/clkpart.cc @@ -0,0 +1,268 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct ClkPartPass : public Pass { + ClkPartPass() : Pass("clkpart", "partition design according to clock domain") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" clkpart [options] [selection]\n"); + log("\n"); + log("Partition the contents of selected modules according to the clock (and optionally\n"); + log("the enable) domains of its $_DFF* cells by extracting them into sub-modules,\n"); + log("using the `submod` command.\n"); + log("Sub-modules created by this command are marked with a 'clkpart' attribute.\n"); + log("\n"); + log(" -unpart\n"); + log(" undo this operation within the selected modules, by flattening those with\n"); + log(" a 'clkpart' attribute into those modules without this attribute.\n"); + log("\n"); + log(" -enable\n"); + log(" also consider enable domains.\n"); + log("\n"); + } + + bool unpart_mode, enable_mode; + + void clear_flags() YS_OVERRIDE + { + unpart_mode = false; + enable_mode = false; + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing CLKPART pass (TODO).\n"); + log_push(); + + clear_flags(); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-unpart") { + unpart_mode = true; + continue; + } + if (args[argidx] == "-enable") { + enable_mode = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (unpart_mode) + unpart(design); + else + part(design); + + log_pop(); + } + + void part(RTLIL::Design *design) + { + CellTypes ct(design); + SigMap assign_map; + + for (auto mod : design->selected_modules()) + { + if (mod->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(mod)); + continue; + } + + assign_map.set(mod); + + std::vector all_cells = mod->selected_cells(); + std::set unassigned_cells(all_cells.begin(), all_cells.end()); + + std::set expand_queue, next_expand_queue; + std::set expand_queue_up, next_expand_queue_up; + std::set expand_queue_down, next_expand_queue_down; + + typedef tuple clkdomain_t; + std::map> assigned_cells; + std::map assigned_cells_reverse; + + std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; + std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; + + for (auto cell : all_cells) + { + clkdomain_t key; + + for (auto &conn : cell->connections()) + for (auto bit : conn.second) { + bit = assign_map(bit); + if (bit.wire != nullptr) { + cell_to_bit[cell].insert(bit); + bit_to_cell[bit].insert(cell); + if (ct.cell_input(cell->type, conn.first)) { + cell_to_bit_up[cell].insert(bit); + bit_to_cell_down[bit].insert(cell); + } + if (ct.cell_output(cell->type, conn.first)) { + cell_to_bit_down[cell].insert(bit); + bit_to_cell_up[bit].insert(cell); + } + } + } + + if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) + { + key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); + } + else + if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + { + bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); + bool this_en_pol = !enable_mode || cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, enable_mode ? assign_map(cell->getPort(ID(E)) : RTLIL::SigSpec())); + } + else + continue; + + unassigned_cells.erase(cell); + expand_queue.insert(cell); + expand_queue_up.insert(cell); + expand_queue_down.insert(cell); + + assigned_cells[key].push_back(cell->name); + assigned_cells_reverse[cell] = key; + } + + while (!expand_queue_up.empty() || !expand_queue_down.empty()) + { + if (!expand_queue_up.empty()) + { + RTLIL::Cell *cell = *expand_queue_up.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_up.erase(cell); + + for (auto bit : cell_to_bit_up[cell]) + for (auto c : bit_to_cell_up[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c->name); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (!expand_queue_down.empty()) + { + RTLIL::Cell *cell = *expand_queue_down.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_down.erase(cell); + + for (auto bit : cell_to_bit_down[cell]) + for (auto c : bit_to_cell_down[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c->name); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (expand_queue_up.empty() && expand_queue_down.empty()) { + expand_queue_up.swap(next_expand_queue_up); + expand_queue_down.swap(next_expand_queue_down); + } + } + + while (!expand_queue.empty()) + { + RTLIL::Cell *cell = *expand_queue.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue.erase(cell); + + for (auto bit : cell_to_bit.at(cell)) { + for (auto c : bit_to_cell[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue.insert(c); + assigned_cells[key].push_back(c->name); + assigned_cells_reverse[c] = key; + } + bit_to_cell[bit].clear(); + } + + if (expand_queue.empty()) + expand_queue.swap(next_expand_queue); + } + + clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); + for (auto cell : unassigned_cells) { + assigned_cells[key].push_back(cell->name); + assigned_cells_reverse[cell] = key; + } + + log_header(design, "Summary of detected clock domains:\n"); + for (auto &it : assigned_cells) + log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), + std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), + std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + + for (auto &it : assigned_cells) { + RTLIL::Selection sel(false); + sel.selected_members[mod->name] = pool(it.second.begin(), it.second.end()); + + RTLIL::IdString submod = stringf("%s.%s", mod->name.c_str(), NEW_ID.c_str()); + Pass::call_on_selection(design, sel, stringf("submod -name %s", submod.c_str())); + + design->module(submod)->set_bool_attribute(ID(clkpart)); + } + } + } + + void unpart(RTLIL::Design *design) + { + vector keeped; + for (auto mod : design->selected_modules()) { + if (mod->get_bool_attribute(ID(clkpart))) + continue; + if (mod->get_bool_attribute(ID(keep_hierarchy))) + continue; + keeped.push_back(mod); + mod->set_bool_attribute(ID(keep_hierarchy)); + } + + Pass::call(design, "flatten"); + + for (auto mod : keeped) + mod->set_bool_attribute(ID(keep_hierarchy), false); + + } +} ClkPartPass; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From 450ad0e9ba031fbeef904746ca773e3b0e21af8f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 15:35:08 -0800 Subject: Add to CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index a49c27b05..d9d261fbc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -53,6 +53,7 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "check -mapped" - Added checking of SystemVerilog always block types (always_comb, always_latch and always_ff) + - Added "clkpart" pass Yosys 0.8 .. Yosys 0.9 ---------------------- -- cgit v1.2.3 From 3df191cec5d64c743f8fbb0294d9492c5598bc1b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 15:41:23 -0800 Subject: Entry in Makefile.inc --- passes/techmap/Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index cd357d72a..13992315e 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -41,6 +41,7 @@ OBJS += passes/techmap/zinit.o OBJS += passes/techmap/dff2dffs.o OBJS += passes/techmap/flowmap.o OBJS += passes/techmap/extractinv.o +OBJS += passes/techmap/clkpart.o endif GENFILES += passes/techmap/techmap.inc -- cgit v1.2.3 From 84153288bb7d92c31c1d8873b1257a296ca664ad Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 15:41:34 -0800 Subject: Brackets --- passes/techmap/clkpart.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/clkpart.cc b/passes/techmap/clkpart.cc index 4fa729250..bf3b5bd30 100644 --- a/passes/techmap/clkpart.cc +++ b/passes/techmap/clkpart.cc @@ -144,7 +144,7 @@ struct ClkPartPass : public Pass { { bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); bool this_en_pol = !enable_mode || cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, enable_mode ? assign_map(cell->getPort(ID(E)) : RTLIL::SigSpec())); + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, enable_mode ? assign_map(cell->getPort(ID(E))) : RTLIL::SigSpec()); } else continue; -- cgit v1.2.3 From 2ef2e2c040d9ff299f1bc6daca891a1236ed877e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 16:41:05 -0800 Subject: Add testcase --- tests/various/submod.ys | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/various/submod.ys diff --git a/tests/various/submod.ys b/tests/various/submod.ys new file mode 100644 index 000000000..54455b580 --- /dev/null +++ b/tests/various/submod.ys @@ -0,0 +1,26 @@ +read_verilog < Date: Fri, 22 Nov 2019 16:46:26 -0800 Subject: sigmap(wire) should inherit port_output status of POs --- passes/hierarchy/submod.cc | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index ec242aa1f..982558fb2 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -20,6 +20,7 @@ #include "kernel/register.h" #include "kernel/celltypes.h" #include "kernel/log.h" +#include "kernel/sigtools.h" #include #include #include @@ -32,6 +33,7 @@ struct SubmodWorker CellTypes ct; RTLIL::Design *design; RTLIL::Module *module; + pool outputs; bool copy_mode; std::string opt_name; @@ -125,7 +127,7 @@ struct SubmodWorker if (wire->port_input) flags.is_ext_driven = true; - if (wire->port_output) + if (wire->port_output || outputs.count(wire)) flags.is_ext_used = true; bool new_wire_port_input = false; @@ -219,6 +221,22 @@ struct SubmodWorker ct.setup_stdcells_mem(); ct.setup_design(design); + SigMap sigmap(module); + for (auto port : module->ports) { + auto wire = module->wire(port); + if (!wire->port_output) + continue; + auto sig = sigmap(wire); + for (auto c : sig.chunks()) { + if (!c.wire) + continue; + if (c.wire == wire) + continue; + outputs.insert(c.wire); + log_dump(c.wire->name); + } + } + if (opt_name.empty()) { for (auto &it : module->wires_) -- cgit v1.2.3 From 8779faf7891cf1fc394204b12ad1a0e403d22c6b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 16:50:09 -0800 Subject: Cleanup spacing --- tests/various/submod.ys | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/various/submod.ys b/tests/various/submod.ys index 54455b580..271a8edef 100644 --- a/tests/various/submod.ys +++ b/tests/various/submod.ys @@ -13,9 +13,9 @@ EOT hierarchy -top top proc design -save gold + submod flatten - design -stash gate design -import gold -as gold @@ -23,4 +23,3 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter - -- 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(-) 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 74ea4381362d4f402e7fc262b960e14122128303 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 16:52:55 -0800 Subject: Add testcase for signal used as part input part output --- tests/simple_abc9/abc9.v | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 6bdd3bc32..8314af211 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -289,3 +289,8 @@ module abc9_test033(input clk, d, output reg q1, q2); always @(posedge clk) q1 <= d; always @(posedge clk) q2 <= q1; endmodule + +module abc9_test034(input clk, d, output reg [1:0] q); +always @(posedge clk) q[0] <= d; +always @(negedge clk) q[1] <= q[0]; +endmodule -- cgit v1.2.3 From 00d76f6cc4ccbf15b188570f0bf0dbd143ce3782 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 16:58:08 -0800 Subject: Replace TODO --- passes/techmap/clkpart.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/clkpart.cc b/passes/techmap/clkpart.cc index bf3b5bd30..d8d53536d 100644 --- a/passes/techmap/clkpart.cc +++ b/passes/techmap/clkpart.cc @@ -58,7 +58,7 @@ struct ClkPartPass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - log_header(design, "Executing CLKPART pass (TODO).\n"); + log_header(design, "Executing CLKPART pass (partition design according to clock domain).\n"); log_push(); clear_flags(); -- cgit v1.2.3 From 95af8f56e45e23dd29c9a3992f18eee2fa6ceeb1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 17:00:11 -0800 Subject: Only action if there is more than one clock domain --- passes/techmap/clkpart.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/passes/techmap/clkpart.cc b/passes/techmap/clkpart.cc index d8d53536d..8f671c175 100644 --- a/passes/techmap/clkpart.cc +++ b/passes/techmap/clkpart.cc @@ -233,15 +233,16 @@ struct ClkPartPass : public Pass { std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); - for (auto &it : assigned_cells) { - RTLIL::Selection sel(false); - sel.selected_members[mod->name] = pool(it.second.begin(), it.second.end()); + if (assigned_cells.size() > 1) + for (auto &it : assigned_cells) { + RTLIL::Selection sel(false); + sel.selected_members[mod->name] = pool(it.second.begin(), it.second.end()); - RTLIL::IdString submod = stringf("%s.%s", mod->name.c_str(), NEW_ID.c_str()); - Pass::call_on_selection(design, sel, stringf("submod -name %s", submod.c_str())); + RTLIL::IdString submod = stringf("%s.%s", mod->name.c_str(), NEW_ID.c_str()); + Pass::call_on_selection(design, sel, stringf("submod -name %s", submod.c_str())); - design->module(submod)->set_bool_attribute(ID(clkpart)); - } + design->module(submod)->set_bool_attribute(ID(clkpart)); + } } } -- cgit v1.2.3 From 573396851a03f08f80644924a560369d50659507 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 17:03:30 -0800 Subject: Oops --- passes/hierarchy/submod.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 982558fb2..707bc26b3 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -233,7 +233,6 @@ struct SubmodWorker if (c.wire == wire) continue; outputs.insert(c.wire); - log_dump(c.wire->name); } } -- cgit v1.2.3 From 4fdcf8f7d73d0e577815ab50a3e0255f4bfd2154 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 17:23:34 -0800 Subject: Add another test with constant driver --- tests/various/submod.ys | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/various/submod.ys b/tests/various/submod.ys index 271a8edef..a9d3fe672 100644 --- a/tests/various/submod.ys +++ b/tests/various/submod.ys @@ -23,3 +23,31 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter + + +design -reset +read_verilog < Date: Fri, 22 Nov 2019 17:23:51 -0800 Subject: Constant driven signals are also an input to submodules --- passes/hierarchy/submod.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 707bc26b3..a1fac9b79 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -33,7 +33,7 @@ struct SubmodWorker CellTypes ct; RTLIL::Design *design; RTLIL::Module *module; - pool outputs; + pool constants, outputs; bool copy_mode; std::string opt_name; @@ -125,7 +125,7 @@ struct SubmodWorker RTLIL::Wire *wire = it.first; wire_flags_t &flags = it.second; - if (wire->port_input) + if (wire->port_input || constants.count(wire)) flags.is_ext_driven = true; if (wire->port_output || outputs.count(wire)) flags.is_ext_used = true; @@ -235,6 +235,14 @@ struct SubmodWorker outputs.insert(c.wire); } } + for (auto wire : module->wires()) { + auto sig = sigmap(wire); + for (auto c : sig.chunks()) { + if (c.wire) + continue; + constants.insert(wire); + } + } if (opt_name.empty()) { -- cgit v1.2.3 From 900c806d4e48e861161661239de418613f50babb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 17:25:53 -0800 Subject: Move clkpart into passes/hierarchy --- passes/hierarchy/Makefile.inc | 1 + passes/hierarchy/clkpart.cc | 269 ++++++++++++++++++++++++++++++++++++++++++ passes/techmap/Makefile.inc | 1 - passes/techmap/clkpart.cc | 269 ------------------------------------------ 4 files changed, 270 insertions(+), 270 deletions(-) create mode 100644 passes/hierarchy/clkpart.cc delete mode 100644 passes/techmap/clkpart.cc diff --git a/passes/hierarchy/Makefile.inc b/passes/hierarchy/Makefile.inc index b3f139b72..ea809ec08 100644 --- a/passes/hierarchy/Makefile.inc +++ b/passes/hierarchy/Makefile.inc @@ -2,4 +2,5 @@ OBJS += passes/hierarchy/hierarchy.o OBJS += passes/hierarchy/uniquify.o OBJS += passes/hierarchy/submod.o +OBJS += passes/hierarchy/clkpart.o diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc new file mode 100644 index 000000000..8f671c175 --- /dev/null +++ b/passes/hierarchy/clkpart.cc @@ -0,0 +1,269 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct ClkPartPass : public Pass { + ClkPartPass() : Pass("clkpart", "partition design according to clock domain") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" clkpart [options] [selection]\n"); + log("\n"); + log("Partition the contents of selected modules according to the clock (and optionally\n"); + log("the enable) domains of its $_DFF* cells by extracting them into sub-modules,\n"); + log("using the `submod` command.\n"); + log("Sub-modules created by this command are marked with a 'clkpart' attribute.\n"); + log("\n"); + log(" -unpart\n"); + log(" undo this operation within the selected modules, by flattening those with\n"); + log(" a 'clkpart' attribute into those modules without this attribute.\n"); + log("\n"); + log(" -enable\n"); + log(" also consider enable domains.\n"); + log("\n"); + } + + bool unpart_mode, enable_mode; + + void clear_flags() YS_OVERRIDE + { + unpart_mode = false; + enable_mode = false; + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing CLKPART pass (partition design according to clock domain).\n"); + log_push(); + + clear_flags(); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-unpart") { + unpart_mode = true; + continue; + } + if (args[argidx] == "-enable") { + enable_mode = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (unpart_mode) + unpart(design); + else + part(design); + + log_pop(); + } + + void part(RTLIL::Design *design) + { + CellTypes ct(design); + SigMap assign_map; + + for (auto mod : design->selected_modules()) + { + if (mod->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(mod)); + continue; + } + + assign_map.set(mod); + + std::vector all_cells = mod->selected_cells(); + std::set unassigned_cells(all_cells.begin(), all_cells.end()); + + std::set expand_queue, next_expand_queue; + std::set expand_queue_up, next_expand_queue_up; + std::set expand_queue_down, next_expand_queue_down; + + typedef tuple clkdomain_t; + std::map> assigned_cells; + std::map assigned_cells_reverse; + + std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; + std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; + + for (auto cell : all_cells) + { + clkdomain_t key; + + for (auto &conn : cell->connections()) + for (auto bit : conn.second) { + bit = assign_map(bit); + if (bit.wire != nullptr) { + cell_to_bit[cell].insert(bit); + bit_to_cell[bit].insert(cell); + if (ct.cell_input(cell->type, conn.first)) { + cell_to_bit_up[cell].insert(bit); + bit_to_cell_down[bit].insert(cell); + } + if (ct.cell_output(cell->type, conn.first)) { + cell_to_bit_down[cell].insert(bit); + bit_to_cell_up[bit].insert(cell); + } + } + } + + if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) + { + key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); + } + else + if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + { + bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); + bool this_en_pol = !enable_mode || cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, enable_mode ? assign_map(cell->getPort(ID(E))) : RTLIL::SigSpec()); + } + else + continue; + + unassigned_cells.erase(cell); + expand_queue.insert(cell); + expand_queue_up.insert(cell); + expand_queue_down.insert(cell); + + assigned_cells[key].push_back(cell->name); + assigned_cells_reverse[cell] = key; + } + + while (!expand_queue_up.empty() || !expand_queue_down.empty()) + { + if (!expand_queue_up.empty()) + { + RTLIL::Cell *cell = *expand_queue_up.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_up.erase(cell); + + for (auto bit : cell_to_bit_up[cell]) + for (auto c : bit_to_cell_up[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c->name); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (!expand_queue_down.empty()) + { + RTLIL::Cell *cell = *expand_queue_down.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_down.erase(cell); + + for (auto bit : cell_to_bit_down[cell]) + for (auto c : bit_to_cell_down[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c->name); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (expand_queue_up.empty() && expand_queue_down.empty()) { + expand_queue_up.swap(next_expand_queue_up); + expand_queue_down.swap(next_expand_queue_down); + } + } + + while (!expand_queue.empty()) + { + RTLIL::Cell *cell = *expand_queue.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue.erase(cell); + + for (auto bit : cell_to_bit.at(cell)) { + for (auto c : bit_to_cell[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue.insert(c); + assigned_cells[key].push_back(c->name); + assigned_cells_reverse[c] = key; + } + bit_to_cell[bit].clear(); + } + + if (expand_queue.empty()) + expand_queue.swap(next_expand_queue); + } + + clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); + for (auto cell : unassigned_cells) { + assigned_cells[key].push_back(cell->name); + assigned_cells_reverse[cell] = key; + } + + log_header(design, "Summary of detected clock domains:\n"); + for (auto &it : assigned_cells) + log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), + std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), + std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + + if (assigned_cells.size() > 1) + for (auto &it : assigned_cells) { + RTLIL::Selection sel(false); + sel.selected_members[mod->name] = pool(it.second.begin(), it.second.end()); + + RTLIL::IdString submod = stringf("%s.%s", mod->name.c_str(), NEW_ID.c_str()); + Pass::call_on_selection(design, sel, stringf("submod -name %s", submod.c_str())); + + design->module(submod)->set_bool_attribute(ID(clkpart)); + } + } + } + + void unpart(RTLIL::Design *design) + { + vector keeped; + for (auto mod : design->selected_modules()) { + if (mod->get_bool_attribute(ID(clkpart))) + continue; + if (mod->get_bool_attribute(ID(keep_hierarchy))) + continue; + keeped.push_back(mod); + mod->set_bool_attribute(ID(keep_hierarchy)); + } + + Pass::call(design, "flatten"); + + for (auto mod : keeped) + mod->set_bool_attribute(ID(keep_hierarchy), false); + + } +} ClkPartPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 13992315e..cd357d72a 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -41,7 +41,6 @@ OBJS += passes/techmap/zinit.o OBJS += passes/techmap/dff2dffs.o OBJS += passes/techmap/flowmap.o OBJS += passes/techmap/extractinv.o -OBJS += passes/techmap/clkpart.o endif GENFILES += passes/techmap/techmap.inc diff --git a/passes/techmap/clkpart.cc b/passes/techmap/clkpart.cc deleted file mode 100644 index 8f671c175..000000000 --- a/passes/techmap/clkpart.cc +++ /dev/null @@ -1,269 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Eddie Hung - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/register.h" -#include "kernel/sigtools.h" -#include "kernel/celltypes.h" -#include "kernel/rtlil.h" -#include "kernel/log.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct ClkPartPass : public Pass { - ClkPartPass() : Pass("clkpart", "partition design according to clock domain") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" clkpart [options] [selection]\n"); - log("\n"); - log("Partition the contents of selected modules according to the clock (and optionally\n"); - log("the enable) domains of its $_DFF* cells by extracting them into sub-modules,\n"); - log("using the `submod` command.\n"); - log("Sub-modules created by this command are marked with a 'clkpart' attribute.\n"); - log("\n"); - log(" -unpart\n"); - log(" undo this operation within the selected modules, by flattening those with\n"); - log(" a 'clkpart' attribute into those modules without this attribute.\n"); - log("\n"); - log(" -enable\n"); - log(" also consider enable domains.\n"); - log("\n"); - } - - bool unpart_mode, enable_mode; - - void clear_flags() YS_OVERRIDE - { - unpart_mode = false; - enable_mode = false; - } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing CLKPART pass (partition design according to clock domain).\n"); - log_push(); - - clear_flags(); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-unpart") { - unpart_mode = true; - continue; - } - if (args[argidx] == "-enable") { - enable_mode = true; - continue; - } - break; - } - extra_args(args, argidx, design); - - if (unpart_mode) - unpart(design); - else - part(design); - - log_pop(); - } - - void part(RTLIL::Design *design) - { - CellTypes ct(design); - SigMap assign_map; - - for (auto mod : design->selected_modules()) - { - if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); - continue; - } - - assign_map.set(mod); - - std::vector all_cells = mod->selected_cells(); - std::set unassigned_cells(all_cells.begin(), all_cells.end()); - - std::set expand_queue, next_expand_queue; - std::set expand_queue_up, next_expand_queue_up; - std::set expand_queue_down, next_expand_queue_down; - - typedef tuple clkdomain_t; - std::map> assigned_cells; - std::map assigned_cells_reverse; - - std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; - std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; - - for (auto cell : all_cells) - { - clkdomain_t key; - - for (auto &conn : cell->connections()) - for (auto bit : conn.second) { - bit = assign_map(bit); - if (bit.wire != nullptr) { - cell_to_bit[cell].insert(bit); - bit_to_cell[bit].insert(cell); - if (ct.cell_input(cell->type, conn.first)) { - cell_to_bit_up[cell].insert(bit); - bit_to_cell_down[bit].insert(cell); - } - if (ct.cell_output(cell->type, conn.first)) { - cell_to_bit_down[cell].insert(bit); - bit_to_cell_up[bit].insert(cell); - } - } - } - - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) - { - key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); - } - else - if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - { - bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); - bool this_en_pol = !enable_mode || cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, enable_mode ? assign_map(cell->getPort(ID(E))) : RTLIL::SigSpec()); - } - else - continue; - - unassigned_cells.erase(cell); - expand_queue.insert(cell); - expand_queue_up.insert(cell); - expand_queue_down.insert(cell); - - assigned_cells[key].push_back(cell->name); - assigned_cells_reverse[cell] = key; - } - - while (!expand_queue_up.empty() || !expand_queue_down.empty()) - { - if (!expand_queue_up.empty()) - { - RTLIL::Cell *cell = *expand_queue_up.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue_up.erase(cell); - - for (auto bit : cell_to_bit_up[cell]) - for (auto c : bit_to_cell_up[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c->name); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (!expand_queue_down.empty()) - { - RTLIL::Cell *cell = *expand_queue_down.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue_down.erase(cell); - - for (auto bit : cell_to_bit_down[cell]) - for (auto c : bit_to_cell_down[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c->name); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (expand_queue_up.empty() && expand_queue_down.empty()) { - expand_queue_up.swap(next_expand_queue_up); - expand_queue_down.swap(next_expand_queue_down); - } - } - - while (!expand_queue.empty()) - { - RTLIL::Cell *cell = *expand_queue.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue.erase(cell); - - for (auto bit : cell_to_bit.at(cell)) { - for (auto c : bit_to_cell[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue.insert(c); - assigned_cells[key].push_back(c->name); - assigned_cells_reverse[c] = key; - } - bit_to_cell[bit].clear(); - } - - if (expand_queue.empty()) - expand_queue.swap(next_expand_queue); - } - - clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); - for (auto cell : unassigned_cells) { - assigned_cells[key].push_back(cell->name); - assigned_cells_reverse[cell] = key; - } - - log_header(design, "Summary of detected clock domains:\n"); - for (auto &it : assigned_cells) - log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), - std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), - std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); - - if (assigned_cells.size() > 1) - for (auto &it : assigned_cells) { - RTLIL::Selection sel(false); - sel.selected_members[mod->name] = pool(it.second.begin(), it.second.end()); - - RTLIL::IdString submod = stringf("%s.%s", mod->name.c_str(), NEW_ID.c_str()); - Pass::call_on_selection(design, sel, stringf("submod -name %s", submod.c_str())); - - design->module(submod)->set_bool_attribute(ID(clkpart)); - } - } - } - - void unpart(RTLIL::Design *design) - { - vector keeped; - for (auto mod : design->selected_modules()) { - if (mod->get_bool_attribute(ID(clkpart))) - continue; - if (mod->get_bool_attribute(ID(keep_hierarchy))) - continue; - keeped.push_back(mod); - mod->set_bool_attribute(ID(keep_hierarchy)); - } - - Pass::call(design, "flatten"); - - for (auto mod : keeped) - mod->set_bool_attribute(ID(keep_hierarchy), false); - - } -} ClkPartPass; - -PRIVATE_NAMESPACE_END -- cgit v1.2.3 From 08f85e64383c0248030873dcdcf388853d335eea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 20:53:48 -0800 Subject: Stray dump --- tests/various/submod.ys | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/various/submod.ys b/tests/various/submod.ys index a9d3fe672..451ced5e6 100644 --- a/tests/various/submod.ys +++ b/tests/various/submod.ys @@ -42,7 +42,6 @@ proc design -save gold submod -dump flatten design -stash gate -- cgit v1.2.3 From cba3073026711e7683c46ba091c56a5c5a041a45 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 20:53:58 -0800 Subject: submod to bitty rather bussy, for bussy wires used as input and output --- passes/hierarchy/submod.cc | 87 +++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index a1fac9b79..212932e46 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -33,7 +33,8 @@ struct SubmodWorker CellTypes ct; RTLIL::Design *design; RTLIL::Module *module; - pool constants, outputs; + SigMap sigmap; + pool outputs; bool copy_mode; std::string opt_name; @@ -46,44 +47,44 @@ struct SubmodWorker std::map submodules; - struct wire_flags_t { + struct bit_flags_t { RTLIL::Wire *new_wire; bool is_int_driven, is_int_used, is_ext_driven, is_ext_used; - wire_flags_t() : new_wire(NULL), is_int_driven(false), is_int_used(false), is_ext_driven(false), is_ext_used(false) { } + bit_flags_t() : new_wire(NULL), is_int_driven(false), is_int_used(false), is_ext_driven(false), is_ext_used(false) { } }; - std::map wire_flags; + std::map bit_flags; bool flag_found_something; - void flag_wire(RTLIL::Wire *wire, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used) + void flag_bit(RTLIL::SigBit bit, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used) { - if (wire_flags.count(wire) == 0) { + if (bit_flags.count(bit) == 0) { if (!create) return; - wire_flags[wire] = wire_flags_t(); + bit_flags[bit] = bit_flags_t(); } if (set_int_driven) - wire_flags[wire].is_int_driven = true; + bit_flags[bit].is_int_driven = true; if (set_int_used) - wire_flags[wire].is_int_used = true; + bit_flags[bit].is_int_used = true; if (set_ext_driven) - wire_flags[wire].is_ext_driven = true; + bit_flags[bit].is_ext_driven = true; if (set_ext_used) - wire_flags[wire].is_ext_used = true; + bit_flags[bit].is_ext_used = true; flag_found_something = true; } void flag_signal(const RTLIL::SigSpec &sig, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used) { - for (auto &c : sig.chunks()) - if (c.wire != NULL) - flag_wire(c.wire, create, set_int_driven, set_int_used, set_ext_driven, set_ext_used); + for (auto &b : sig) + if (b.wire != NULL) + flag_bit(b, create, set_int_driven, set_int_used, set_ext_driven, set_ext_used); } void handle_submodule(SubModule &submod) { log("Creating submodule %s (%s) of module %s.\n", submod.name.c_str(), submod.full_name.c_str(), module->name.c_str()); - wire_flags.clear(); + bit_flags.clear(); for (RTLIL::Cell *cell : submod.cells) { if (ct.cell_known(cell->type)) { for (auto &conn : cell->connections()) @@ -116,18 +117,19 @@ struct SubmodWorker int auto_name_counter = 1; std::set all_wire_names; - for (auto &it : wire_flags) { - all_wire_names.insert(it.first->name); + for (auto &it : bit_flags) { + all_wire_names.insert(it.first.wire->name); } - for (auto &it : wire_flags) + for (auto &it : bit_flags) { - RTLIL::Wire *wire = it.first; - wire_flags_t &flags = it.second; + const RTLIL::SigBit &bit = it.first; + RTLIL::Wire *wire = bit.wire; + bit_flags_t &flags = it.second; - if (wire->port_input || constants.count(wire)) + if (wire->port_input) flags.is_ext_driven = true; - if (wire->port_output || outputs.count(wire)) + if (outputs.count(bit)) flags.is_ext_used = true; bool new_wire_port_input = false; @@ -141,7 +143,11 @@ struct SubmodWorker if (flags.is_int_driven && flags.is_ext_driven) new_wire_port_input = true, new_wire_port_output = true; - std::string new_wire_name = wire->name.str(); + RTLIL::IdString new_wire_name; + if (GetSize(wire) == 1) + new_wire_name = wire->name; + else + new_wire_name = stringf("%s[%d]", wire->name.c_str(), bit.offset); if (new_wire_port_input || new_wire_port_output) { while (new_wire_name[0] == '$') { std::string next_wire_name = stringf("\\n%d", auto_name_counter++); @@ -152,10 +158,9 @@ struct SubmodWorker } } - RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name, wire->width); + RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name); new_wire->port_input = new_wire_port_input; new_wire->port_output = new_wire_port_output; - new_wire->start_offset = wire->start_offset; new_wire->attributes = wire->attributes; if (new_wire->port_input && new_wire->port_output) @@ -178,8 +183,8 @@ struct SubmodWorker for (auto &conn : new_cell->connections_) for (auto &bit : conn.second) if (bit.wire != NULL) { - log_assert(wire_flags.count(bit.wire) > 0); - bit.wire = wire_flags[bit.wire].new_wire; + log_assert(bit_flags.count(bit) > 0); + bit = bit_flags[bit].new_wire; } log(" cell %s (%s)\n", new_cell->name.c_str(), new_cell->type.c_str()); if (!copy_mode) @@ -189,18 +194,18 @@ struct SubmodWorker if (!copy_mode) { RTLIL::Cell *new_cell = module->addCell(submod.full_name, submod.full_name); - for (auto &it : wire_flags) + for (auto &it : bit_flags) { - RTLIL::Wire *old_wire = it.first; + RTLIL::SigBit old_bit = it.first; RTLIL::Wire *new_wire = it.second.new_wire; if (new_wire->port_id > 0) - new_cell->setPort(new_wire->name, RTLIL::SigSpec(old_wire)); + new_cell->setPort(new_wire->name, old_bit); } } } SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, std::string opt_name = std::string()) : - design(design), module(module), copy_mode(copy_mode), opt_name(opt_name) + design(design), module(module), sigmap(module), copy_mode(copy_mode), opt_name(opt_name) { if (!design->selected_whole_module(module->name) && opt_name.empty()) return; @@ -221,27 +226,13 @@ struct SubmodWorker ct.setup_stdcells_mem(); ct.setup_design(design); - SigMap sigmap(module); for (auto port : module->ports) { auto wire = module->wire(port); if (!wire->port_output) continue; - auto sig = sigmap(wire); - for (auto c : sig.chunks()) { - if (!c.wire) - continue; - if (c.wire == wire) - continue; - outputs.insert(c.wire); - } - } - for (auto wire : module->wires()) { - auto sig = sigmap(wire); - for (auto c : sig.chunks()) { - if (c.wire) - continue; - constants.insert(wire); - } + for (auto b : sigmap(wire)) + if (b.wire) + outputs.insert(b); } if (opt_name.empty()) -- cgit v1.2.3 From 5cd3d3db0aaa8642dad53f8fb629e3109cef5825 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 22:22:56 -0800 Subject: Remove redundant flatten --- tests/various/submod.ys | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/various/submod.ys b/tests/various/submod.ys index 451ced5e6..7c6f555ac 100644 --- a/tests/various/submod.ys +++ b/tests/various/submod.ys @@ -15,7 +15,6 @@ proc design -save gold submod -flatten design -stash gate design -import gold -as gold @@ -42,7 +41,6 @@ proc design -save gold submod -flatten design -stash gate design -import gold -as gold -- cgit v1.2.3 From 736b96b186cd1096fd6043797fdcae295580f289 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 23:16:15 -0800 Subject: Call submod once, more meaningful submod names, ignore largest domain --- passes/hierarchy/clkpart.cc | 50 +++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index 8f671c175..a9ef2aa6c 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -90,7 +90,9 @@ struct ClkPartPass : public Pass { { CellTypes ct(design); SigMap assign_map; + std::vector new_submods; + log_header(design, "Summary of detected clock domains:\n"); for (auto mod : design->selected_modules()) { if (mod->processes.size() > 0) { @@ -108,7 +110,7 @@ struct ClkPartPass : public Pass { std::set expand_queue_down, next_expand_queue_down; typedef tuple clkdomain_t; - std::map> assigned_cells; + std::map> assigned_cells; std::map assigned_cells_reverse; std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; @@ -154,7 +156,7 @@ struct ClkPartPass : public Pass { expand_queue_up.insert(cell); expand_queue_down.insert(cell); - assigned_cells[key].push_back(cell->name); + assigned_cells[key].push_back(cell); assigned_cells_reverse[cell] = key; } @@ -171,7 +173,7 @@ struct ClkPartPass : public Pass { if (unassigned_cells.count(c)) { unassigned_cells.erase(c); next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c->name); + assigned_cells[key].push_back(c); assigned_cells_reverse[c] = key; expand_queue.insert(c); } @@ -188,7 +190,7 @@ struct ClkPartPass : public Pass { if (unassigned_cells.count(c)) { unassigned_cells.erase(c); next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c->name); + assigned_cells[key].push_back(c); assigned_cells_reverse[c] = key; expand_queue.insert(c); } @@ -211,7 +213,7 @@ struct ClkPartPass : public Pass { if (unassigned_cells.count(c)) { unassigned_cells.erase(c); next_expand_queue.insert(c); - assigned_cells[key].push_back(c->name); + assigned_cells[key].push_back(c); assigned_cells_reverse[c] = key; } bit_to_cell[bit].clear(); @@ -223,27 +225,39 @@ struct ClkPartPass : public Pass { clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); for (auto cell : unassigned_cells) { - assigned_cells[key].push_back(cell->name); + assigned_cells[key].push_back(cell); assigned_cells_reverse[cell] = key; } - log_header(design, "Summary of detected clock domains:\n"); - for (auto &it : assigned_cells) - log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), + clkdomain_t largest_domain; + int largest_domain_size = 0; + log(" module %s\n", mod->name.c_str()); + for (auto &it : assigned_cells) { + log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + if (GetSize(it.second) > largest_domain_size) { + largest_domain = it.first; + largest_domain_size = GetSize(it.second); + } + } - if (assigned_cells.size() > 1) - for (auto &it : assigned_cells) { - RTLIL::Selection sel(false); - sel.selected_members[mod->name] = pool(it.second.begin(), it.second.end()); - - RTLIL::IdString submod = stringf("%s.%s", mod->name.c_str(), NEW_ID.c_str()); - Pass::call_on_selection(design, sel, stringf("submod -name %s", submod.c_str())); + for (auto &it : assigned_cells) { + if (it.first == largest_domain) + continue; - design->module(submod)->set_bool_attribute(ID(clkpart)); - } + std::string submod = stringf("\\%s%s.%s%s", + std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), + std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + for (auto c : it.second) + c->attributes[ID(submod)] = submod; + new_submods.push_back(stringf("%s_%s", mod->name.c_str(), submod.c_str())); + } } + + Pass::call(design, "submod"); + for (auto m : new_submods) + design->module(m)->set_bool_attribute(ID(clkpart)); } void unpart(RTLIL::Design *design) -- cgit v1.2.3 From 96941aacbb4e3be4901941b8c0ba4565f9919a22 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Nov 2019 23:29:10 -0800 Subject: Do not use log_signal() for empty SigSpec to prevent "{ }" --- passes/hierarchy/clkpart.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index a9ef2aa6c..7cd1f4b43 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -246,9 +246,11 @@ struct ClkPartPass : public Pass { if (it.first == largest_domain) continue; + auto clk = std::get<1>(it.first); + auto en = std::get<3>(it.first); std::string submod = stringf("\\%s%s.%s%s", - std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), - std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + std::get<0>(it.first) ? "" : "!", clk.empty() ? "" : log_signal(clk), + std::get<2>(it.first) ? "" : "!", en.empty() ? "" : log_signal(en)); for (auto c : it.second) c->attributes[ID(submod)] = submod; new_submods.push_back(stringf("%s_%s", mod->name.c_str(), submod.c_str())); -- cgit v1.2.3 From 66ff0511a0e3eeae2989c2fa582c1e1c13dd75ad Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 23 Nov 2019 09:52:17 -0800 Subject: Add -set_attr option, -unpart to take attr name --- passes/hierarchy/clkpart.cc | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index 7cd1f4b43..acdd9b4ae 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -28,7 +28,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct ClkPartPass : public Pass { - ClkPartPass() : Pass("clkpart", "partition design according to clock domain") { } + ClkPartPass() : Pass("clkpart", "partition design according to clock/enable domain") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -38,11 +38,14 @@ struct ClkPartPass : public Pass { log("Partition the contents of selected modules according to the clock (and optionally\n"); log("the enable) domains of its $_DFF* cells by extracting them into sub-modules,\n"); log("using the `submod` command.\n"); - log("Sub-modules created by this command are marked with a 'clkpart' attribute.\n"); log("\n"); - log(" -unpart\n"); - log(" undo this operation within the selected modules, by flattening those with\n"); - log(" a 'clkpart' attribute into those modules without this attribute.\n"); + log(" -set_attr \n"); + log(" set the specified attribute on all sub-modules created.\n"); + log("\n"); + log(" -unpart \n"); + log(" undo this operation within the selected modules, by flattening those\n"); + log(" attached with an attribute into those modules without this\n"); + log(" attribute.\n"); log("\n"); log(" -enable\n"); log(" also consider enable domains.\n"); @@ -50,15 +53,19 @@ struct ClkPartPass : public Pass { } bool unpart_mode, enable_mode; + IdString attr_name; + Const attr_value; void clear_flags() YS_OVERRIDE { unpart_mode = false; enable_mode = false; + attr_name = IdString(); + attr_value = Const(); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - log_header(design, "Executing CLKPART pass (partition design according to clock domain).\n"); + log_header(design, "Executing CLKPART pass (partition design according to clock/enable domain).\n"); log_push(); clear_flags(); @@ -66,8 +73,14 @@ struct ClkPartPass : public Pass { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-unpart") { + if (args[argidx] == "-set_attr" && argidx+2 < args.size()) { + attr_name = args[argidx++]; + attr_value = args[argidx++]; + continue; + } + if (args[argidx] == "-unpart" && argidx+1 < args.size()) { unpart_mode = true; + attr_name = args[argidx++]; continue; } if (args[argidx] == "-enable") { @@ -258,15 +271,17 @@ struct ClkPartPass : public Pass { } Pass::call(design, "submod"); - for (auto m : new_submods) - design->module(m)->set_bool_attribute(ID(clkpart)); + + if (!attr_name.empty()) + for (auto m : new_submods) + design->module(m)->attributes[attr_name] = attr_value; } void unpart(RTLIL::Design *design) { vector keeped; for (auto mod : design->selected_modules()) { - if (mod->get_bool_attribute(ID(clkpart))) + if (mod->get_bool_attribute(attr_name)) continue; if (mod->get_bool_attribute(ID(keep_hierarchy))) continue; -- cgit v1.2.3 From 165f5cb6cf3415bb56ddaef91079c558cd2f16d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 23 Nov 2019 10:01:09 -0800 Subject: More sane naming of submod --- passes/hierarchy/clkpart.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index acdd9b4ae..4f4291e06 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -261,9 +261,9 @@ struct ClkPartPass : public Pass { auto clk = std::get<1>(it.first); auto en = std::get<3>(it.first); - std::string submod = stringf("\\%s%s.%s%s", + std::string submod = stringf("clk=%s%s%s%s%s", std::get<0>(it.first) ? "" : "!", clk.empty() ? "" : log_signal(clk), - std::get<2>(it.first) ? "" : "!", en.empty() ? "" : log_signal(en)); + std::get<2>(it.first) ? "" : "!", en.empty() ? ".en=" : "", en.empty() ? "" : log_signal(en)); for (auto c : it.second) c->attributes[ID(submod)] = submod; new_submods.push_back(stringf("%s_%s", mod->name.c_str(), submod.c_str())); -- cgit v1.2.3 From 907c8aeaef4a0a06beda9126b23aae3bfcd53b65 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 23 Nov 2019 10:16:56 -0800 Subject: Escape IdStrings --- passes/hierarchy/clkpart.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index 4f4291e06..7c3e52178 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -74,13 +74,12 @@ struct ClkPartPass : public Pass { for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-set_attr" && argidx+2 < args.size()) { - attr_name = args[argidx++]; + attr_name = RTLIL::escape_id(args[argidx++]); attr_value = args[argidx++]; continue; } if (args[argidx] == "-unpart" && argidx+1 < args.size()) { - unpart_mode = true; - attr_name = args[argidx++]; + attr_name = RTLIL::escape_id(args[argidx++]); continue; } if (args[argidx] == "-enable") { -- cgit v1.2.3 From 722eeacc095106a80bfda5326416a643af02738d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 23 Nov 2019 10:17:31 -0800 Subject: Print ".en=" only if there is an enable signal --- passes/hierarchy/clkpart.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index 7c3e52178..d914bcec0 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -262,7 +262,7 @@ struct ClkPartPass : public Pass { auto en = std::get<3>(it.first); std::string submod = stringf("clk=%s%s%s%s%s", std::get<0>(it.first) ? "" : "!", clk.empty() ? "" : log_signal(clk), - std::get<2>(it.first) ? "" : "!", en.empty() ? ".en=" : "", en.empty() ? "" : log_signal(en)); + std::get<2>(it.first) ? "" : "!", en.empty() ? "" : ".en=", en.empty() ? "" : log_signal(en)); for (auto c : it.second) c->attributes[ID(submod)] = submod; new_submods.push_back(stringf("%s_%s", mod->name.c_str(), submod.c_str())); -- cgit v1.2.3 From eb11c06a69c3b50e39cf363926992b40a9c440c3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 23 Nov 2019 10:18:22 -0800 Subject: For abc9, run clkpart before ff_map and after abc9 --- techlibs/xilinx/synth_xilinx.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b5c203d1f..7105ba429 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -513,6 +513,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_ffs")) { if (abc9 || help_mode) { + run("clkpart -set_attr clkpart 1", "('-abc9' only)"); run("techmap -map " + ff_map_file, "('-abc9' only)"); } } @@ -537,6 +538,7 @@ struct SynthXilinxPass : public ScriptPass else abc9_opts += " -lut +/xilinx/abc9_xc7.lut"; run("abc9" + abc9_opts); + run("clkpart -unpart clkpart"); } else { if (nowidelut) -- cgit v1.2.3 From bf1167bc64eba873ceaf3e4a1988a216fb3909c3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 23 Nov 2019 10:26:55 -0800 Subject: Conditioning abc9 on POs not accurate due to cells --- passes/techmap/abc9.cc | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 4b6ec6e11..c2ac4ef7f 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -322,19 +322,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip fprintf(f, "%s\n", abc9_script.c_str()); fclose(f); - bool count_output = false; - for (auto port_name : module->ports) { - RTLIL::Wire *port_wire = module->wire(port_name); - log_assert(port_wire); - if (port_wire->port_output) { - count_output = true; - break; - } - } - + //bool count_output = false; log_push(); - if (count_output) + //if (count_output) { handle_loops(design, module); @@ -736,10 +727,10 @@ clone_lut: design->remove(mapped_mod); } - else - { - log("Don't call ABC as there is nothing to map.\n"); - } + //else + //{ + // log("Don't call ABC as there is nothing to map.\n"); + //} if (cleanup) { -- cgit v1.2.3 From 15aa3f460d1aa873108360df1cf2d5f22137946d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 23 Nov 2019 10:28:46 -0800 Subject: More oopsies --- passes/hierarchy/clkpart.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index d914bcec0..b79625540 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -74,12 +74,13 @@ struct ClkPartPass : public Pass { for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-set_attr" && argidx+2 < args.size()) { - attr_name = RTLIL::escape_id(args[argidx++]); + attr_name = RTLIL::escape_id(args[++argidx]); attr_value = args[argidx++]; continue; } if (args[argidx] == "-unpart" && argidx+1 < args.size()) { - attr_name = RTLIL::escape_id(args[argidx++]); + unpart_mode = true; + attr_name = RTLIL::escape_id(args[++argidx]); continue; } if (args[argidx] == "-enable") { -- cgit v1.2.3 From 63b7a48fbc250dd16847eed95d5ce79417cd7d2f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Nov 2019 12:04:11 -0800 Subject: clkpart to analyse async flops too --- passes/hierarchy/clkpart.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index b79625540..15a5328b9 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -161,6 +161,14 @@ struct ClkPartPass : public Pass { bool this_en_pol = !enable_mode || cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, enable_mode ? assign_map(cell->getPort(ID(E))) : RTLIL::SigSpec()); } + else + if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), + ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_))) + { + bool this_clk_pol = cell->type.in(ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)); + log_assert(!enable_mode); // TODO + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); + } else continue; -- cgit v1.2.3 From f50b6422b0b517dd0d9a07742f04477e2973c0f9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Nov 2019 12:35:38 -0800 Subject: abc9 to no longer to clock partitioning, operate on whole modules only --- passes/techmap/abc9.cc | 171 +++++++++---------------------------------------- 1 file changed, 32 insertions(+), 139 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index c2ac4ef7f..60fc06f6e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -752,6 +752,10 @@ struct Abc9Pass : public Pass { log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); log("library to a target architecture.\n"); log("\n"); + log("Selection must only contain fully selected modules. It is assumed that such\n"); + log("modules contain only cells belonging to the same clock domain, as produced by\n"); + log("the 'clkpart' command.\n"); + log("\n"); log(" -exe \n"); #ifdef ABCEXTERNAL log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); @@ -1082,63 +1086,44 @@ struct Abc9Pass : public Pass { continue; } - SigMap assign_map(module); - - CellTypes ct(design); - - std::vector all_cells = module->selected_cells(); - std::set unassigned_cells(all_cells.begin(), all_cells.end()); - - std::set expand_queue, next_expand_queue; - std::set expand_queue_up, next_expand_queue_up; - std::set expand_queue_down, next_expand_queue_down; - - std::map> assigned_cells; - std::map assigned_cells_reverse; + if (!design->selected_whole_module(module)) { + log("Skipping module %s as it is partially selected.\n", log_id(module)); + continue; + } - std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; - std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; + SigMap sigmap(module); typedef std::pair ctrldomain_t; std::map mergeability_class; + pool clocks; + std::string target = delay_target; - for (auto cell : all_cells) { - for (auto &conn : cell->connections()) - for (auto bit : assign_map(conn.second)) - if (bit.wire != nullptr) { - cell_to_bit[cell].insert(bit); - bit_to_cell[bit].insert(cell); - if (ct.cell_input(cell->type, conn.first)) { - cell_to_bit_up[cell].insert(bit); - bit_to_cell_down[bit].insert(cell); - } - if (ct.cell_output(cell->type, conn.first)) { - cell_to_bit_down[cell].insert(bit); - bit_to_cell_up[bit].insert(cell); - } - } - + for (auto cell : module->selected_cells()) { auto inst_module = design->module(cell->type); if (!inst_module || !inst_module->attributes.count("\\abc9_flop")) continue; - Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); - if (abc9_clock_wire == NULL) - log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - SigSpec abc9_clock = assign_map(abc9_clock_wire); + if (delay_target.empty()) { + Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); + if (abc9_clock_wire == NULL) + log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + SigBit abc9_clock = sigmap(abc9_clock_wire); + auto r = clocks.insert(abc9_clock.wire); + if (r.second) { + auto it = abc9_clock.wire->attributes.find("\\abc9_period"); + if (it != abc9_clock.wire->attributes.end()) { + int period = it->second.as_int(); + log("Identified target period = %d ps for clock %s\n", period, log_signal(abc9_clock)); + target = stringf("-D %d", period); + } + } + } + Wire *abc9_control_wire = module->wire(stringf("%s.$abc9_control", cell->name.c_str())); if (abc9_control_wire == NULL) log_error("'%s$abc9_control' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - SigSpec abc9_control = assign_map(abc9_control_wire); - - unassigned_cells.erase(cell); - expand_queue.insert(cell); - expand_queue_up.insert(cell); - expand_queue_down.insert(cell); - - assigned_cells[abc9_clock].insert(cell->name); - assigned_cells_reverse[cell] = abc9_clock; + SigSpec abc9_control = sigmap(abc9_control_wire); ctrldomain_t key(cell->type, abc9_control); auto r = mergeability_class.emplace(key, mergeability_class.size() + 1); @@ -1146,102 +1131,10 @@ struct Abc9Pass : public Pass { log_assert(r2.second); } - while (!expand_queue_up.empty() || !expand_queue_down.empty()) - { - if (!expand_queue_up.empty()) - { - RTLIL::Cell *cell = *expand_queue_up.begin(); - SigSpec key = assigned_cells_reverse.at(cell); - expand_queue_up.erase(cell); - - for (auto bit : cell_to_bit_up[cell]) - for (auto c : bit_to_cell_up[bit]) - if (unassigned_cells.count(c) && !c->type.in("$__ABC9_FF_", "$__ABC9_ASYNC_")) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].insert(c->name); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (!expand_queue_down.empty()) - { - RTLIL::Cell *cell = *expand_queue_down.begin(); - SigSpec key = assigned_cells_reverse.at(cell); - expand_queue_down.erase(cell); - - for (auto bit : cell_to_bit_down[cell]) - for (auto c : bit_to_cell_down[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].insert(c->name); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (expand_queue_up.empty() && expand_queue_down.empty()) { - expand_queue_up.swap(next_expand_queue_up); - expand_queue_down.swap(next_expand_queue_down); - } - } - - while (!expand_queue.empty()) - { - RTLIL::Cell *cell = *expand_queue.begin(); - SigSpec key = assigned_cells_reverse.at(cell); - expand_queue.erase(cell); - - for (auto bit : cell_to_bit.at(cell)) { - for (auto c : bit_to_cell[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue.insert(c); - assigned_cells[key].insert(c->name); - assigned_cells_reverse[c] = key; - } - bit_to_cell[bit].clear(); - } - - if (expand_queue.empty()) - expand_queue.swap(next_expand_queue); - } - - SigSpec key; - for (auto cell : unassigned_cells) { - assigned_cells[key].insert(cell->name); - assigned_cells_reverse[cell] = key; - } - - log_header(design, "Summary of detected clock domains:\n"); - for (auto &it : assigned_cells) - log(" %d cells in clk=%s\n", GetSize(it.second), log_signal(it.first)); - - design->selection_stack.emplace_back(false); design->selected_active_module = module->name.str(); - for (auto &it : assigned_cells) { - std::string target = delay_target; - if (target.empty()) { - for (auto b : assign_map(it.first)) - if (b.wire) { - auto jt = b.wire->attributes.find("\\abc9_period"); - if (jt != b.wire->attributes.end()) { - target = stringf("-D %d", jt->second.as_int()); - log("Target period = %s ps for clock domain %s\n", target.c_str(), log_signal(it.first)); - break; - } - } - } - RTLIL::Selection& sel = design->selection_stack.back(); - sel.selected_members[module->name] = std::move(it.second); - abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, false, "$", - keepff, target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay, box_lookup, nomfs); - assign_map.set(module); - } - design->selection_stack.pop_back(); + abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, false, "$", + keepff, target, lutin_shared, fast_mode, show_tempdir, + box_file, lut_file, wire_delay, box_lookup, nomfs); design->selected_active_module.clear(); } -- cgit v1.2.3 From 180cb3939546f68eca878a8427a043eb1169094c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Nov 2019 12:35:57 -0800 Subject: abc9 to contain time call --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 60fc06f6e..2409f3d91 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -30,7 +30,7 @@ "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ "&mfs; &ps -l" #else -#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l; time" #endif -- cgit v1.2.3 From 6a2eb5d8f9286b9574647c03e2bdc8b63fccbe4d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Nov 2019 12:36:13 -0800 Subject: Special abc9_clock wire to contain only clock signal --- techlibs/xilinx/abc9_map.v | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 9913b229f..29ddf7133 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -62,10 +62,8 @@ // The purpose of the following FD* rules are to wrap the flop with: // (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 // the connectivity of its basic D-Q flop -// (b) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock -// domain (used when partitioning the module so that `abc9' only -// performs sequential synthesis (with reachability analysis) correctly on -// one domain at a time) +// (b) a special _TECHMAP_REPLACE_.$abc9_clock wire to indicate its clock +// signal, used to extract the delay target // (c) a special _TECHMAP_REPLACE_.$abc9_control that captures the control // domain (which, combined with this cell type, encodes to `abc9' which // flops may be merged together) @@ -88,7 +86,7 @@ module FDRE (output reg Q, input C, CE, D, R); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule @@ -103,7 +101,7 @@ module FDRE_1 (output reg Q, input C, CE, D, R); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule @@ -133,7 +131,7 @@ module FDCE (output reg Q, input C, CE, D, CLR); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -154,7 +152,7 @@ module FDCE_1 (output reg Q, input C, CE, D, CLR); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(Q)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -182,7 +180,7 @@ module FDPE (output reg Q, input C, CE, D, PRE); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -203,7 +201,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(Q)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -225,7 +223,7 @@ module FDSE (output reg Q, input C, CE, D, S); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule @@ -240,7 +238,7 @@ module FDSE_1 (output reg Q, input C, CE, D, S); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule -- cgit v1.2.3 From 6831510f5b436ddf05b8a1cb30b52be67f865de0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Nov 2019 12:59:34 -0800 Subject: Fix debug --- passes/techmap/abc9.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2409f3d91..193103747 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -347,10 +347,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip log_assert(!design->module(ID($__abc9__))); { AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); - reader.parse_xaiger(); + reader.parse_xaiger(box_lookup); } ifs.close(); - Pass::call(design, stringf("write_verilog -noexpr -norename")); + Pass::call_on_module(design, design->module(ID($__abc9__)), stringf("write_verilog -noexpr -norename -selected")); design->remove(design->module(ID($__abc9__))); #endif @@ -421,7 +421,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip ifs.close(); #if 0 - Pass::call(design, stringf("write_verilog -noexpr -norename")); + Pass::call_on_module(design, design->module(ID($__abc9__)), stringf("write_verilog -noexpr -norename -selected")); #endif log_header(design, "Re-integrating ABC9 results.\n"); -- cgit v1.2.3 From 67be62a957c565bfa03f084c8f110d65ca14196b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Nov 2019 12:04:11 -0800 Subject: clkpart to analyse async flops too --- passes/hierarchy/clkpart.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index b79625540..15a5328b9 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -161,6 +161,14 @@ struct ClkPartPass : public Pass { bool this_en_pol = !enable_mode || cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, enable_mode ? assign_map(cell->getPort(ID(E))) : RTLIL::SigSpec()); } + else + if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), + ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_))) + { + bool this_clk_pol = cell->type.in(ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)); + log_assert(!enable_mode); // TODO + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); + } else continue; -- 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(-) 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(-) 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 dd317c92808a73e61e771a123fc4377d3fb78af2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Nov 2019 16:07:35 -0800 Subject: Add testcase where \init is copied --- tests/various/submod.ys | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/various/submod.ys b/tests/various/submod.ys index 7c6f555ac..f50556d76 100644 --- a/tests/various/submod.ys +++ b/tests/various/submod.ys @@ -48,3 +48,21 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter + + +design -reset +read_verilog -icells < Date: Mon, 25 Nov 2019 16:07:47 -0800 Subject: Move \init from source wire to submod if output port --- passes/hierarchy/submod.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 212932e46..7952c2dd6 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -162,6 +162,13 @@ struct SubmodWorker new_wire->port_input = new_wire_port_input; new_wire->port_output = new_wire_port_output; new_wire->attributes = wire->attributes; + if (new_wire->port_output) { + auto it = wire->attributes.find(ID(init)); + if (it != wire->attributes.end()) { + new_wire->attributes[ID(init)] = it->second[bit.offset]; + it->second[bit.offset] = State::Sx; + } + } if (new_wire->port_input && new_wire->port_output) log(" signal %s: inout %s\n", wire->name.c_str(), new_wire->name.c_str()); -- cgit v1.2.3 From eb666b46777877bfd723b7dc7fb36e717b66bfdd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Nov 2019 11:12:58 -0800 Subject: Update docs with bullet points --- passes/hierarchy/submod.cc | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 7952c2dd6..ae80f09a8 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -296,7 +296,7 @@ struct SubmodPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" submod [-copy] [selection]\n"); + log(" submod [options] [selection]\n"); log("\n"); log("This pass identifies all cells with the 'submod' attribute and moves them to\n"); log("a newly created module. The value of the attribute is used as name for the\n"); @@ -308,16 +308,15 @@ struct SubmodPass : public Pass { log("This pass only operates on completely selected modules with no processes\n"); log("or memories.\n"); log("\n"); + log(" -copy\n"); + log(" by default the cells are 'moved' from the source module and the source\n"); + log(" module will use an instance of the new module after this command is\n"); + log(" finished. call with -copy to not modify the source module.\n"); log("\n"); - log(" submod -name [-copy] [selection]\n"); - log("\n"); - log("As above, but don't use the 'submod' attribute but instead use the selection.\n"); - log("Only objects from one module might be selected. The value of the -name option\n"); - log("is used as the value of the 'submod' attribute above.\n"); - log("\n"); - log("By default the cells are 'moved' from the source module and the source module\n"); - log("will use an instance of the new module after this command is finished. Call\n"); - log("with -copy to not modify the source module.\n"); + log(" -name \n"); + log(" don't use the 'submod' attribute but instead use the selection. only\n"); + log(" objects from one module might be selected. the value of the -name option\n"); + log(" is used as the value of the 'submod' attribute instead.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE -- cgit v1.2.3 From e8aa92ca35f63612133def8b823ef17f396f0c0c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Nov 2019 11:35:15 -0800 Subject: Add -hidden option to submod --- passes/hierarchy/submod.cc | 60 ++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 212932e46..118a65301 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -37,6 +37,7 @@ struct SubmodWorker pool outputs; bool copy_mode; + bool hidden_mode; std::string opt_name; struct SubModule @@ -149,19 +150,29 @@ struct SubmodWorker else new_wire_name = stringf("%s[%d]", wire->name.c_str(), bit.offset); if (new_wire_port_input || new_wire_port_output) { - while (new_wire_name[0] == '$') { - std::string next_wire_name = stringf("\\n%d", auto_name_counter++); - if (all_wire_names.count(next_wire_name) == 0) { - all_wire_names.insert(next_wire_name); - new_wire_name = next_wire_name; - } - } + if (new_wire_name[0] == '$') + do { + std::string next_wire_name = stringf("%s\\n%d", hidden_mode ? "$submod" : ":", auto_name_counter++); + if (all_wire_names.count(next_wire_name) == 0) { + all_wire_names.insert(next_wire_name); + new_wire_name = next_wire_name; + } + } while (new_wire_name[0] == '$'); + else + new_wire_name = stringf("$submod%s\n", new_wire_name.c_str()); } RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name); new_wire->port_input = new_wire_port_input; new_wire->port_output = new_wire_port_output; new_wire->attributes = wire->attributes; + if (new_wire->port_output) { + auto it = wire->attributes.find(ID(init)); + if (it != wire->attributes.end()) { + new_wire->attributes[ID(init)] = it->second[bit.offset]; + it->second[bit.offset] = State::Sx; + } + } if (new_wire->port_input && new_wire->port_output) log(" signal %s: inout %s\n", wire->name.c_str(), new_wire->name.c_str()); @@ -204,8 +215,8 @@ struct SubmodWorker } } - SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, std::string opt_name = std::string()) : - design(design), module(module), sigmap(module), copy_mode(copy_mode), opt_name(opt_name) + SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, bool hidden_mode = false, std::string opt_name = std::string()) : + design(design), module(module), sigmap(module), copy_mode(copy_mode), hidden_mode(hidden_mode), opt_name(opt_name) { if (!design->selected_whole_module(module->name) && opt_name.empty()) return; @@ -289,7 +300,7 @@ struct SubmodPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" submod [-copy] [selection]\n"); + log(" submod [options] [selection]\n"); log("\n"); log("This pass identifies all cells with the 'submod' attribute and moves them to\n"); log("a newly created module. The value of the attribute is used as name for the\n"); @@ -301,16 +312,20 @@ struct SubmodPass : public Pass { log("This pass only operates on completely selected modules with no processes\n"); log("or memories.\n"); log("\n"); + log(" -copy\n"); + log(" by default the cells are 'moved' from the source module and the source\n"); + log(" module will use an instance of the new module after this command is\n"); + log(" finished. call with -copy to not modify the source module.\n"); log("\n"); - log(" submod -name [-copy] [selection]\n"); + log(" -name \n"); + log(" don't use the 'submod' attribute but instead use the selection. only\n"); + log(" objects from one module might be selected. the value of the -name option\n"); + log(" is used as the value of the 'submod' attribute instead.\n"); log("\n"); - log("As above, but don't use the 'submod' attribute but instead use the selection.\n"); - log("Only objects from one module might be selected. The value of the -name option\n"); - log("is used as the value of the 'submod' attribute above.\n"); - log("\n"); - log("By default the cells are 'moved' from the source module and the source module\n"); - log("will use an instance of the new module after this command is finished. Call\n"); - log("with -copy to not modify the source module.\n"); + log(" -hidden\n"); + log(" instead of creating submodule ports with public names, create ports with\n"); + log(" private names so that a subsequent 'flatten; clean' call will restore the\n"); + log(" original module with original public names.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -320,6 +335,7 @@ struct SubmodPass : public Pass { std::string opt_name; bool copy_mode = false; + bool hidden_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -331,6 +347,10 @@ struct SubmodPass : public Pass { copy_mode = true; continue; } + if (args[argidx] == "-hidden") { + hidden_mode = true; + continue; + } break; } extra_args(args, argidx, design); @@ -351,7 +371,7 @@ struct SubmodPass : public Pass { queued_modules.push_back(mod_it.first); for (auto &modname : queued_modules) if (design->modules_.count(modname) != 0) { - SubmodWorker worker(design, design->modules_[modname], copy_mode); + SubmodWorker worker(design, design->modules_[modname], copy_mode, hidden_mode); handled_modules.insert(modname); did_something = true; } @@ -374,7 +394,7 @@ struct SubmodPass : public Pass { else { Pass::call_on_module(design, module, "opt_clean"); log_header(design, "Continuing SUBMOD pass.\n"); - SubmodWorker worker(design, module, copy_mode, opt_name); + SubmodWorker worker(design, module, copy_mode, hidden_mode, opt_name); } } -- cgit v1.2.3 From 3027f015c2f4dc91650af0dba224585a1a9d0b9f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Nov 2019 11:35:32 -0800 Subject: clkpart to use 'submod -hidden' --- passes/hierarchy/clkpart.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index 15a5328b9..81983e226 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -278,7 +278,7 @@ struct ClkPartPass : public Pass { } } - Pass::call(design, "submod"); + Pass::call(design, "submod -hidden"); if (!attr_name.empty()) for (auto m : new_submods) -- cgit v1.2.3 From 09637dd3e454784cba695496fc94be313e4d8522 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Nov 2019 11:57:26 -0800 Subject: Fix submod -hidden --- passes/hierarchy/submod.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 118a65301..14974666e 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -151,15 +151,16 @@ struct SubmodWorker new_wire_name = stringf("%s[%d]", wire->name.c_str(), bit.offset); if (new_wire_port_input || new_wire_port_output) { if (new_wire_name[0] == '$') - do { - std::string next_wire_name = stringf("%s\\n%d", hidden_mode ? "$submod" : ":", auto_name_counter++); + while (1) { + std::string next_wire_name = stringf("%s\\n%d", hidden_mode ? "$submod" : "", auto_name_counter++); if (all_wire_names.count(next_wire_name) == 0) { all_wire_names.insert(next_wire_name); new_wire_name = next_wire_name; + break; } - } while (new_wire_name[0] == '$'); - else - new_wire_name = stringf("$submod%s\n", new_wire_name.c_str()); + } + else if (hidden_mode) + new_wire_name = stringf("$submod%s", new_wire_name.c_str()); } RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name); -- cgit v1.2.3 From 739f5309062f6e60809a2ebe4eda4602cca6fc41 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Nov 2019 14:51:39 -0800 Subject: Move 'clean' from map_luts to finalize --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7105ba429..6e8ced0df 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -560,7 +560,6 @@ struct SynthXilinxPass : public ScriptPass else techmap_args += " -map " + ff_map_file; run("techmap " + techmap_args); - run("clean"); } if (check_label("finalize")) { @@ -575,6 +574,7 @@ struct SynthXilinxPass : public ScriptPass run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I A:top", "(only if '-iopad' or '-ise' and not '-noiopad')"); if (help_mode || ise) run("extractinv -inv INV O:I", "(only if '-ise')"); + run("clean"); } if (check_label("check")) { -- 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(-) 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 435d33c37307563f193b8c798ad46ebb19cf4f07 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Nov 2019 11:35:15 -0800 Subject: Add -hidden option to submod --- passes/hierarchy/submod.cc | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index ae80f09a8..118a65301 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -37,6 +37,7 @@ struct SubmodWorker pool outputs; bool copy_mode; + bool hidden_mode; std::string opt_name; struct SubModule @@ -149,13 +150,16 @@ struct SubmodWorker else new_wire_name = stringf("%s[%d]", wire->name.c_str(), bit.offset); if (new_wire_port_input || new_wire_port_output) { - while (new_wire_name[0] == '$') { - std::string next_wire_name = stringf("\\n%d", auto_name_counter++); - if (all_wire_names.count(next_wire_name) == 0) { - all_wire_names.insert(next_wire_name); - new_wire_name = next_wire_name; - } - } + if (new_wire_name[0] == '$') + do { + std::string next_wire_name = stringf("%s\\n%d", hidden_mode ? "$submod" : ":", auto_name_counter++); + if (all_wire_names.count(next_wire_name) == 0) { + all_wire_names.insert(next_wire_name); + new_wire_name = next_wire_name; + } + } while (new_wire_name[0] == '$'); + else + new_wire_name = stringf("$submod%s\n", new_wire_name.c_str()); } RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name); @@ -211,8 +215,8 @@ struct SubmodWorker } } - SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, std::string opt_name = std::string()) : - design(design), module(module), sigmap(module), copy_mode(copy_mode), opt_name(opt_name) + SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, bool hidden_mode = false, std::string opt_name = std::string()) : + design(design), module(module), sigmap(module), copy_mode(copy_mode), hidden_mode(hidden_mode), opt_name(opt_name) { if (!design->selected_whole_module(module->name) && opt_name.empty()) return; @@ -318,6 +322,11 @@ struct SubmodPass : public Pass { log(" objects from one module might be selected. the value of the -name option\n"); log(" is used as the value of the 'submod' attribute instead.\n"); log("\n"); + log(" -hidden\n"); + log(" instead of creating submodule ports with public names, create ports with\n"); + log(" private names so that a subsequent 'flatten; clean' call will restore the\n"); + log(" original module with original public names.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { @@ -326,6 +335,7 @@ struct SubmodPass : public Pass { std::string opt_name; bool copy_mode = false; + bool hidden_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -337,6 +347,10 @@ struct SubmodPass : public Pass { copy_mode = true; continue; } + if (args[argidx] == "-hidden") { + hidden_mode = true; + continue; + } break; } extra_args(args, argidx, design); @@ -357,7 +371,7 @@ struct SubmodPass : public Pass { queued_modules.push_back(mod_it.first); for (auto &modname : queued_modules) if (design->modules_.count(modname) != 0) { - SubmodWorker worker(design, design->modules_[modname], copy_mode); + SubmodWorker worker(design, design->modules_[modname], copy_mode, hidden_mode); handled_modules.insert(modname); did_something = true; } @@ -380,7 +394,7 @@ struct SubmodPass : public Pass { else { Pass::call_on_module(design, module, "opt_clean"); log_header(design, "Continuing SUBMOD pass.\n"); - SubmodWorker worker(design, module, copy_mode, opt_name); + SubmodWorker worker(design, module, copy_mode, hidden_mode, opt_name); } } -- cgit v1.2.3 From 5e487b103c3c1ed9f1fcaca21821466628b7ff80 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Nov 2019 11:57:26 -0800 Subject: Fix submod -hidden --- passes/hierarchy/submod.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 118a65301..14974666e 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -151,15 +151,16 @@ struct SubmodWorker new_wire_name = stringf("%s[%d]", wire->name.c_str(), bit.offset); if (new_wire_port_input || new_wire_port_output) { if (new_wire_name[0] == '$') - do { - std::string next_wire_name = stringf("%s\\n%d", hidden_mode ? "$submod" : ":", auto_name_counter++); + while (1) { + std::string next_wire_name = stringf("%s\\n%d", hidden_mode ? "$submod" : "", auto_name_counter++); if (all_wire_names.count(next_wire_name) == 0) { all_wire_names.insert(next_wire_name); new_wire_name = next_wire_name; + break; } - } while (new_wire_name[0] == '$'); - else - new_wire_name = stringf("$submod%s\n", new_wire_name.c_str()); + } + else if (hidden_mode) + new_wire_name = stringf("$submod%s", new_wire_name.c_str()); } RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name); -- cgit v1.2.3 From 6318e3ce6df2484c4cc17856608e2a6354cd643a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Nov 2019 23:38:49 -0800 Subject: Fix wire width --- tests/various/submod.ys | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/various/submod.ys b/tests/various/submod.ys index f50556d76..a0a3f2da5 100644 --- a/tests/various/submod.ys +++ b/tests/various/submod.ys @@ -1,8 +1,8 @@ read_verilog < Date: Tue, 26 Nov 2019 23:39:14 -0800 Subject: Promote output wires in sigmap so that can be detected --- passes/hierarchy/submod.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 14974666e..f23dfb702 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -34,7 +34,6 @@ struct SubmodWorker RTLIL::Design *design; RTLIL::Module *module; SigMap sigmap; - pool outputs; bool copy_mode; bool hidden_mode; @@ -124,13 +123,13 @@ struct SubmodWorker for (auto &it : bit_flags) { - const RTLIL::SigBit &bit = it.first; + const RTLIL::SigBit &bit = sigmap(it.first); RTLIL::Wire *wire = bit.wire; bit_flags_t &flags = it.second; if (wire->port_input) flags.is_ext_driven = true; - if (outputs.count(bit)) + if (wire->port_output) flags.is_ext_used = true; bool new_wire_port_input = false; @@ -240,11 +239,8 @@ struct SubmodWorker for (auto port : module->ports) { auto wire = module->wire(port); - if (!wire->port_output) - continue; - for (auto b : sigmap(wire)) - if (b.wire) - outputs.insert(b); + if (wire->port_output) + sigmap.add(wire); } if (opt_name.empty()) -- cgit v1.2.3 From 8c813632b6c1557f5123ea0cece2738fad40b89b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 27 Nov 2019 00:48:22 -0800 Subject: Revert "submod to bitty rather bussy, for bussy wires used as input and output" This reverts commit cba3073026711e7683c46ba091c56a5c5a041a45. --- passes/hierarchy/submod.cc | 111 +++++++++++++++++++++++++++++---------------- tests/various/submod.ys | 7 ++- 2 files changed, 76 insertions(+), 42 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index f23dfb702..238e1f43f 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -34,6 +34,7 @@ struct SubmodWorker RTLIL::Design *design; RTLIL::Module *module; SigMap sigmap; + std::map replace_const; bool copy_mode; bool hidden_mode; @@ -47,44 +48,51 @@ struct SubmodWorker std::map submodules; - struct bit_flags_t { + struct wire_flags_t { RTLIL::Wire *new_wire; - bool is_int_driven, is_int_used, is_ext_driven, is_ext_used; - bit_flags_t() : new_wire(NULL), is_int_driven(false), is_int_used(false), is_ext_driven(false), is_ext_used(false) { } + RTLIL::Const is_int_driven; + bool is_int_used, is_ext_driven, is_ext_used; + wire_flags_t(RTLIL::Wire* wire) : new_wire(NULL), is_int_driven(State::S0, GetSize(wire)), is_int_used(false), is_ext_driven(false), is_ext_used(false) { } }; - std::map bit_flags; + std::map wire_flags; bool flag_found_something; - void flag_bit(RTLIL::SigBit bit, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used) + void flag_wire(RTLIL::Wire *wire, bool create, bool /*set_int_driven*/, bool set_int_used, bool set_ext_driven, bool set_ext_used) { - if (bit_flags.count(bit) == 0) { + if (wire_flags.count(wire) == 0) { if (!create) return; - bit_flags[bit] = bit_flags_t(); + wire_flags.emplace(wire, wire_flags_t(wire)); } - if (set_int_driven) - bit_flags[bit].is_int_driven = true; + //if (set_int_driven) + // wire_flags[wire].is_int_driven = true; if (set_int_used) - bit_flags[bit].is_int_used = true; + wire_flags.at(wire).is_int_used = true; if (set_ext_driven) - bit_flags[bit].is_ext_driven = true; + wire_flags.at(wire).is_ext_driven = true; if (set_ext_used) - bit_flags[bit].is_ext_used = true; + wire_flags.at(wire).is_ext_used = true; flag_found_something = true; } void flag_signal(const RTLIL::SigSpec &sig, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used) { - for (auto &b : sig) - if (b.wire != NULL) - flag_bit(b, create, set_int_driven, set_int_used, set_ext_driven, set_ext_used); + for (auto &c : sig.chunks()) + if (c.wire != NULL) { + flag_wire(c.wire, create, set_int_driven, set_int_used, set_ext_driven, set_ext_used); + if (set_int_driven) + for (int i = c.offset; i < c.offset+c.width; i++) { + wire_flags.at(c.wire).is_int_driven[i] = State::S1; + flag_found_something = true; + } + } } void handle_submodule(SubModule &submod) { log("Creating submodule %s (%s) of module %s.\n", submod.name.c_str(), submod.full_name.c_str(), module->name.c_str()); - bit_flags.clear(); + wire_flags.clear(); for (RTLIL::Cell *cell : submod.cells) { if (ct.cell_known(cell->type)) { for (auto &conn : cell->connections()) @@ -117,37 +125,40 @@ struct SubmodWorker int auto_name_counter = 1; std::set all_wire_names; - for (auto &it : bit_flags) { - all_wire_names.insert(it.first.wire->name); + for (auto &it : wire_flags) { + all_wire_names.insert(it.first->name); } - for (auto &it : bit_flags) + for (auto &it : wire_flags) { - const RTLIL::SigBit &bit = sigmap(it.first); - RTLIL::Wire *wire = bit.wire; - bit_flags_t &flags = it.second; + RTLIL::Wire *wire = it.first; + wire_flags_t &flags = it.second; if (wire->port_input) flags.is_ext_driven = true; if (wire->port_output) flags.is_ext_used = true; + else { + auto sig = sigmap(wire); + for (auto c : sig.chunks()) + if (c.wire->port_output) { + flags.is_ext_used = true; + break; + } + } bool new_wire_port_input = false; bool new_wire_port_output = false; - if (flags.is_int_driven && flags.is_ext_used) + if (!flags.is_int_driven.is_fully_zero() && flags.is_ext_used) new_wire_port_output = true; if (flags.is_ext_driven && flags.is_int_used) new_wire_port_input = true; - if (flags.is_int_driven && flags.is_ext_driven) + if (!flags.is_int_driven.is_fully_zero() && flags.is_ext_driven) new_wire_port_input = true, new_wire_port_output = true; - RTLIL::IdString new_wire_name; - if (GetSize(wire) == 1) - new_wire_name = wire->name; - else - new_wire_name = stringf("%s[%d]", wire->name.c_str(), bit.offset); + std::string new_wire_name = wire->name.str(); if (new_wire_port_input || new_wire_port_output) { if (new_wire_name[0] == '$') while (1) { @@ -162,15 +173,26 @@ struct SubmodWorker new_wire_name = stringf("$submod%s", new_wire_name.c_str()); } - RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name); + RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name, wire->width); new_wire->port_input = new_wire_port_input; new_wire->port_output = new_wire_port_output; + new_wire->start_offset = wire->start_offset; new_wire->attributes = wire->attributes; if (new_wire->port_output) { - auto it = wire->attributes.find(ID(init)); - if (it != wire->attributes.end()) { - new_wire->attributes[ID(init)] = it->second[bit.offset]; - it->second[bit.offset] = State::Sx; + new_wire->attributes.erase(ID(init)); + auto sig = sigmap(wire); + for (int i = 0; i < GetSize(sig); i++) { + if (flags.is_int_driven[i] == State::S0) + continue; + log_dump(i, flags.is_int_driven[i]); + if (!sig[i].wire) + continue; + auto it = sig[i].wire->attributes.find(ID(init)); + if (it != sig[i].wire->attributes.end()) { + auto jt = new_wire->attributes.insert(std::make_pair(ID(init), Const(State::Sx, GetSize(sig)))).first; + jt->second[i] = it->second[sig[i].offset]; + it->second[sig[i].offset] = State::Sx; + } } } @@ -194,8 +216,8 @@ struct SubmodWorker for (auto &conn : new_cell->connections_) for (auto &bit : conn.second) if (bit.wire != NULL) { - log_assert(bit_flags.count(bit) > 0); - bit = bit_flags[bit].new_wire; + log_assert(wire_flags.count(bit.wire) > 0); + bit.wire = wire_flags.at(bit.wire).new_wire; } log(" cell %s (%s)\n", new_cell->name.c_str(), new_cell->type.c_str()); if (!copy_mode) @@ -205,12 +227,16 @@ struct SubmodWorker if (!copy_mode) { RTLIL::Cell *new_cell = module->addCell(submod.full_name, submod.full_name); - for (auto &it : bit_flags) + for (auto &it : wire_flags) { - RTLIL::SigBit old_bit = it.first; + RTLIL::SigSpec old_sig = sigmap(it.first); RTLIL::Wire *new_wire = it.second.new_wire; - if (new_wire->port_id > 0) - new_cell->setPort(new_wire->name, old_bit); + if (new_wire->port_id > 0) { + // Prevents "ERROR: Mismatch in directionality ..." when flattening + if (new_wire->port_output) + old_sig.replace(replace_const); + new_cell->setPort(new_wire->name, old_sig); + } } } } @@ -242,6 +268,11 @@ struct SubmodWorker if (wire->port_output) sigmap.add(wire); } + auto wire = module->addWire(NEW_ID); + replace_const.emplace(State::S0, wire); + replace_const.emplace(State::S1, wire); + replace_const.emplace(State::Sx, wire); + replace_const.emplace(State::Sz, wire); if (opt_name.empty()) { diff --git a/tests/various/submod.ys b/tests/various/submod.ys index a0a3f2da5..552fd4e01 100644 --- a/tests/various/submod.ys +++ b/tests/various/submod.ys @@ -52,8 +52,10 @@ sat -verify -prove-asserts -show-ports miter design -reset read_verilog -icells < Date: Wed, 27 Nov 2019 00:50:25 -0800 Subject: Stray log_dump --- passes/hierarchy/submod.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 238e1f43f..349483778 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -184,7 +184,6 @@ struct SubmodWorker for (int i = 0; i < GetSize(sig); i++) { if (flags.is_int_driven[i] == State::S0) continue; - log_dump(i, flags.is_int_driven[i]); if (!sig[i].wire) continue; auto it = sig[i].wire->attributes.find(ID(init)); -- cgit v1.2.3 From cb05fe0f70039077bdc1c72f0e2121be6eb7835b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 27 Nov 2019 00:51:39 -0800 Subject: Check for nullptr --- passes/hierarchy/submod.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 349483778..7b5e110cb 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -141,7 +141,7 @@ struct SubmodWorker else { auto sig = sigmap(wire); for (auto c : sig.chunks()) - if (c.wire->port_output) { + if (c.wire && c.wire->port_output) { flags.is_ext_used = true; break; } -- cgit v1.2.3 From c7aa2c6b79243201d076b6e71a461865610c9e8b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 27 Nov 2019 01:01:24 -0800 Subject: Cleanup --- passes/hierarchy/submod.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 7b5e110cb..cf27d2358 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -57,15 +57,13 @@ struct SubmodWorker std::map wire_flags; bool flag_found_something; - void flag_wire(RTLIL::Wire *wire, bool create, bool /*set_int_driven*/, bool set_int_used, bool set_ext_driven, bool set_ext_used) + void flag_wire(RTLIL::Wire *wire, bool create, bool set_int_used, bool set_ext_driven, bool set_ext_used) { if (wire_flags.count(wire) == 0) { if (!create) return; - wire_flags.emplace(wire, wire_flags_t(wire)); + wire_flags.emplace(wire, wire); } - //if (set_int_driven) - // wire_flags[wire].is_int_driven = true; if (set_int_used) wire_flags.at(wire).is_int_used = true; if (set_ext_driven) @@ -79,7 +77,7 @@ struct SubmodWorker { for (auto &c : sig.chunks()) if (c.wire != NULL) { - flag_wire(c.wire, create, set_int_driven, set_int_used, set_ext_driven, set_ext_used); + flag_wire(c.wire, create, set_int_used, set_ext_driven, set_ext_used); if (set_int_driven) for (int i = c.offset; i < c.offset+c.width; i++) { wire_flags.at(c.wire).is_int_driven[i] = State::S1; -- cgit v1.2.3 From 1c0ee4f786a77d8557c9dd462abc54982b7b639d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 27 Nov 2019 08:18:41 -0800 Subject: Do not replace constants with same wire --- passes/hierarchy/submod.cc | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index cf27d2358..b21b0de01 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -34,7 +34,6 @@ struct SubmodWorker RTLIL::Design *design; RTLIL::Module *module; SigMap sigmap; - std::map replace_const; bool copy_mode; bool hidden_mode; @@ -231,7 +230,9 @@ struct SubmodWorker if (new_wire->port_id > 0) { // Prevents "ERROR: Mismatch in directionality ..." when flattening if (new_wire->port_output) - old_sig.replace(replace_const); + for (auto &b : old_sig) + if (!b.wire) + b = module->addWire(NEW_ID); new_cell->setPort(new_wire->name, old_sig); } } @@ -265,11 +266,6 @@ struct SubmodWorker if (wire->port_output) sigmap.add(wire); } - auto wire = module->addWire(NEW_ID); - replace_const.emplace(State::S0, wire); - replace_const.emplace(State::S1, wire); - replace_const.emplace(State::Sx, wire); - replace_const.emplace(State::Sz, wire); if (opt_name.empty()) { -- cgit v1.2.3 From df8dc6d1fb1f9fc47a8356b5f0bf572a1ea140d2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 27 Nov 2019 09:10:34 -0800 Subject: ean call after abc{,9} --- techlibs/xilinx/synth_xilinx.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 6e8ced0df..5bc55387b 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -538,6 +538,7 @@ struct SynthXilinxPass : public ScriptPass else abc9_opts += " -lut +/xilinx/abc9_xc7.lut"; run("abc9" + abc9_opts); + run("clean"); run("clkpart -unpart clkpart"); } else { @@ -545,8 +546,8 @@ struct SynthXilinxPass : public ScriptPass run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : "")); else run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + run("clean"); } - run("clean"); // This shregmap call infers fixed length shift registers after abc // has performed any necessary retiming -- 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(-) 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(-) 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 ac5b5e97bcd56a539a02344584011dd985f13f06 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 27 Nov 2019 13:21:59 -0800 Subject: Fix multiple driver issue --- passes/hierarchy/submod.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index b21b0de01..839f8561c 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -228,11 +228,16 @@ struct SubmodWorker RTLIL::SigSpec old_sig = sigmap(it.first); RTLIL::Wire *new_wire = it.second.new_wire; if (new_wire->port_id > 0) { - // Prevents "ERROR: Mismatch in directionality ..." when flattening if (new_wire->port_output) - for (auto &b : old_sig) + for (int i = 0; i < GetSize(old_sig); i++) { + auto &b = old_sig[i]; + // Prevents "ERROR: Mismatch in directionality ..." when flattening if (!b.wire) b = module->addWire(NEW_ID); + // Prevents "Warning: multiple conflicting drivers ..." + else if (!it.second.is_int_driven[i]) + b = module->addWire(NEW_ID); + } new_cell->setPort(new_wire->name, old_sig); } } -- cgit v1.2.3 From ff1e35768224a7824ec9838ca84d27bbb4a14676 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 27 Nov 2019 13:22:26 -0800 Subject: Add multiple driver testcase --- tests/various/submod.ys | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/various/submod.ys b/tests/various/submod.ys index 552fd4e01..9d7dabdd7 100644 --- a/tests/various/submod.ys +++ b/tests/various/submod.ys @@ -15,6 +15,7 @@ proc design -save gold submod +check -assert design -stash gate design -import gold -as gold @@ -41,6 +42,7 @@ proc design -save gold submod +check -assert top design -stash gate design -import gold -as gold @@ -50,6 +52,35 @@ miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter +design -reset +read_verilog < Date: Wed, 27 Nov 2019 13:21:59 -0800 Subject: Fix multiple driver issue --- passes/hierarchy/submod.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index b21b0de01..839f8561c 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -228,11 +228,16 @@ struct SubmodWorker RTLIL::SigSpec old_sig = sigmap(it.first); RTLIL::Wire *new_wire = it.second.new_wire; if (new_wire->port_id > 0) { - // Prevents "ERROR: Mismatch in directionality ..." when flattening if (new_wire->port_output) - for (auto &b : old_sig) + for (int i = 0; i < GetSize(old_sig); i++) { + auto &b = old_sig[i]; + // Prevents "ERROR: Mismatch in directionality ..." when flattening if (!b.wire) b = module->addWire(NEW_ID); + // Prevents "Warning: multiple conflicting drivers ..." + else if (!it.second.is_int_driven[i]) + b = module->addWire(NEW_ID); + } new_cell->setPort(new_wire->name, old_sig); } } -- cgit v1.2.3 From b3a66dff7cac8ee98a9b26463e8858a38ea57f83 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Nov 2019 12:57:36 -0800 Subject: Move \init signal for non-port signals as long as internally driven --- passes/hierarchy/submod.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 839f8561c..211f96175 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -175,7 +175,7 @@ struct SubmodWorker new_wire->port_output = new_wire_port_output; new_wire->start_offset = wire->start_offset; new_wire->attributes = wire->attributes; - if (new_wire->port_output) { + if (!flags.is_int_driven.is_fully_zero()) { new_wire->attributes.erase(ID(init)); auto sig = sigmap(wire); for (int i = 0; i < GetSize(sig); i++) { -- cgit v1.2.3 From b1ab7c16c41f0a14b8b14a041367f2259b3c0e37 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Nov 2019 12:59:43 -0800 Subject: clkpart -unpart into 'finalize' --- techlibs/xilinx/synth_xilinx.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 5bc55387b..554c42d68 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -538,16 +538,14 @@ struct SynthXilinxPass : public ScriptPass else abc9_opts += " -lut +/xilinx/abc9_xc7.lut"; run("abc9" + abc9_opts); - run("clean"); - run("clkpart -unpart clkpart"); } else { if (nowidelut) run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : "")); else run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); - run("clean"); } + run("clean"); // This shregmap call infers fixed length shift registers after abc // has performed any necessary retiming @@ -564,6 +562,9 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("finalize")) { + if (help_mode || abc9) + run("clkpart -unpart clkpart", "(only if 'abc9')"); + bool do_iopad = iopad || (ise && !noiopad); if (help_mode || !noclkbuf) { if (help_mode || do_iopad) -- cgit v1.2.3 From 4ac1b92df33d1ef4bbed71216e2b39c4a0651e5b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 1 Dec 2019 23:19:32 -0800 Subject: Use pool<> not std::set<> for determinism --- passes/hierarchy/clkpart.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc index 81983e226..2d295e915 100644 --- a/passes/hierarchy/clkpart.cc +++ b/passes/hierarchy/clkpart.cc @@ -116,11 +116,11 @@ struct ClkPartPass : public Pass { assign_map.set(mod); std::vector all_cells = mod->selected_cells(); - std::set unassigned_cells(all_cells.begin(), all_cells.end()); + pool unassigned_cells(all_cells.begin(), all_cells.end()); - std::set expand_queue, next_expand_queue; - std::set expand_queue_up, next_expand_queue_up; - std::set expand_queue_down, next_expand_queue_down; + pool expand_queue, next_expand_queue; + pool expand_queue_up, next_expand_queue_up; + pool expand_queue_down, next_expand_queue_down; typedef tuple clkdomain_t; std::map> assigned_cells; -- cgit v1.2.3 From 1d87488795e4f898e2fcf6a71259a3972dbe7819 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 1 Dec 2019 23:26:17 -0800 Subject: Use pool instead of std::set for determinism --- passes/hierarchy/submod.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 211f96175..3b4f33a60 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -42,7 +42,7 @@ struct SubmodWorker struct SubModule { std::string name, full_name; - std::set cells; + pool cells; }; std::map submodules; -- cgit v1.2.3 From 6398b7c17c406a502d157d69011b9acb460848ea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 1 Dec 2019 23:43:28 -0800 Subject: Cleanup --- passes/techmap/abc9.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 193103747..5a9cbc245 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1098,7 +1098,7 @@ struct Abc9Pass : public Pass { pool clocks; std::string target = delay_target; - for (auto cell : module->selected_cells()) { + for (auto cell : module->cells()) { auto inst_module = design->module(cell->type); if (!inst_module || !inst_module->attributes.count("\\abc9_flop")) continue; @@ -1119,7 +1119,6 @@ struct Abc9Pass : public Pass { } } - Wire *abc9_control_wire = module->wire(stringf("%s.$abc9_control", cell->name.c_str())); if (abc9_control_wire == NULL) log_error("'%s$abc9_control' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); @@ -1127,7 +1126,7 @@ struct Abc9Pass : public Pass { ctrldomain_t key(cell->type, abc9_control); auto r = mergeability_class.emplace(key, mergeability_class.size() + 1); - auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); + auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); log_assert(r2.second); } -- cgit v1.2.3 From 19bfb4195818be12e6fb962de29ca32444498c22 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 2 Dec 2019 14:17:06 -0800 Subject: Add INIT value to abc9_control --- techlibs/xilinx/abc9_map.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 29ddf7133..b8defcb64 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -87,7 +87,7 @@ module FDRE (output reg Q, input C, CE, D, R); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; + wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, IS_D_INVERTED, R, IS_R_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module FDRE_1 (output reg Q, input C, CE, D, R); @@ -102,7 +102,7 @@ module FDRE_1 (output reg Q, input C, CE, D, R); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; + wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule @@ -132,7 +132,7 @@ module FDCE (output reg Q, input C, CE, D, CLR); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; + wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDCE_1 (output reg Q, input C, CE, D, CLR); @@ -153,7 +153,7 @@ module FDCE_1 (output reg Q, input C, CE, D, CLR); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; + wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -181,7 +181,7 @@ module FDPE (output reg Q, input C, CE, D, PRE); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; + wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDPE_1 (output reg Q, input C, CE, D, PRE); @@ -202,7 +202,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; + wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -224,7 +224,7 @@ module FDSE (output reg Q, input C, CE, D, S); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; + wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, IS_D_INVERTED, S, IS_S_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module FDSE_1 (output reg Q, input C, CE, D, S); @@ -239,7 +239,7 @@ module FDSE_1 (output reg Q, input C, CE, D, S); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; + wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule -- cgit v1.2.3 From 0add5965c7bb369bc9dd883c559bcd890d911c14 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Dec 2019 14:27:45 -0800 Subject: techmap abc_unmap.v before xilinx_srl -fixed --- techlibs/xilinx/synth_xilinx.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 554c42d68..3fffd81f6 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -538,6 +538,7 @@ struct SynthXilinxPass : public ScriptPass else abc9_opts += " -lut +/xilinx/abc9_xc7.lut"; run("abc9" + abc9_opts); + run("techmap -map +/xilinx/abc9_unmap.v"); } else { if (nowidelut) @@ -553,12 +554,10 @@ struct SynthXilinxPass : public ScriptPass run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')"); std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"; if (help_mode) - techmap_args += " [-map " + ff_map_file + "]"; - else if (abc9) - techmap_args += " -map +/xilinx/abc9_unmap.v"; - else - techmap_args += " -map " + ff_map_file; - run("techmap " + techmap_args); + techmap_args += stringf("[-map %s]", ff_map_file.c_str()); + else if (!abc9) + techmap_args += stringf(" -map %s", ff_map_file.c_str()); + run("techmap " + techmap_args, "(option without '-abc9')"); } if (check_label("finalize")) { -- cgit v1.2.3 From 51650494107d414a53b3e9793b90c193714dac94 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Dec 2019 15:09:33 -0800 Subject: Update ABCREV for upstream bugfix --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6e7681cf3..b088e97f1 100644 --- a/Makefile +++ b/Makefile @@ -128,7 +128,7 @@ bumpversion: # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = 623b5e8 +ABCREV = d527697 ABCPULL = 1 ABCURL ?= https://github.com/berkeley-abc/abc ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 -- cgit v1.2.3 From f98aa1c13fdba69a2ceedd1f3b6613816c60a637 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Dec 2019 15:40:44 -0800 Subject: Revert "Add INIT value to abc9_control" This reverts commit 19bfb4195818be12e6fb962de29ca32444498c22. --- techlibs/xilinx/abc9_map.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index b8defcb64..29ddf7133 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -87,7 +87,7 @@ module FDRE (output reg Q, input C, CE, D, R); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, IS_D_INVERTED, R, IS_R_INVERTED}; + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module FDRE_1 (output reg Q, input C, CE, D, R); @@ -102,7 +102,7 @@ module FDRE_1 (output reg Q, input C, CE, D, R); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule @@ -132,7 +132,7 @@ module FDCE (output reg Q, input C, CE, D, CLR); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDCE_1 (output reg Q, input C, CE, D, CLR); @@ -153,7 +153,7 @@ module FDCE_1 (output reg Q, input C, CE, D, CLR); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -181,7 +181,7 @@ module FDPE (output reg Q, input C, CE, D, PRE); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDPE_1 (output reg Q, input C, CE, D, PRE); @@ -202,7 +202,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -224,7 +224,7 @@ module FDSE (output reg Q, input C, CE, D, S); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, IS_D_INVERTED, S, IS_S_INVERTED}; + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module FDSE_1 (output reg Q, input C, CE, D, S); @@ -239,7 +239,7 @@ module FDSE_1 (output reg Q, input C, CE, D, S); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; - wire [4:0] _TECHMAP_REPLACE_.$abc9_control = {INIT, CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; + wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule -- cgit v1.2.3 From a181ff66d3094e5740b0c803e6fafa8e91bb11e5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Dec 2019 18:47:09 -0800 Subject: Add abc9_init wire, attach to abc9_flop cell --- passes/techmap/abc9.cc | 14 ++++++++++++-- techlibs/xilinx/abc9_map.v | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5a9cbc245..5139cb80b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1106,7 +1106,7 @@ struct Abc9Pass : public Pass { if (delay_target.empty()) { Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); if (abc9_clock_wire == NULL) - log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_error("'%s.$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); SigBit abc9_clock = sigmap(abc9_clock_wire); auto r = clocks.insert(abc9_clock.wire); if (r.second) { @@ -1121,13 +1121,23 @@ struct Abc9Pass : public Pass { Wire *abc9_control_wire = module->wire(stringf("%s.$abc9_control", cell->name.c_str())); if (abc9_control_wire == NULL) - log_error("'%s$abc9_control' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_error("'%s.$abc9_control' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); SigSpec abc9_control = sigmap(abc9_control_wire); ctrldomain_t key(cell->type, abc9_control); auto r = mergeability_class.emplace(key, mergeability_class.size() + 1); auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); log_assert(r2.second); + + Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str())); + if (abc9_init_wire == NULL) + log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_assert(GetSize(abc9_init_wire) == 1); + SigSpec abc9_init = sigmap(abc9_init_wire); + if (!abc9_init.is_fully_const()) + log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); + log_assert(r2.second); } design->selected_active_module = module->name.str(); diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 29ddf7133..98a4457ae 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -64,10 +64,12 @@ // the connectivity of its basic D-Q flop // (b) a special _TECHMAP_REPLACE_.$abc9_clock wire to indicate its clock // signal, used to extract the delay target -// (c) a special _TECHMAP_REPLACE_.$abc9_control that captures the control +// (c) a special _TECHMAP_REPLACE_.$abc9_control wire that captures the control // domain (which, combined with this cell type, encodes to `abc9' which // flops may be merged together) -// (d) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback +// (d) a special _TECHMAP_REPLACE_.$abc9_init wire to encode the flop's initial +// state +// (e) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; @@ -88,6 +90,7 @@ module FDRE (output reg Q, input C, CE, D, R); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module FDRE_1 (output reg Q, input C, CE, D, R); @@ -103,6 +106,7 @@ module FDRE_1 (output reg Q, input C, CE, D, R); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule @@ -133,6 +137,7 @@ module FDCE (output reg Q, input C, CE, D, CLR); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDCE_1 (output reg Q, input C, CE, D, CLR); @@ -154,6 +159,7 @@ module FDCE_1 (output reg Q, input C, CE, D, CLR); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -182,6 +188,7 @@ module FDPE (output reg Q, input C, CE, D, PRE); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDPE_1 (output reg Q, input C, CE, D, PRE); @@ -203,6 +210,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -225,6 +233,7 @@ module FDSE (output reg Q, input C, CE, D, S); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule module FDSE_1 (output reg Q, input C, CE, D, S); @@ -240,6 +249,7 @@ module FDSE_1 (output reg Q, input C, CE, D, S); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; wire _TECHMAP_REPLACE_.$abc9_currQ = Q; endmodule -- 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(-) 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 d66d06b91df4aade84107b59b2b1f32188a3995e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Dec 2019 19:21:42 -0800 Subject: Add assertion --- passes/techmap/abc9.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5139cb80b..5b4100574 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1107,6 +1107,7 @@ struct Abc9Pass : public Pass { Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); if (abc9_clock_wire == NULL) log_error("'%s.$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_assert(GetSize(abc9_clock_wire) == 1); SigBit abc9_clock = sigmap(abc9_clock_wire); auto r = clocks.insert(abc9_clock.wire); if (r.second) { -- 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(-) 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 31ef4cc7048b9da557ee78bb791c5bb7210e9fc5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Dec 2019 16:11:02 -0800 Subject: abc9_map.v to do `zinit' and make INIT = 1'b0 --- techlibs/xilinx/abc9_map.v | 182 ++++++++++++++++++++++++++++----------------- 1 file changed, 112 insertions(+), 70 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 98a4457ae..8939b46a0 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -71,43 +71,55 @@ // state // (e) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour +// In order to perform sequential synthesis, `abc9' also requires that +// the initial value of all flops be zero. module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; - wire $nextQ; + wire DD, QQ, $nextQ; + generate if (INIT == 1'b1) + assign DD = ~D, Q = ~QQ; + else + assign DD = D, Q = QQ; + endgenerate FDRE #( - .INIT(INIT), + .INIT(1'b0), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), .IS_R_INVERTED(IS_R_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) + .D(DD), .Q($nextQ), .C(C), .CE(CE), .R(R) ); - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; - wire _TECHMAP_REPLACE_.$abc9_currQ = Q; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; - wire $nextQ; + wire DD, QQ, $nextQ; + generate if (INIT == 1'b1) + assign DD = ~D, Q = ~QQ; + else + assign DD = D, Q = QQ; + endgenerate FDRE_1 #( - .INIT(INIT), + .INIT(1'b0), ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) + .D(DD), .Q($nextQ), .C(C), .CE(CE), .R(R) ); - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; - wire _TECHMAP_REPLACE_.$abc9_currQ = Q; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule module FDCE (output reg Q, input C, CE, D, CLR); @@ -115,103 +127,123 @@ module FDCE (output reg Q, input C, CE, D, CLR); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; - wire $nextQ, $abc9_currQ; + wire DD, QQ, $nextQ, $abc9_currQ; + generate if (INIT == 1'b1) + assign DD = ~D, Q = ~QQ; + else + assign DD = D, Q = QQ; + endgenerate FDCE #( - .INIT(INIT), + .INIT(1'b0), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), .IS_CLR_INVERTED(IS_CLR_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC below + .D(DD), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); // Since this is an async flop, async behaviour is also dealt with // using the $_ABC9_ASYNC box by abc9_map.v - \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q)); + \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; - wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; - wire $nextQ, $abc9_currQ; + wire DD, QQ, $nextQ, $abc9_currQ; + generate if (INIT == 1'b1) + assign DD = ~D, Q = ~QQ; + else + assign DD = D, Q = QQ; + endgenerate FDCE_1 #( - .INIT(INIT) + .INIT(1'b0) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC below + .D(DD), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); - \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(Q)); + \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; - wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDPE (output reg Q, input C, CE, D, PRE); - parameter [0:0] INIT = 1'b0; + parameter [0:0] INIT = 1'b1; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; - wire $nextQ, $abc9_currQ; + wire DD, QQ, $nextQ, $abc9_currQ; + generate if (INIT == 1'b1) + assign DD = ~D, Q = ~QQ; + else + assign DD = D, Q = QQ; + endgenerate FDPE #( - .INIT(INIT), + .INIT(1'b0), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), .IS_PRE_INVERTED(IS_PRE_INVERTED), ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC below + .D(DD), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); - \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q)); + \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; - wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDPE_1 (output reg Q, input C, CE, D, PRE); - parameter [0:0] INIT = 1'b0; - wire $nextQ, $abc9_currQ; + parameter [0:0] INIT = 1'b1; + wire DD, QQ, $nextQ, $abc9_currQ; + generate if (INIT == 1'b1) + assign DD = ~D, Q = ~QQ; + else + assign DD = D, Q = QQ; + endgenerate FDPE_1 #( - .INIT(INIT) + .INIT(1'b0), ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC below + .D(DD), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); - \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(Q)); + \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; - wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule module FDSE (output reg Q, input C, CE, D, S); @@ -219,38 +251,48 @@ module FDSE (output reg Q, input C, CE, D, S); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; - wire $nextQ; + wire DD, QQ, $nextQ; + generate if (INIT == 1'b1) + assign DD = ~D, Q = ~QQ; + else + assign DD = D, Q = QQ; + endgenerate FDSE #( - .INIT(INIT), + .INIT(1'b0), .IS_C_INVERTED(IS_C_INVERTED), .IS_D_INVERTED(IS_D_INVERTED), .IS_S_INVERTED(IS_S_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) + .D(DD), .Q($nextQ), .C(C), .CE(CE), .S(S) ); - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; - wire _TECHMAP_REPLACE_.$abc9_currQ = Q; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; - wire $nextQ; + wire DD, QQ, $nextQ; + generate if (INIT == 1'b1) + assign DD = ~D, Q = ~QQ; + else + assign DD = D, Q = QQ; + endgenerate FDSE_1 #( - .INIT(INIT), + .INIT(1'b0), ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) + .D(DD), .Q($nextQ), .C(C), .CE(CE), .S(S) ); - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q)); + \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = INIT; - wire _TECHMAP_REPLACE_.$abc9_currQ = Q; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule module RAM32X1D ( -- cgit v1.2.3 From b43986c5a1e9c41865139df9c0b5f9750c26762c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Dec 2019 16:34:34 -0800 Subject: output reg Q -> output Q to suppress warning --- techlibs/xilinx/abc9_map.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 8939b46a0..d84b9a8fa 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -73,7 +73,7 @@ // into the (combinatorial) FD* cell to facilitate clock-enable behaviour // In order to perform sequential synthesis, `abc9' also requires that // the initial value of all flops be zero. -module FDRE (output reg Q, input C, CE, D, R); +module FDRE (output Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -100,7 +100,7 @@ module FDRE (output reg Q, input C, CE, D, R); wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule -module FDRE_1 (output reg Q, input C, CE, D, R); +module FDRE_1 (output Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; wire DD, QQ, $nextQ; generate if (INIT == 1'b1) @@ -122,7 +122,7 @@ module FDRE_1 (output reg Q, input C, CE, D, R); wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule -module FDCE (output reg Q, input C, CE, D, CLR); +module FDCE (output Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -157,7 +157,7 @@ module FDCE (output reg Q, input C, CE, D, CLR); wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule -module FDCE_1 (output reg Q, input C, CE, D, CLR); +module FDCE_1 (output Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; wire DD, QQ, $nextQ, $abc9_currQ; generate if (INIT == 1'b1) @@ -185,7 +185,7 @@ module FDCE_1 (output reg Q, input C, CE, D, CLR); wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule -module FDPE (output reg Q, input C, CE, D, PRE); +module FDPE (output Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -218,7 +218,7 @@ module FDPE (output reg Q, input C, CE, D, PRE); wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule -module FDPE_1 (output reg Q, input C, CE, D, PRE); +module FDPE_1 (output Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; wire DD, QQ, $nextQ, $abc9_currQ; generate if (INIT == 1'b1) @@ -246,7 +246,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule -module FDSE (output reg Q, input C, CE, D, S); +module FDSE (output Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -273,7 +273,7 @@ module FDSE (output reg Q, input C, CE, D, S); wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule -module FDSE_1 (output reg Q, input C, CE, D, S); +module FDSE_1 (output Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; wire DD, QQ, $nextQ; generate if (INIT == 1'b1) -- cgit v1.2.3 From c8a7bc5d3a0a69e942a1c9ce84c1dbf0c32e49e4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Dec 2019 16:37:56 -0800 Subject: Bump ABC to get "&verify -s" fix --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b088e97f1..e484656c8 100644 --- a/Makefile +++ b/Makefile @@ -128,7 +128,7 @@ bumpversion: # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = d527697 +ABCREV = 451f2b0 ABCPULL = 1 ABCURL ?= https://github.com/berkeley-abc/abc ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 -- cgit v1.2.3 From 258a34e6f148928e80f13416b28d6bba6988c78a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Dec 2019 20:33:24 -0800 Subject: Oh deary me --- techlibs/xilinx/cells_sim.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index d845b324f..2fda3b8fd 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -378,10 +378,10 @@ module FDPE ( parameter [0:0] IS_PRE_INVERTED = 1'b0; initial Q <= INIT; generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) - 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= Q ; - 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= Q ; - 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else Q <= Q ; - 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else Q <= Q ; + 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate endmodule -- cgit v1.2.3 From 19bc429482418aa42861ca0f195d86bc9577e320 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Dec 2019 21:36:41 -0800 Subject: abc9_map.v to transform INIT=1 to INIT=0 --- techlibs/xilinx/abc9_map.v | 319 ++++++++++++++++++++++++++---------------- tests/arch/xilinx/abc9_map.ys | 91 ++++++++++++ 2 files changed, 292 insertions(+), 118 deletions(-) create mode 100644 tests/arch/xilinx/abc9_map.ys diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index d84b9a8fa..3fa5f5a1c 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -71,27 +71,39 @@ // state // (e) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour +// // In order to perform sequential synthesis, `abc9' also requires that // the initial value of all flops be zero. + module FDRE (output Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; - wire DD, QQ, $nextQ; - generate if (INIT == 1'b1) - assign DD = ~D, Q = ~QQ; - else - assign DD = D, Q = QQ; + wire QQ, $nextQ; + generate if (INIT == 1'b1) begin + assign Q = ~QQ; + FDSE #( + .INIT(1'b0), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_S_INVERTED(IS_R_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(~D), .Q($nextQ), .C(C), .CE(CE), .S(R) + ); + end + else begin + assign Q = QQ; + FDRE #( + .INIT(1'b0), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_R_INVERTED(IS_R_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) + ); + end endgenerate - FDRE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_R_INVERTED(IS_R_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(DD), .Q($nextQ), .C(C), .CE(CE), .R(R) - ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals @@ -102,17 +114,24 @@ module FDRE (output Q, input C, CE, D, R); endmodule module FDRE_1 (output Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; - wire DD, QQ, $nextQ; - generate if (INIT == 1'b1) - assign DD = ~D, Q = ~QQ; - else - assign DD = D, Q = QQ; + wire QQ, $nextQ; + generate if (INIT == 1'b1) begin + assign Q = ~QQ; + FDSE_1 #( + .INIT(1'b0) + ) _TECHMAP_REPLACE_ ( + .D(~D), .Q($nextQ), .C(C), .CE(CE), .S(R) + ); + end + else begin + assign Q = QQ; + FDRE_1 #( + .INIT(1'b0) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) + ); + end endgenerate - FDRE_1 #( - .INIT(1'b0), - ) _TECHMAP_REPLACE_ ( - .D(DD), .Q($nextQ), .C(C), .CE(CE), .R(R) - ); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals @@ -127,25 +146,39 @@ module FDCE (output Q, input C, CE, D, CLR); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; - wire DD, QQ, $nextQ, $abc9_currQ; - generate if (INIT == 1'b1) - assign DD = ~D, Q = ~QQ; - else - assign DD = D, Q = QQ; - endgenerate - FDCE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_CLR_INVERTED(IS_CLR_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(DD), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC below - ); + wire QQ, $nextQ, $abc9_currQ; + generate if (INIT == 1'b1) begin + assign Q = ~QQ; + FDPE #( + .INIT(1'b0), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_PRE_INVERTED(IS_CLR_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(~D), .Q($nextQ), .C(C), .CE(CE), .PRE(CLR) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below + ); + end + else begin + assign Q = QQ; + FDCE #( + .INIT(1'b0), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_CLR_INVERTED(IS_CLR_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below + ); + end endgenerate \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); // Since this is an async flop, async behaviour is also dealt with // using the $_ABC9_ASYNC box by abc9_map.v @@ -159,22 +192,32 @@ module FDCE (output Q, input C, CE, D, CLR); endmodule module FDCE_1 (output Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; - wire DD, QQ, $nextQ, $abc9_currQ; - generate if (INIT == 1'b1) - assign DD = ~D, Q = ~QQ; - else - assign DD = D, Q = QQ; - endgenerate - FDCE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(DD), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC below - ); + generate if (INIT == 1'b1) begin + assign Q = ~QQ; + FDPE_1 #( + .INIT(1'b0) + ) _TECHMAP_REPLACE_ ( + .D(~D), .Q($nextQ), .C(C), .CE(CE), .PRE(CLR) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below + ); + end + else begin + assign Q = QQ; + FDCE_1 #( + .INIT(1'b0) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below + ); + end endgenerate \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); @@ -190,25 +233,39 @@ module FDPE (output Q, input C, CE, D, PRE); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; - wire DD, QQ, $nextQ, $abc9_currQ; - generate if (INIT == 1'b1) - assign DD = ~D, Q = ~QQ; - else - assign DD = D, Q = QQ; - endgenerate - FDPE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_PRE_INVERTED(IS_PRE_INVERTED), - ) _TECHMAP_REPLACE_ ( - .D(DD), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC below - ); + wire QQ, $nextQ, $abc9_currQ; + generate if (INIT == 1'b1) begin + assign Q = ~QQ; + FDCE #( + .INIT(1'b0), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_CLR_INVERTED(IS_PRE_INVERTED), + ) _TECHMAP_REPLACE_ ( + .D(~D), .Q($nextQ), .C(C), .CE(CE), .CLR(PRE) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below + ); + end + else begin + assign Q = QQ; + FDPE #( + .INIT(1'b0), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_PRE_INVERTED(IS_PRE_INVERTED), + ) _TECHMAP_REPLACE_ ( + .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below + ); + end endgenerate \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); @@ -220,22 +277,33 @@ module FDPE (output Q, input C, CE, D, PRE); endmodule module FDPE_1 (output Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; - wire DD, QQ, $nextQ, $abc9_currQ; - generate if (INIT == 1'b1) - assign DD = ~D, Q = ~QQ; - else - assign DD = D, Q = QQ; - endgenerate - FDPE_1 #( - .INIT(1'b0), - ) _TECHMAP_REPLACE_ ( - .D(DD), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC below - ); + wire QQ, $nextQ, $abc9_currQ; + generate if (INIT == 1'b1) begin + assign Q = ~QQ; + FDCE_1 #( + .INIT(1'b0) + ) _TECHMAP_REPLACE_ ( + .D(~D), .Q($nextQ), .C(C), .CE(CE), .CLR(PRE) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below + ); + end + else begin + assign Q = QQ; + FDPE_1 #( + .INIT(1'b0) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC below + ); + end endgenerate \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); @@ -251,20 +319,29 @@ module FDSE (output Q, input C, CE, D, S); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; - wire DD, QQ, $nextQ; - generate if (INIT == 1'b1) - assign DD = ~D, Q = ~QQ; - else - assign DD = D, Q = QQ; - endgenerate - FDSE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_S_INVERTED(IS_S_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(DD), .Q($nextQ), .C(C), .CE(CE), .S(S) - ); + wire QQ, $nextQ; + generate if (INIT == 1'b1) begin + assign Q = ~QQ; + FDRE #( + .INIT(1'b0), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_R_INVERTED(IS_S_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(~D), .Q($nextQ), .C(C), .CE(CE), .R(S) + ); + end + else begin + assign Q = QQ; + FDSE #( + .INIT(1'b0), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_S_INVERTED(IS_S_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) + ); + end endgenerate \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals @@ -275,17 +352,23 @@ module FDSE (output Q, input C, CE, D, S); endmodule module FDSE_1 (output Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; - wire DD, QQ, $nextQ; - generate if (INIT == 1'b1) - assign DD = ~D, Q = ~QQ; - else - assign DD = D, Q = QQ; - endgenerate - FDSE_1 #( - .INIT(1'b0), - ) _TECHMAP_REPLACE_ ( - .D(DD), .Q($nextQ), .C(C), .CE(CE), .S(S) - ); + wire QQ, $nextQ; + generate if (INIT == 1'b1) begin + assign Q = ~QQ; + FDRE_1 #( + .INIT(1'b0) + ) _TECHMAP_REPLACE_ ( + .D(~D), .Q($nextQ), .C(C), .CE(CE), .R(S) + ); + end + else begin + assign Q = QQ; + FDSE_1 #( + .INIT(1'b0) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) + ); + end endgenerate \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals diff --git a/tests/arch/xilinx/abc9_map.ys b/tests/arch/xilinx/abc9_map.ys new file mode 100644 index 000000000..6823589f1 --- /dev/null +++ b/tests/arch/xilinx/abc9_map.ys @@ -0,0 +1,91 @@ +read_verilog < Date: Wed, 4 Dec 2019 23:04:40 -0800 Subject: Missing wire declaration --- techlibs/xilinx/abc9_map.v | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 3fa5f5a1c..d2159f82d 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -192,6 +192,7 @@ module FDCE (output Q, input C, CE, D, CLR); endmodule module FDCE_1 (output Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; + wire QQ, $nextQ, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDPE_1 #( -- cgit v1.2.3 From 864bff14f11fc67bac40f77e5bf17c7fc61ad9f6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Dec 2019 11:11:53 -0800 Subject: Revert "Special abc9_clock wire to contain only clock signal" This reverts commit 6a2eb5d8f9286b9574647c03e2bdc8b63fccbe4d. --- techlibs/xilinx/abc9_map.v | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index d2159f82d..4d76a5232 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -62,8 +62,10 @@ // The purpose of the following FD* rules are to wrap the flop with: // (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 // the connectivity of its basic D-Q flop -// (b) a special _TECHMAP_REPLACE_.$abc9_clock wire to indicate its clock -// signal, used to extract the delay target +// (b) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock +// domain (used when partitioning the module so that `abc9' only +// performs sequential synthesis (with reachability analysis) correctly on +// one domain at a time) and used to infert the delay target // (c) a special _TECHMAP_REPLACE_.$abc9_control wire that captures the control // domain (which, combined with this cell type, encodes to `abc9' which // flops may be merged together) @@ -107,7 +109,7 @@ module FDRE (output Q, input C, CE, D, R); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals - wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; @@ -135,7 +137,7 @@ module FDRE_1 (output Q, input C, CE, D, R); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals - wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; @@ -185,7 +187,7 @@ module FDCE (output Q, input C, CE, D, CLR); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); // Special signals - wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; @@ -223,7 +225,7 @@ module FDCE_1 (output Q, input C, CE, D, CLR); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); // Special signals - wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; @@ -271,7 +273,7 @@ module FDPE (output Q, input C, CE, D, PRE); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); // Special signals - wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; @@ -309,7 +311,7 @@ module FDPE_1 (output Q, input C, CE, D, PRE); \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); // Special signals - wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; @@ -346,7 +348,7 @@ module FDSE (output Q, input C, CE, D, S); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals - wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; @@ -373,7 +375,7 @@ module FDSE_1 (output Q, input C, CE, D, S); \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); // Special signals - wire [0:0] _TECHMAP_REPLACE_.$abc9_clock = C; + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; -- cgit v1.2.3 From 02786b0aa0eb45a53b92b86b192d5ae5846366bd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Dec 2019 17:25:26 -0800 Subject: Remove clkpart --- passes/hierarchy/Makefile.inc | 1 - passes/hierarchy/clkpart.cc | 308 ---------------------------------------- techlibs/xilinx/synth_xilinx.cc | 4 - 3 files changed, 313 deletions(-) delete mode 100644 passes/hierarchy/clkpart.cc diff --git a/passes/hierarchy/Makefile.inc b/passes/hierarchy/Makefile.inc index ea809ec08..b3f139b72 100644 --- a/passes/hierarchy/Makefile.inc +++ b/passes/hierarchy/Makefile.inc @@ -2,5 +2,4 @@ OBJS += passes/hierarchy/hierarchy.o OBJS += passes/hierarchy/uniquify.o OBJS += passes/hierarchy/submod.o -OBJS += passes/hierarchy/clkpart.o diff --git a/passes/hierarchy/clkpart.cc b/passes/hierarchy/clkpart.cc deleted file mode 100644 index 2d295e915..000000000 --- a/passes/hierarchy/clkpart.cc +++ /dev/null @@ -1,308 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Eddie Hung - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/register.h" -#include "kernel/sigtools.h" -#include "kernel/celltypes.h" -#include "kernel/rtlil.h" -#include "kernel/log.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct ClkPartPass : public Pass { - ClkPartPass() : Pass("clkpart", "partition design according to clock/enable domain") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" clkpart [options] [selection]\n"); - log("\n"); - log("Partition the contents of selected modules according to the clock (and optionally\n"); - log("the enable) domains of its $_DFF* cells by extracting them into sub-modules,\n"); - log("using the `submod` command.\n"); - log("\n"); - log(" -set_attr \n"); - log(" set the specified attribute on all sub-modules created.\n"); - log("\n"); - log(" -unpart \n"); - log(" undo this operation within the selected modules, by flattening those\n"); - log(" attached with an attribute into those modules without this\n"); - log(" attribute.\n"); - log("\n"); - log(" -enable\n"); - log(" also consider enable domains.\n"); - log("\n"); - } - - bool unpart_mode, enable_mode; - IdString attr_name; - Const attr_value; - - void clear_flags() YS_OVERRIDE - { - unpart_mode = false; - enable_mode = false; - attr_name = IdString(); - attr_value = Const(); - } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing CLKPART pass (partition design according to clock/enable domain).\n"); - log_push(); - - clear_flags(); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-set_attr" && argidx+2 < args.size()) { - attr_name = RTLIL::escape_id(args[++argidx]); - attr_value = args[argidx++]; - continue; - } - if (args[argidx] == "-unpart" && argidx+1 < args.size()) { - unpart_mode = true; - attr_name = RTLIL::escape_id(args[++argidx]); - continue; - } - if (args[argidx] == "-enable") { - enable_mode = true; - continue; - } - break; - } - extra_args(args, argidx, design); - - if (unpart_mode) - unpart(design); - else - part(design); - - log_pop(); - } - - void part(RTLIL::Design *design) - { - CellTypes ct(design); - SigMap assign_map; - std::vector new_submods; - - log_header(design, "Summary of detected clock domains:\n"); - for (auto mod : design->selected_modules()) - { - if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); - continue; - } - - assign_map.set(mod); - - std::vector all_cells = mod->selected_cells(); - pool unassigned_cells(all_cells.begin(), all_cells.end()); - - pool expand_queue, next_expand_queue; - pool expand_queue_up, next_expand_queue_up; - pool expand_queue_down, next_expand_queue_down; - - typedef tuple clkdomain_t; - std::map> assigned_cells; - std::map assigned_cells_reverse; - - std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; - std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; - - for (auto cell : all_cells) - { - clkdomain_t key; - - for (auto &conn : cell->connections()) - for (auto bit : conn.second) { - bit = assign_map(bit); - if (bit.wire != nullptr) { - cell_to_bit[cell].insert(bit); - bit_to_cell[bit].insert(cell); - if (ct.cell_input(cell->type, conn.first)) { - cell_to_bit_up[cell].insert(bit); - bit_to_cell_down[bit].insert(cell); - } - if (ct.cell_output(cell->type, conn.first)) { - cell_to_bit_down[cell].insert(bit); - bit_to_cell_up[bit].insert(cell); - } - } - } - - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) - { - key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); - } - else - if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - { - bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); - bool this_en_pol = !enable_mode || cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, enable_mode ? assign_map(cell->getPort(ID(E))) : RTLIL::SigSpec()); - } - else - if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_))) - { - bool this_clk_pol = cell->type.in(ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)); - log_assert(!enable_mode); // TODO - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); - } - else - continue; - - unassigned_cells.erase(cell); - expand_queue.insert(cell); - expand_queue_up.insert(cell); - expand_queue_down.insert(cell); - - assigned_cells[key].push_back(cell); - assigned_cells_reverse[cell] = key; - } - - while (!expand_queue_up.empty() || !expand_queue_down.empty()) - { - if (!expand_queue_up.empty()) - { - RTLIL::Cell *cell = *expand_queue_up.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue_up.erase(cell); - - for (auto bit : cell_to_bit_up[cell]) - for (auto c : bit_to_cell_up[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (!expand_queue_down.empty()) - { - RTLIL::Cell *cell = *expand_queue_down.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue_down.erase(cell); - - for (auto bit : cell_to_bit_down[cell]) - for (auto c : bit_to_cell_down[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (expand_queue_up.empty() && expand_queue_down.empty()) { - expand_queue_up.swap(next_expand_queue_up); - expand_queue_down.swap(next_expand_queue_down); - } - } - - while (!expand_queue.empty()) - { - RTLIL::Cell *cell = *expand_queue.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue.erase(cell); - - for (auto bit : cell_to_bit.at(cell)) { - for (auto c : bit_to_cell[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue.insert(c); - assigned_cells[key].push_back(c); - assigned_cells_reverse[c] = key; - } - bit_to_cell[bit].clear(); - } - - if (expand_queue.empty()) - expand_queue.swap(next_expand_queue); - } - - clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); - for (auto cell : unassigned_cells) { - assigned_cells[key].push_back(cell); - assigned_cells_reverse[cell] = key; - } - - clkdomain_t largest_domain; - int largest_domain_size = 0; - log(" module %s\n", mod->name.c_str()); - for (auto &it : assigned_cells) { - log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), - std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), - std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); - if (GetSize(it.second) > largest_domain_size) { - largest_domain = it.first; - largest_domain_size = GetSize(it.second); - } - } - - for (auto &it : assigned_cells) { - if (it.first == largest_domain) - continue; - - auto clk = std::get<1>(it.first); - auto en = std::get<3>(it.first); - std::string submod = stringf("clk=%s%s%s%s%s", - std::get<0>(it.first) ? "" : "!", clk.empty() ? "" : log_signal(clk), - std::get<2>(it.first) ? "" : "!", en.empty() ? "" : ".en=", en.empty() ? "" : log_signal(en)); - for (auto c : it.second) - c->attributes[ID(submod)] = submod; - new_submods.push_back(stringf("%s_%s", mod->name.c_str(), submod.c_str())); - } - } - - Pass::call(design, "submod -hidden"); - - if (!attr_name.empty()) - for (auto m : new_submods) - design->module(m)->attributes[attr_name] = attr_value; - } - - void unpart(RTLIL::Design *design) - { - vector keeped; - for (auto mod : design->selected_modules()) { - if (mod->get_bool_attribute(attr_name)) - continue; - if (mod->get_bool_attribute(ID(keep_hierarchy))) - continue; - keeped.push_back(mod); - mod->set_bool_attribute(ID(keep_hierarchy)); - } - - Pass::call(design, "flatten"); - - for (auto mod : keeped) - mod->set_bool_attribute(ID(keep_hierarchy), false); - - } -} ClkPartPass; - -PRIVATE_NAMESPACE_END diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 3fffd81f6..30be9832c 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -513,7 +513,6 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_ffs")) { if (abc9 || help_mode) { - run("clkpart -set_attr clkpart 1", "('-abc9' only)"); run("techmap -map " + ff_map_file, "('-abc9' only)"); } } @@ -561,9 +560,6 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("finalize")) { - if (help_mode || abc9) - run("clkpart -unpart clkpart", "(only if 'abc9')"); - bool do_iopad = iopad || (ise && !noiopad); if (help_mode || !noclkbuf) { if (help_mode || do_iopad) -- cgit v1.2.3 From 01a3cc29ba8dbadea254a205809f583d4a860672 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Dec 2019 17:26:22 -0800 Subject: abc9 to do clock partitioning again --- passes/techmap/abc9.cc | 181 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 144 insertions(+), 37 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5b4100574..0237724f6 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -752,10 +752,6 @@ struct Abc9Pass : public Pass { log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); log("library to a target architecture.\n"); log("\n"); - log("Selection must only contain fully selected modules. It is assumed that such\n"); - log("modules contain only cells belonging to the same clock domain, as produced by\n"); - log("the 'clkpart' command.\n"); - log("\n"); log(" -exe \n"); #ifdef ABCEXTERNAL log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); @@ -1076,6 +1072,8 @@ struct Abc9Pass : public Pass { } } + SigMap assign_map; + CellTypes ct(design); for (auto module : design->selected_modules()) { if (module->attributes.count(ID(abc9_box_id))) @@ -1086,65 +1084,174 @@ struct Abc9Pass : public Pass { continue; } - if (!design->selected_whole_module(module)) { - log("Skipping module %s as it is partially selected.\n", log_id(module)); - continue; - } + assign_map.set(module); + + std::vector all_cells = module->selected_cells(); + std::set unassigned_cells(all_cells.begin(), all_cells.end()); + + std::set expand_queue, next_expand_queue; + std::set expand_queue_up, next_expand_queue_up; + std::set expand_queue_down, next_expand_queue_down; - SigMap sigmap(module); + std::map> assigned_cells; + std::map assigned_cells_reverse; + + std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; + std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; typedef std::pair ctrldomain_t; std::map mergeability_class; - pool clocks; - std::string target = delay_target; - for (auto cell : module->cells()) { + for (auto cell : all_cells) { + for (auto &conn : cell->connections()) + for (auto bit : assign_map(conn.second)) + if (bit.wire != nullptr) { + cell_to_bit[cell].insert(bit); + bit_to_cell[bit].insert(cell); + if (ct.cell_input(cell->type, conn.first)) { + cell_to_bit_up[cell].insert(bit); + bit_to_cell_down[bit].insert(cell); + } + if (ct.cell_output(cell->type, conn.first)) { + cell_to_bit_down[cell].insert(bit); + bit_to_cell_up[bit].insert(cell); + } + } + auto inst_module = design->module(cell->type); if (!inst_module || !inst_module->attributes.count("\\abc9_flop")) continue; - if (delay_target.empty()) { - Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); - if (abc9_clock_wire == NULL) - log_error("'%s.$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - log_assert(GetSize(abc9_clock_wire) == 1); - SigBit abc9_clock = sigmap(abc9_clock_wire); - auto r = clocks.insert(abc9_clock.wire); - if (r.second) { - auto it = abc9_clock.wire->attributes.find("\\abc9_period"); - if (it != abc9_clock.wire->attributes.end()) { - int period = it->second.as_int(); - log("Identified target period = %d ps for clock %s\n", period, log_signal(abc9_clock)); - target = stringf("-D %d", period); - } - } - } + Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); + if (abc9_clock_wire == NULL) + log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + SigSpec abc9_clock = assign_map(abc9_clock_wire); Wire *abc9_control_wire = module->wire(stringf("%s.$abc9_control", cell->name.c_str())); if (abc9_control_wire == NULL) - log_error("'%s.$abc9_control' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - SigSpec abc9_control = sigmap(abc9_control_wire); + log_error("'%s$abc9_control' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + SigSpec abc9_control = assign_map(abc9_control_wire); + + unassigned_cells.erase(cell); + expand_queue.insert(cell); + expand_queue_up.insert(cell); + expand_queue_down.insert(cell); + + assigned_cells[abc9_clock].insert(cell->name); + assigned_cells_reverse[cell] = abc9_clock; ctrldomain_t key(cell->type, abc9_control); auto r = mergeability_class.emplace(key, mergeability_class.size() + 1); - auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); + auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); log_assert(r2.second); Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str())); if (abc9_init_wire == NULL) - log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); log_assert(GetSize(abc9_init_wire) == 1); - SigSpec abc9_init = sigmap(abc9_init_wire); + SigSpec abc9_init = assign_map(abc9_init_wire); if (!abc9_init.is_fully_const()) - log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); log_assert(r2.second); } + while (!expand_queue_up.empty() || !expand_queue_down.empty()) + { + if (!expand_queue_up.empty()) + { + RTLIL::Cell *cell = *expand_queue_up.begin(); + SigSpec key = assigned_cells_reverse.at(cell); + expand_queue_up.erase(cell); + + for (auto bit : cell_to_bit_up[cell]) + for (auto c : bit_to_cell_up[bit]) + if (unassigned_cells.count(c) && !c->type.in("$__ABC9_FF_", "$__ABC9_ASYNC_")) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].insert(c->name); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (!expand_queue_down.empty()) + { + RTLIL::Cell *cell = *expand_queue_down.begin(); + SigSpec key = assigned_cells_reverse.at(cell); + expand_queue_down.erase(cell); + + for (auto bit : cell_to_bit_down[cell]) + for (auto c : bit_to_cell_down[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].insert(c->name); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (expand_queue_up.empty() && expand_queue_down.empty()) { + expand_queue_up.swap(next_expand_queue_up); + expand_queue_down.swap(next_expand_queue_down); + } + } + + while (!expand_queue.empty()) + { + RTLIL::Cell *cell = *expand_queue.begin(); + SigSpec key = assigned_cells_reverse.at(cell); + expand_queue.erase(cell); + + for (auto bit : cell_to_bit.at(cell)) { + for (auto c : bit_to_cell[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue.insert(c); + assigned_cells[key].insert(c->name); + assigned_cells_reverse[c] = key; + } + bit_to_cell[bit].clear(); + } + + if (expand_queue.empty()) + expand_queue.swap(next_expand_queue); + } + + SigSpec key; + for (auto cell : unassigned_cells) { + assigned_cells[key].insert(cell->name); + assigned_cells_reverse[cell] = key; + } + + log_header(design, "Summary of detected clock domains:\n"); + for (auto &it : assigned_cells) + log(" %d cells in clk=%s\n", GetSize(it.second), log_signal(it.first)); + + design->selection_stack.emplace_back(false); design->selected_active_module = module->name.str(); - abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, false, "$", - keepff, target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay, box_lookup, nomfs); + for (auto &it : assigned_cells) { + std::string target = delay_target; + if (target.empty()) { + for (auto b : assign_map(it.first)) + if (b.wire) { + auto jt = b.wire->attributes.find("\\abc9_period"); + if (jt != b.wire->attributes.end()) { + target = stringf("-D %d", jt->second.as_int()); + log("Target period = %s ps for clock domain %s\n", target.c_str(), log_signal(it.first)); + break; + } + } + } + RTLIL::Selection& sel = design->selection_stack.back(); + sel.selected_members[module->name] = std::move(it.second); + abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, false, "$", + keepff, target, lutin_shared, fast_mode, show_tempdir, + box_file, lut_file, wire_delay, box_lookup, nomfs); + assign_map.set(module); + } + design->selection_stack.pop_back(); design->selected_active_module.clear(); } -- 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(-) 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 ec0acc9f85af0d21ea722375788b372cc416f173 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Dec 2019 23:18:27 -0800 Subject: abc9 to use mergeability class to differentiate sync/async --- techlibs/xilinx/abc9_map.v | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 4d76a5232..d5d5a89f6 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -62,16 +62,18 @@ // The purpose of the following FD* rules are to wrap the flop with: // (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 // the connectivity of its basic D-Q flop -// (b) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock +// (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to +// capture asynchronous behaviour +// (c) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock // domain (used when partitioning the module so that `abc9' only // performs sequential synthesis (with reachability analysis) correctly on // one domain at a time) and used to infert the delay target -// (c) a special _TECHMAP_REPLACE_.$abc9_control wire that captures the control +// (d) a special _TECHMAP_REPLACE_.$abc9_control wire that captures the control // domain (which, combined with this cell type, encodes to `abc9' which // flops may be merged together) -// (d) a special _TECHMAP_REPLACE_.$abc9_init wire to encode the flop's initial +// (e) a special _TECHMAP_REPLACE_.$abc9_init wire to encode the flop's initial // state -// (e) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback +// (f) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour // // In order to perform sequential synthesis, `abc9' also requires that @@ -110,7 +112,7 @@ module FDRE (output Q, input C, CE, D, R); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b0 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule @@ -138,7 +140,7 @@ module FDRE_1 (output Q, input C, CE, D, R); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b1 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule @@ -188,7 +190,7 @@ module FDCE (output Q, input C, CE, D, CLR); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b1 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -226,7 +228,7 @@ module FDCE_1 (output Q, input C, CE, D, CLR); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b1 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -274,7 +276,7 @@ module FDPE (output Q, input C, CE, D, PRE); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b1 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -312,7 +314,8 @@ module FDPE_1 (output Q, input C, CE, D, PRE); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b1 /* async */}; +>>>>>>> d3b23690... abc9 to use mergeability class to differentiate sync/async wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -349,7 +352,7 @@ module FDSE (output Q, input C, CE, D, S); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b0 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule @@ -376,7 +379,7 @@ module FDSE_1 (output Q, input C, CE, D, S); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b0 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule -- 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(-) 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 fce527f4f7764ae2e2d5f6a7e01da59075f79350 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Dec 2019 16:20:18 -0800 Subject: Fix abc9 re-integration, remove abc9_control_wire, use cell->type as as part of clock domain for mergeability class --- passes/techmap/abc9.cc | 54 ++++++++++++++------------------------------------ 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 0237724f6..2d1ce318a 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -30,7 +30,7 @@ "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ "&mfs; &ps -l" #else -#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l; time" +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" #endif @@ -429,26 +429,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip if (mapped_mod == NULL) log_error("ABC output file does not contain a module `$__abc9__'.\n"); - pool output_bits; for (auto &it : mapped_mod->wires_) { RTLIL::Wire *w = it.second; RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w)); if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx; - if (w->port_output) { - RTLIL::Wire *wire = module->wire(w->name); - log_assert(wire); - for (int i = 0; i < GetSize(w); i++) - output_bits.insert({wire, i}); - } - } - - for (auto &it : module->connections_) { - auto &signal = it.first; - auto bits = signal.bits(); - for (auto &b : bits) - if (output_bits.count(b)) - b = module->addWire(NEW_ID); - signal = std::move(bits); } dict abc9_box; @@ -1093,15 +1077,13 @@ struct Abc9Pass : public Pass { std::set expand_queue_up, next_expand_queue_up; std::set expand_queue_down, next_expand_queue_down; - std::map> assigned_cells; - std::map assigned_cells_reverse; + typedef std::pair clkdomain_t; + std::map> assigned_cells; + std::map assigned_cells_reverse; std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; - typedef std::pair ctrldomain_t; - std::map mergeability_class; - for (auto cell : all_cells) { for (auto &conn : cell->connections()) for (auto bit : assign_map(conn.second)) @@ -1127,22 +1109,16 @@ struct Abc9Pass : public Pass { log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); SigSpec abc9_clock = assign_map(abc9_clock_wire); - Wire *abc9_control_wire = module->wire(stringf("%s.$abc9_control", cell->name.c_str())); - if (abc9_control_wire == NULL) - log_error("'%s$abc9_control' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - SigSpec abc9_control = assign_map(abc9_control_wire); - unassigned_cells.erase(cell); expand_queue.insert(cell); expand_queue_up.insert(cell); expand_queue_down.insert(cell); - assigned_cells[abc9_clock].insert(cell->name); - assigned_cells_reverse[cell] = abc9_clock; + clkdomain_t key(abc9_clock, cell->type); + assigned_cells[key].insert(cell->name); + assigned_cells_reverse[cell] = key; - ctrldomain_t key(cell->type, abc9_control); - auto r = mergeability_class.emplace(key, mergeability_class.size() + 1); - auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); + auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), 1)); log_assert(r2.second); Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str())); @@ -1161,7 +1137,7 @@ struct Abc9Pass : public Pass { if (!expand_queue_up.empty()) { RTLIL::Cell *cell = *expand_queue_up.begin(); - SigSpec key = assigned_cells_reverse.at(cell); + auto key = assigned_cells_reverse.at(cell); expand_queue_up.erase(cell); for (auto bit : cell_to_bit_up[cell]) @@ -1178,7 +1154,7 @@ struct Abc9Pass : public Pass { if (!expand_queue_down.empty()) { RTLIL::Cell *cell = *expand_queue_down.begin(); - SigSpec key = assigned_cells_reverse.at(cell); + auto key = assigned_cells_reverse.at(cell); expand_queue_down.erase(cell); for (auto bit : cell_to_bit_down[cell]) @@ -1201,7 +1177,7 @@ struct Abc9Pass : public Pass { while (!expand_queue.empty()) { RTLIL::Cell *cell = *expand_queue.begin(); - SigSpec key = assigned_cells_reverse.at(cell); + auto key = assigned_cells_reverse.at(cell); expand_queue.erase(cell); for (auto bit : cell_to_bit.at(cell)) { @@ -1219,7 +1195,7 @@ struct Abc9Pass : public Pass { expand_queue.swap(next_expand_queue); } - SigSpec key; + clkdomain_t key; for (auto cell : unassigned_cells) { assigned_cells[key].insert(cell->name); assigned_cells_reverse[cell] = key; @@ -1227,19 +1203,19 @@ struct Abc9Pass : public Pass { log_header(design, "Summary of detected clock domains:\n"); for (auto &it : assigned_cells) - log(" %d cells in clk=%s\n", GetSize(it.second), log_signal(it.first)); + log(" %d cells in clk=%s cell=%s\n", GetSize(it.second), log_signal(it.first.first), log_id(it.first.second)); design->selection_stack.emplace_back(false); design->selected_active_module = module->name.str(); for (auto &it : assigned_cells) { std::string target = delay_target; if (target.empty()) { - for (auto b : assign_map(it.first)) + for (auto b : assign_map(it.first.first)) if (b.wire) { auto jt = b.wire->attributes.find("\\abc9_period"); if (jt != b.wire->attributes.end()) { target = stringf("-D %d", jt->second.as_int()); - log("Target period = %s ps for clock domain %s\n", target.c_str(), log_signal(it.first)); + log("Target period = %s ps for clock domain %s\n", target.c_str(), log_signal(it.first.first)); break; } } -- cgit v1.2.3 From 69d8c1386a239372a2ab8910bf12d5d70701b7fa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Dec 2019 16:21:06 -0800 Subject: Do not connect undriven POs to 1'bx --- frontends/aiger/aigerparse.cc | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 9374f1ab3..084107b35 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -1005,15 +1005,10 @@ void AigerReader::post_process() if (other_wire) { other_wire->port_input = false; other_wire->port_output = false; - } - if (wire->port_input) { - if (other_wire) + if (wire->port_input) module->connect(other_wire, SigSpec(wire, i)); - } - else { - // Since we skip POs that are connected to Sx, - // re-connect them here - module->connect(SigSpec(wire, i), other_wire ? other_wire : SigSpec(RTLIL::Sx)); + else + module->connect(SigSpec(wire, i), other_wire); } } } -- cgit v1.2.3 From c767525441ebc6a21b29bf0c1208049cd38adc8e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Dec 2019 16:23:09 -0800 Subject: Remove creation of $abc9_control_wire --- techlibs/xilinx/abc9_map.v | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index d5d5a89f6..49000ea25 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -65,15 +65,14 @@ // (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to // capture asynchronous behaviour // (c) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock -// domain (used when partitioning the module so that `abc9' only +// domain and polarity (used when partitioning the module so that `abc9' only // performs sequential synthesis (with reachability analysis) correctly on -// one domain at a time) and used to infert the delay target -// (d) a special _TECHMAP_REPLACE_.$abc9_control wire that captures the control -// domain (which, combined with this cell type, encodes to `abc9' which -// flops may be merged together) -// (e) a special _TECHMAP_REPLACE_.$abc9_init wire to encode the flop's initial +// one domain at a time) and also used to infer the optional delay target +// from the (* abc9_clock_period = %d *) attribute attached to any wire +// within +// (d) a special _TECHMAP_REPLACE_.$abc9_init wire to encode the flop's initial // state -// (f) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback +// (e) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour // // In order to perform sequential synthesis, `abc9' also requires that @@ -112,7 +111,6 @@ module FDRE (output Q, input C, CE, D, R); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b0 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule @@ -140,7 +138,6 @@ module FDRE_1 (output Q, input C, CE, D, R); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b1 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule @@ -190,7 +187,6 @@ module FDCE (output Q, input C, CE, D, CLR); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b1 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -228,7 +224,6 @@ module FDCE_1 (output Q, input C, CE, D, CLR); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b1 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -276,7 +271,6 @@ module FDPE (output Q, input C, CE, D, PRE); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b1 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -314,8 +308,6 @@ module FDPE_1 (output Q, input C, CE, D, PRE); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b1 /* async */}; ->>>>>>> d3b23690... abc9 to use mergeability class to differentiate sync/async wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; endmodule @@ -352,7 +344,6 @@ module FDSE (output Q, input C, CE, D, S); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b0 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule @@ -379,7 +370,6 @@ module FDSE_1 (output Q, input C, CE, D, S); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_control = {1'b0 /* async */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; endmodule -- cgit v1.2.3 From ab667d3d47ceb07a41b571517b4effb0f4a4bf0b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Dec 2019 16:35:57 -0800 Subject: Call abc9 with "&write -n", and parse_xaiger() to cope --- frontends/aiger/aigerparse.cc | 177 ++++++++++++++++++++---------------------- passes/techmap/abc9.cc | 4 +- 2 files changed, 87 insertions(+), 94 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 084107b35..8ff690464 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -376,105 +376,98 @@ void AigerReader::parse_xaiger(const dict &box_lookup) if (n0) module->connect(n0, State::S0); + int c = f.get(); + if (c != 'c') + log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); + c = f.get(); + log_assert(c == '\n'); + // Parse footer (symbol table, comments, etc.) std::string s; - bool comment_seen = false; - for (int c = f.peek(); c != EOF; c = f.peek()) { - if (comment_seen || c == 'c') { - if (!comment_seen) { - f.ignore(1); - c = f.peek(); - comment_seen = true; - } - if (c == '\n') - break; - f.ignore(1); - // XAIGER extensions - if (c == 'm') { - uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); - uint32_t lutNum = parse_xaiger_literal(f); - uint32_t lutSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); - log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize); - ConstEvalAig ce(module); - for (unsigned i = 0; i < lutNum; ++i) { - uint32_t rootNodeID = parse_xaiger_literal(f); - uint32_t cutLeavesM = parse_xaiger_literal(f); - log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); - RTLIL::Wire *output_sig = module->wire(stringf("\\__%d__", rootNodeID)); - uint32_t nodeID; - RTLIL::SigSpec input_sig; - for (unsigned j = 0; j < cutLeavesM; ++j) { - nodeID = parse_xaiger_literal(f); - log_debug2("\t%u\n", nodeID); - RTLIL::Wire *wire = module->wire(stringf("\\__%d__", nodeID)); - log_assert(wire); - input_sig.append(wire); - } - // TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size()) - ce.clear(); - ce.compute_deps(output_sig, input_sig.to_sigbit_pool()); - RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size()); - for (int j = 0; j < (1 << cutLeavesM); ++j) { - int gray = j ^ (j >> 1); - ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast(cutLeavesM)}); - RTLIL::SigBit o(output_sig); - bool success YS_ATTRIBUTE(unused) = ce.eval(o); - log_assert(success); - log_assert(o.wire == nullptr); - lut_mask[gray] = o.data; - } - RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID)); - log_assert(output_cell); - module->remove(output_cell); - module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); + for (int c = f.get(); c != EOF; c = f.get()) { + // XAIGER extensions + if (c == 'm') { + uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + uint32_t lutNum = parse_xaiger_literal(f); + uint32_t lutSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize); + ConstEvalAig ce(module); + for (unsigned i = 0; i < lutNum; ++i) { + uint32_t rootNodeID = parse_xaiger_literal(f); + uint32_t cutLeavesM = parse_xaiger_literal(f); + log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); + RTLIL::Wire *output_sig = module->wire(stringf("\\__%d__", rootNodeID)); + uint32_t nodeID; + RTLIL::SigSpec input_sig; + for (unsigned j = 0; j < cutLeavesM; ++j) { + nodeID = parse_xaiger_literal(f); + log_debug2("\t%u\n", nodeID); + RTLIL::Wire *wire = module->wire(stringf("\\__%d__", nodeID)); + log_assert(wire); + input_sig.append(wire); } - } - else if (c == 'r') { - uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); - flopNum = parse_xaiger_literal(f); - log_debug("flopNum = %u\n", flopNum); - log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); - f.ignore(flopNum * sizeof(uint32_t)); - } - else if (c == 'n') { - parse_xaiger_literal(f); - f >> s; - log_debug("n: '%s'\n", s.c_str()); - } - else if (c == 'h') { - f.ignore(sizeof(uint32_t)); - uint32_t version YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); - log_assert(version == 1); - uint32_t ciNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); - log_debug("ciNum = %u\n", ciNum); - uint32_t coNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); - log_debug("coNum = %u\n", coNum); - piNum = parse_xaiger_literal(f); - log_debug("piNum = %u\n", piNum); - uint32_t poNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); - log_debug("poNum = %u\n", poNum); - uint32_t boxNum = parse_xaiger_literal(f); - log_debug("boxNum = %u\n", boxNum); - for (unsigned i = 0; i < boxNum; i++) { - f.ignore(2*sizeof(uint32_t)); - uint32_t boxUniqueId = parse_xaiger_literal(f); - log_assert(boxUniqueId > 0); - uint32_t oldBoxNum = parse_xaiger_literal(f); - RTLIL::Cell* cell = module->addCell(stringf("$__box%u__", oldBoxNum), box_lookup.at(boxUniqueId)); - boxes.emplace_back(cell); + // TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size()) + ce.clear(); + ce.compute_deps(output_sig, input_sig.to_sigbit_pool()); + RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size()); + for (int j = 0; j < (1 << cutLeavesM); ++j) { + int gray = j ^ (j >> 1); + ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast(cutLeavesM)}); + RTLIL::SigBit o(output_sig); + bool success YS_ATTRIBUTE(unused) = ce.eval(o); + log_assert(success); + log_assert(o.wire == nullptr); + lut_mask[gray] = o.data; } + RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID)); + log_assert(output_cell); + module->remove(output_cell); + module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } - else if (c == 'a' || c == 'i' || c == 'o' || c == 's') { - uint32_t dataSize = parse_xaiger_literal(f); - f.ignore(dataSize); - log_debug("ignoring '%c'\n", c); - } - else { - break; + } + else if (c == 'r') { + uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + flopNum = parse_xaiger_literal(f); + log_debug("flopNum = %u\n", flopNum); + log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); + f.ignore(flopNum * sizeof(uint32_t)); + } + else if (c == 'n') { + parse_xaiger_literal(f); + f >> s; + log_debug("n: '%s'\n", s.c_str()); + } + else if (c == 'h') { + f.ignore(sizeof(uint32_t)); + uint32_t version YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + log_assert(version == 1); + uint32_t ciNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + log_debug("ciNum = %u\n", ciNum); + uint32_t coNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + log_debug("coNum = %u\n", coNum); + piNum = parse_xaiger_literal(f); + log_debug("piNum = %u\n", piNum); + uint32_t poNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + log_debug("poNum = %u\n", poNum); + uint32_t boxNum = parse_xaiger_literal(f); + log_debug("boxNum = %u\n", boxNum); + for (unsigned i = 0; i < boxNum; i++) { + f.ignore(2*sizeof(uint32_t)); + uint32_t boxUniqueId = parse_xaiger_literal(f); + log_assert(boxUniqueId > 0); + uint32_t oldBoxNum = parse_xaiger_literal(f); + RTLIL::Cell* cell = module->addCell(stringf("$__box%u__", oldBoxNum), box_lookup.at(boxUniqueId)); + boxes.emplace_back(cell); } } - else - log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); + else if (c == 'a' || c == 'i' || c == 'o' || c == 's') { + uint32_t dataSize = parse_xaiger_literal(f); + f.ignore(dataSize); + log_debug("ignoring '%c'\n", c); + } + else { + break; + } } post_process(); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2d1ce318a..6b8936958 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -30,7 +30,7 @@ "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ "&mfs; &ps -l" #else -#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l; &verify -s" #endif @@ -311,7 +311,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) abc9_script = abc9_script.erase(pos, strlen("&mfs")); - abc9_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); + abc9_script += stringf("; &write -n %s/output.aig", tempdir_name.c_str()); abc9_script = add_echos_to_abc9_cmd(abc9_script); for (size_t i = 0; i+1 < abc9_script.size(); i++) -- cgit v1.2.3 From 49c2e59b2a4fce770bdaa74177adff0ee995f90d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Dec 2019 15:44:19 -0800 Subject: Fix comment --- techlibs/xilinx/abc9_xc7.box | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index 24b1898a4..4e632c0fa 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -107,7 +107,7 @@ $__ABC9_LUT6 2000 0 7 1 # SLICEM/A6LUT + F7BMUX # Box to emulate comb/seq behaviour of RAMD128 # Inputs: A S0 S1 S2 S3 S4 S5 S6 -# Outputs: DPO SPO +# Outputs: Y $__ABC9_LUT7 2001 0 8 1 0 1047 1036 877 812 643 532 478 -- cgit v1.2.3 From 3eed8835b5911c4c635e0cade0978987c09c7ab5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 12 Dec 2019 14:56:15 -0800 Subject: abc9_map.v: fix Xilinx LUTRAM --- techlibs/xilinx/abc9_map.v | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 49000ea25..d04cdb5eb 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -393,8 +393,8 @@ module RAM32X1D ( .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4) ); - \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(DPO)); - \$__ABC9_LUT6 spo (.A(\$SPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(SPO)); + \$__ABC9_LUT6 spo (.A(\$SPO ), .S({1'b1, A4, A3, A2, A1, A0}), .Y(SPO)); + \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({1'b1, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); endmodule module RAM64X1D ( @@ -416,8 +416,8 @@ module RAM64X1D ( .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5), .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5) ); - \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(DPO)); - \$__ABC9_LUT6 spo (.A(\$SPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(SPO)); + \$__ABC9_LUT6 spo (.A(\$SPO ), .S({A5, A4, A3, A2, A1, A0}), .Y(SPO)); + \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); endmodule module RAM128X1D ( @@ -438,8 +438,8 @@ module RAM128X1D ( .A(A), .DPRA(DPRA) ); - \$__ABC9_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO)); \$__ABC9_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO)); + \$__ABC9_LUT7 dpo (.A(\$DPO ), .S(DPRA), .Y(DPO)); endmodule module SRL16E ( @@ -455,7 +455,7 @@ module SRL16E ( .Q(\$Q ), .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D) ); - \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A0, A1, A2, A3, 1'b1}), .Y(Q)); + \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); endmodule module SRLC32E ( -- cgit v1.2.3 From fce6bad6ae22a3e14115202b05b50ae4a69b5a93 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 12 Dec 2019 15:02:46 -0800 Subject: Remove 'clkpart' entry in CHANGELOG --- CHANGELOG | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index d9d261fbc..a49c27b05 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -53,7 +53,6 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "check -mapped" - Added checking of SystemVerilog always block types (always_comb, always_latch and always_ff) - - Added "clkpart" pass Yosys 0.8 .. Yosys 0.9 ---------------------- -- cgit v1.2.3 From c0339bbbf16cee8121417f69305c7601122ff70c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 13 Dec 2019 16:21:09 -0800 Subject: Name inputs/outputs of aiger 'i%d' and 'o%d' --- frontends/aiger/aigerparse.cc | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 8ff690464..65a9e30ae 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -610,11 +610,12 @@ void AigerReader::parse_aiger_binary() std::string line; // Parse inputs + int digits = ceil(log10(I)); for (unsigned i = 1; i <= I; ++i) { log_debug2("%d is an input\n", i); - RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); + RTLIL::Wire *wire = module->addWire(stringf("\\i%0*d", digits, i)); wire->port_input = true; - log_assert(!wire->port_output); + module->connect(createWireIfNotExists(module, i << 1), wire); inputs.push_back(wire); } @@ -664,23 +665,15 @@ void AigerReader::parse_aiger_binary() } // Parse outputs + digits = ceil(log10(O)); for (unsigned i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); log_debug2("%d is an output\n", l1); - const unsigned variable = l1 >> 1; - const bool invert = l1 & 1; - RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "_b" the right suffix? - RTLIL::Wire *wire = module->wire(wire_name); - if (!wire) - wire = createWireIfNotExists(module, l1); - else if (wire->port_input || wire->port_output) { - RTLIL::Wire *new_wire = module->addWire(NEW_ID); - module->connect(new_wire, wire); - wire = new_wire; - } + RTLIL::Wire *wire = module->addWire(stringf("\\o%0*d", digits, i)); wire->port_output = true; + module->connect(wire, createWireIfNotExists(module, l1)); outputs.push_back(wire); } std::getline(f, line); // Ignore up to start of next line -- 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(-) 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(-) 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(-) 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(-) 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 d9bf7061cd6a5efc20c053bc96d05650f0fa3a14 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 16:48:31 -0800 Subject: Put $__ABC9_{FF_,ASYNC} into same clock domain as abc9_flop --- passes/techmap/abc9.cc | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8f2d45b62..34e122e7b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1095,7 +1095,7 @@ struct Abc9Pass : public Pass { std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; - for (auto cell : all_cells) { + for (auto cell : all_cells) for (auto &conn : cell->connections()) for (auto bit : assign_map(conn.second)) if (bit.wire != nullptr) { @@ -1111,6 +1111,7 @@ struct Abc9Pass : public Pass { } } + for (auto cell : all_cells) { auto inst_module = design->module(cell->type); if (!inst_module || !inst_module->attributes.count("\\abc9_flop")) continue; @@ -1121,10 +1122,7 @@ struct Abc9Pass : public Pass { SigSpec abc9_clock = assign_map(abc9_clock_wire); unassigned_cells.erase(cell); - expand_queue.insert(cell); expand_queue_up.insert(cell); - expand_queue_down.insert(cell); - clkdomain_t key(abc9_clock, cell->type); assigned_cells[key].insert(cell->name); assigned_cells_reverse[cell] = key; @@ -1141,6 +1139,30 @@ struct Abc9Pass : public Pass { log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); log_assert(r2.second); + + // Also assign these special ABC9 cells to the + // same clock domain + for (auto b : cell_to_bit_down[cell]) + for (auto c : bit_to_cell_down[b]) + if (c->type == "$__ABC9_FF_") { + cell = c; + unassigned_cells.erase(cell); + assigned_cells[key].insert(cell->name); + assigned_cells_reverse[cell] = key; + break; + } + for (auto b : cell_to_bit_down[cell]) + for (auto c : bit_to_cell_down[b]) + if (c->type == "$__ABC9_ASYNC") { + cell = c; + unassigned_cells.erase(cell); + assigned_cells[key].insert(cell->name); + assigned_cells_reverse[cell] = key; + break; + } + + expand_queue.insert(cell); + expand_queue_down.insert(cell); } while (!expand_queue_up.empty() || !expand_queue_down.empty()) @@ -1153,7 +1175,7 @@ struct Abc9Pass : public Pass { for (auto bit : cell_to_bit_up[cell]) for (auto c : bit_to_cell_up[bit]) - if (unassigned_cells.count(c) && !c->type.in("$__ABC9_FF_", "$__ABC9_ASYNC_")) { + if (unassigned_cells.count(c)) { unassigned_cells.erase(c); next_expand_queue_up.insert(c); assigned_cells[key].insert(c->name); -- cgit v1.2.3 From aed67dd020575a393b21a65baebcce1d1f49d22a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 18:41:56 -0800 Subject: abc9 needs a clean afterwards --- tests/simple_abc9/run-test.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh index 0d4262005..bc921daa9 100755 --- a/tests/simple_abc9/run-test.sh +++ b/tests/simple_abc9/run-test.sh @@ -20,10 +20,12 @@ fi cp ../simple/*.v . cp ../simple/*.sv . DOLLAR='?' -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-n 300 -p '\ +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-n 300 -p '\ hierarchy; \ synth -run coarse; \ opt -full; \ - techmap; abc9 -lut 4 -box ../abc.box; \ + techmap; \ + abc9 -lut 4 -box ../abc.box; \ + clean; \ check -assert; \ select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'" -- 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(-) 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(-) 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 0875a078710a2d60ec3c55e9b5a87d97fd643f3b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 17 Dec 2019 15:43:21 -0800 Subject: read_xaiger to cope with optional '\n' after 'c' --- frontends/aiger/aigerparse.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 65a9e30ae..abc2f4144 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -379,8 +379,8 @@ void AigerReader::parse_xaiger(const dict &box_lookup) int c = f.get(); if (c != 'c') log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); - c = f.get(); - log_assert(c == '\n'); + if (f.peek() == '\n') + f.get(); // Parse footer (symbol table, comments, etc.) std::string s; -- 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 +++++++++++-------------------------------- frontends/aiger/aigerparse.cc | 27 +++------------ 2 files changed, 24 insertions(+), 84 deletions(-) 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 { diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index abc2f4144..613723966 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -887,16 +887,7 @@ void AigerReader::post_process() // simply connect the latter to the former RTLIL::Wire* existing = module->wire(escaped_s); if (!existing) { - if (escaped_s.ends_with("$inout.out")) { - wire->port_output = false; - RTLIL::Wire *in_wire = module->wire(escaped_s.substr(1, escaped_s.size()-11)); - log_assert(in_wire); - log_assert(in_wire->port_input && !in_wire->port_output); - in_wire->port_output = true; - module->connect(in_wire, wire); - } - else - module->rename(wire, escaped_s); + module->rename(wire, escaped_s); } else { wire->port_output = false; @@ -908,19 +899,9 @@ void AigerReader::post_process() std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index); RTLIL::Wire* existing = module->wire(indexed_name); if (!existing) { - if (escaped_s.ends_with("$inout.out")) { - wire->port_output = false; - RTLIL::Wire *in_wire = module->wire(stringf("%s[%d]", escaped_s.substr(1, escaped_s.size()-11).c_str(), index)); - log_assert(in_wire); - log_assert(in_wire->port_input && !in_wire->port_output); - in_wire->port_output = true; - module->connect(in_wire, wire); - } - else { - module->rename(wire, indexed_name); - if (wideports) - wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); - } + module->rename(wire, indexed_name); + if (wideports) + wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); } else { module->connect(wire, existing); -- cgit v1.2.3 From a6fdb9f5c1262e57d4aa292778c947773d9fe04d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 17 Dec 2019 15:50:01 -0800 Subject: aiger frontend to user shorter, $-prefixed, names --- frontends/aiger/aigerparse.cc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 613723966..9cb05dfb3 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -255,7 +255,7 @@ end_of_header: else log_abort(); - RTLIL::Wire* n0 = module->wire("\\__0__"); + RTLIL::Wire* n0 = module->wire("$0"); if (n0) module->connect(n0, State::S0); @@ -316,14 +316,14 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera { const unsigned variable = literal >> 1; const bool invert = literal & 1; - RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); + RTLIL::IdString wire_name(stringf("$%d%s", variable, invert ? "b" : "")); RTLIL::Wire *wire = module->wire(wire_name); if (wire) return wire; log_debug2("Creating %s\n", wire_name.c_str()); wire = module->addWire(wire_name); wire->port_input = wire->port_output = false; if (!invert) return wire; - RTLIL::IdString wire_inv_name(stringf("\\__%d__", variable)); + RTLIL::IdString wire_inv_name(stringf("$%d", variable)); RTLIL::Wire *wire_inv = module->wire(wire_inv_name); if (wire_inv) { if (module->cell(wire_inv_name)) return wire; @@ -335,7 +335,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera } log_debug2("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - module->addNotGate(stringf("\\__%d__$not", variable), wire_inv, wire); + module->addNotGate(stringf("$%d$not", variable), wire_inv, wire); return wire; } @@ -372,7 +372,7 @@ void AigerReader::parse_xaiger(const dict &box_lookup) else log_abort(); - RTLIL::Wire* n0 = module->wire("\\__0__"); + RTLIL::Wire* n0 = module->wire("$0"); if (n0) module->connect(n0, State::S0); @@ -396,13 +396,13 @@ void AigerReader::parse_xaiger(const dict &box_lookup) uint32_t rootNodeID = parse_xaiger_literal(f); uint32_t cutLeavesM = parse_xaiger_literal(f); log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); - RTLIL::Wire *output_sig = module->wire(stringf("\\__%d__", rootNodeID)); + RTLIL::Wire *output_sig = module->wire(stringf("$%d", rootNodeID)); uint32_t nodeID; RTLIL::SigSpec input_sig; for (unsigned j = 0; j < cutLeavesM; ++j) { nodeID = parse_xaiger_literal(f); log_debug2("\t%u\n", nodeID); - RTLIL::Wire *wire = module->wire(stringf("\\__%d__", nodeID)); + RTLIL::Wire *wire = module->wire(stringf("$%d", nodeID)); log_assert(wire); input_sig.append(wire); } @@ -419,10 +419,10 @@ void AigerReader::parse_xaiger(const dict &box_lookup) log_assert(o.wire == nullptr); lut_mask[gray] = o.data; } - RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID)); + RTLIL::Cell *output_cell = module->cell(stringf("$%d$and", rootNodeID)); log_assert(output_cell); module->remove(output_cell); - module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); + module->addLut(stringf("$%d$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } } else if (c == 'r') { @@ -456,7 +456,7 @@ void AigerReader::parse_xaiger(const dict &box_lookup) uint32_t boxUniqueId = parse_xaiger_literal(f); log_assert(boxUniqueId > 0); uint32_t oldBoxNum = parse_xaiger_literal(f); - RTLIL::Cell* cell = module->addCell(stringf("$__box%u__", oldBoxNum), box_lookup.at(boxUniqueId)); + RTLIL::Cell* cell = module->addCell(stringf("$__box%u", oldBoxNum), box_lookup.at(boxUniqueId)); boxes.emplace_back(cell); } } @@ -544,7 +544,7 @@ void AigerReader::parse_aiger_ascii() log_debug2("%d is an output\n", l1); const unsigned variable = l1 >> 1; const bool invert = l1 & 1; - RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix? + RTLIL::IdString wire_name(stringf("$%d%s", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix? RTLIL::Wire *wire = module->wire(wire_name); if (!wire) wire = createWireIfNotExists(module, l1); @@ -613,7 +613,7 @@ void AigerReader::parse_aiger_binary() int digits = ceil(log10(I)); for (unsigned i = 1; i <= I; ++i) { log_debug2("%d is an input\n", i); - RTLIL::Wire *wire = module->addWire(stringf("\\i%0*d", digits, i)); + RTLIL::Wire *wire = module->addWire(stringf("$i%0*d", digits, i)); wire->port_input = true; module->connect(createWireIfNotExists(module, i << 1), wire); inputs.push_back(wire); @@ -671,7 +671,7 @@ void AigerReader::parse_aiger_binary() log_error("Line %u cannot be interpreted as an output!\n", line_count); log_debug2("%d is an output\n", l1); - RTLIL::Wire *wire = module->addWire(stringf("\\o%0*d", digits, i)); + RTLIL::Wire *wire = module->addWire(stringf("$o%0*d", digits, i)); wire->port_output = true; module->connect(wire, createWireIfNotExists(module, l1)); outputs.push_back(wire); @@ -915,7 +915,7 @@ void AigerReader::post_process() wire->attributes["\\init"] = init; } else if (type == "box") { - RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); + RTLIL::Cell* cell = module->cell(stringf("$__box%d", variable)); if (cell) { // ABC could have optimised this box away module->rename(cell, escaped_s); for (const auto &i : cell->connections()) { -- cgit v1.2.3 From b1b99e421eac9f960a08a17fe69e56a0b0661ebb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 17 Dec 2019 16:10:40 -0800 Subject: Use pool<> instead of std::set<> to preserver ordering --- passes/techmap/abc9.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 34e122e7b..1f7585318 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1082,18 +1082,18 @@ struct Abc9Pass : public Pass { assign_map.set(module); std::vector all_cells = module->selected_cells(); - std::set unassigned_cells(all_cells.begin(), all_cells.end()); + pool unassigned_cells(all_cells.begin(), all_cells.end()); - std::set expand_queue, next_expand_queue; - std::set expand_queue_up, next_expand_queue_up; - std::set expand_queue_down, next_expand_queue_down; + pool expand_queue, next_expand_queue; + pool expand_queue_up, next_expand_queue_up; + pool expand_queue_down, next_expand_queue_down; typedef std::pair clkdomain_t; std::map> assigned_cells; std::map assigned_cells_reverse; - std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; - std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; + std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; + std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; for (auto cell : all_cells) for (auto &conn : cell->connections()) -- cgit v1.2.3 From 5e206199f4639dbebfc9e2a0e6a8170db449b088 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 17 Dec 2019 16:11:37 -0800 Subject: Bump ABC for upstream fix --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e484656c8..44d064896 100644 --- a/Makefile +++ b/Makefile @@ -128,7 +128,7 @@ bumpversion: # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = 451f2b0 +ABCREV = 02393a2 ABCPULL = 1 ABCURL ?= https://github.com/berkeley-abc/abc ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 -- cgit v1.2.3 From c9c77a90b32a1fea64823dbded7eeddf826617a1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 17 Dec 2019 16:11:54 -0800 Subject: Remove &verify -s --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 1f7585318..8027c5131 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -30,7 +30,7 @@ "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ "&mfs; &ps -l" #else -#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l; &verify -s" +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" #endif -- cgit v1.2.3 From 76ba06a79ea917a0e515aa0e99ae41f42e8bddc9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Dec 2019 15:14:38 -0800 Subject: Bump ABC again --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 44d064896..e268a4281 100644 --- a/Makefile +++ b/Makefile @@ -128,7 +128,7 @@ bumpversion: # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = 02393a2 +ABCREV = c4b12fa ABCPULL = 1 ABCURL ?= https://github.com/berkeley-abc/abc ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 -- cgit v1.2.3 From 979bf36fb00ec61ec7e27f074079e0464be03be7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Dec 2019 11:23:41 -0800 Subject: Split into $__ABC9_ASYNC[01], do not add cell->type to clkdomain_t --- passes/techmap/abc9.cc | 10 +++++----- techlibs/xilinx/abc9_map.v | 32 ++++++++++++++++++-------------- techlibs/xilinx/abc9_model.v | 14 +++++++++++--- techlibs/xilinx/abc9_unmap.v | 3 ++- techlibs/xilinx/abc9_xc7.box | 26 ++++++++++++++++---------- techlibs/xilinx/cells_sim.v | 16 ++++++++-------- 6 files changed, 60 insertions(+), 41 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8027c5131..2bf495ec4 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1088,7 +1088,7 @@ struct Abc9Pass : public Pass { pool expand_queue_up, next_expand_queue_up; pool expand_queue_down, next_expand_queue_down; - typedef std::pair clkdomain_t; + typedef SigSpec clkdomain_t; std::map> assigned_cells; std::map assigned_cells_reverse; @@ -1123,7 +1123,7 @@ struct Abc9Pass : public Pass { unassigned_cells.erase(cell); expand_queue_up.insert(cell); - clkdomain_t key(abc9_clock, cell->type); + clkdomain_t key(abc9_clock); assigned_cells[key].insert(cell->name); assigned_cells_reverse[cell] = key; @@ -1236,19 +1236,19 @@ struct Abc9Pass : public Pass { log_header(design, "Summary of detected clock domains:\n"); for (auto &it : assigned_cells) - log(" %d cells in clk=%s cell=%s\n", GetSize(it.second), log_signal(it.first.first), log_id(it.first.second)); + log(" %d cells in clk=%s\n", GetSize(it.second), log_signal(it.first)); design->selection_stack.emplace_back(false); design->selected_active_module = module->name.str(); for (auto &it : assigned_cells) { std::string target = delay_target; if (target.empty()) { - for (auto b : assign_map(it.first.first)) + for (auto b : assign_map(it.first)) if (b.wire) { auto jt = b.wire->attributes.find("\\abc9_period"); if (jt != b.wire->attributes.end()) { target = stringf("-D %d", jt->second.as_int()); - log("Target period = %s ps for clock domain %s\n", target.c_str(), log_signal(it.first.first)); + log("Target period = %s ps for clock domain %s\n", target.c_str(), log_signal(it.first)); break; } } diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index d04cdb5eb..b36d93c5d 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -161,8 +161,10 @@ module FDCE (output Q, input C, CE, D, CLR); // control is not directly // supported by abc9 but its // behaviour is captured by - // $__ABC9_ASYNC below + // $__ABC9_ASYNC1 below ); + // Since this is an async flop, async behaviour is dealt with here + \$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); end else begin assign Q = QQ; @@ -177,13 +179,12 @@ module FDCE (output Q, input C, CE, D, CLR); // control is not directly // supported by abc9 but its // behaviour is captured by - // $__ABC9_ASYNC below + // $__ABC9_ASYNC0 below ); + // Since this is an async flop, async behaviour is dealt with here + \$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); end endgenerate \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); - // Since this is an async flop, async behaviour is also dealt with - // using the $_ABC9_ASYNC box by abc9_map.v - \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; @@ -203,8 +204,9 @@ module FDCE_1 (output Q, input C, CE, D, CLR); // control is not directly // supported by abc9 but its // behaviour is captured by - // $__ABC9_ASYNC below + // $__ABC9_ASYNC1 below ); + \$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); end else begin assign Q = QQ; @@ -216,11 +218,11 @@ module FDCE_1 (output Q, input C, CE, D, CLR); // control is not directly // supported by abc9 but its // behaviour is captured by - // $__ABC9_ASYNC below + // $__ABC9_ASYNC0 below ); + \$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); end endgenerate \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); - \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; @@ -247,8 +249,9 @@ module FDPE (output Q, input C, CE, D, PRE); // control is not directly // supported by abc9 but its // behaviour is captured by - // $__ABC9_ASYNC below + // $__ABC9_ASYNC0 below ); + \$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); end else begin assign Q = QQ; @@ -263,11 +266,11 @@ module FDPE (output Q, input C, CE, D, PRE); // control is not directly // supported by abc9 but its // behaviour is captured by - // $__ABC9_ASYNC below + // $__ABC9_ASYNC1 below ); + \$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); end endgenerate \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); - \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; @@ -287,8 +290,9 @@ module FDPE_1 (output Q, input C, CE, D, PRE); // control is not directly // supported by abc9 but its // behaviour is captured by - // $__ABC9_ASYNC below + // $__ABC9_ASYNC0 below ); + \$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); end else begin assign Q = QQ; @@ -300,11 +304,11 @@ module FDPE_1 (output Q, input C, CE, D, PRE); // control is not directly // supported by abc9 but its // behaviour is captured by - // $__ABC9_ASYNC below + // $__ABC9_ASYNC1 below ); + \$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); end endgenerate \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); - \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; diff --git a/techlibs/xilinx/abc9_model.v b/techlibs/xilinx/abc9_model.v index cc0e5ec41..c793396a4 100644 --- a/techlibs/xilinx/abc9_model.v +++ b/techlibs/xilinx/abc9_model.v @@ -33,11 +33,19 @@ endmodule module \$__ABC9_FF_ (input D, output Q); endmodule +// Box to emulate async behaviour of FDC* (* abc_box_id = 1000 *) -module \$__ABC9_ASYNC (input A, S, output Y); +module \$__ABC9_ASYNC0 (input A, S, output Y); + assign Y = S ? 1'b0 : A; endmodule -// Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} +// Box to emulate async behaviour of FDP* +(* abc_box_id = 1001 *) +module \$__ABC9_ASYNC1 (input A, S, output Y); + assign Y = S ? 1'b0 : A; +endmodule + +// Box to emulate comb/seq behaviour of RAM{32,64} and SRL{16,32} // Necessary since RAMD* and SRL* have both combinatorial (i.e. // same-cycle read operation) and sequential (write operation // is only committed on the next clock edge). @@ -46,7 +54,7 @@ endmodule (* abc9_box_id=2000 *) module \$__ABC9_LUT6 (input A, input [5:0] S, output Y); endmodule -// Box to emulate comb/seq behaviour of RAMD128 +// Box to emulate comb/seq behaviour of RAM128 (* abc9_box_id=2001 *) module \$__ABC9_LUT7 (input A, input [6:0] S, output Y); endmodule diff --git a/techlibs/xilinx/abc9_unmap.v b/techlibs/xilinx/abc9_unmap.v index 21fe78d08..46526007d 100644 --- a/techlibs/xilinx/abc9_unmap.v +++ b/techlibs/xilinx/abc9_unmap.v @@ -20,7 +20,8 @@ // ============================================================================ -module \$__ABC9_ASYNC (input A, S, output Y); +(* techmap_celltype = "$__ABC9_ASYNC0 $__ABC9_ASYNC1" *) +module \$__ABC9_ASYNC01 (input A, S, output Y); assign Y = A; endmodule diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index 4e632c0fa..a2d119284 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -41,10 +41,16 @@ CARRY4 4 1 10 8 592 540 520 356 - 512 548 292 - 228 580 526 507 398 385 508 528 378 380 114 -# Box to emulate async behaviour of FD[CP]* +# Box to emulate async behaviour of FDC* # Inputs: A S # Outputs: Y -$__ABC9_ASYNC 1000 0 2 1 +$__ABC9_ASYNC0 1000 1 2 1 +0 764 + +# Box to emulate async behaviour of FDP* +# Inputs: A S +# Outputs: Y +$__ABC9_ASYNC1 1001 1 2 1 0 764 # The following FD*.{CE,R,CLR,PRE) are offset by 46ps to @@ -54,42 +60,42 @@ $__ABC9_ASYNC 1000 0 2 1 # Inputs: C CE D R \$currQ # Outputs: Q -FDRE 1001 1 5 1 +FDRE 1100 1 5 1 0 151 0 446 0 # Inputs: C CE D R \$currQ # Outputs: Q -FDRE_1 1002 1 5 1 +FDRE_1 1101 1 5 1 0 151 0 446 0 # Inputs: C CE CLR D \$currQ # Outputs: Q -FDCE 1003 1 5 1 +FDCE 1102 1 5 1 0 151 806 0 0 # Inputs: C CE CLR D \$currQ # Outputs: Q -FDCE_1 1004 1 5 1 +FDCE_1 1103 1 5 1 0 151 806 0 0 # Inputs: C CE D PRE \$currQ # Outputs: Q -FDPE 1005 1 5 1 +FDPE 1104 1 5 1 0 151 0 806 0 # Inputs: C CE D PRE \$currQ # Outputs: Q -FDPE_1 1006 1 5 1 +FDPE_1 1105 1 5 1 0 151 0 806 0 # Inputs: C CE D S \$currQ # Outputs: Q -FDSE 1007 1 5 1 +FDSE 1106 1 5 1 0 151 0 446 0 # Inputs: C CE D S \$currQ # Outputs: Q -FDSE_1 1008 1 5 1 +FDSE_1 1107 1 5 1 0 151 0 446 0 # SLICEM/A6LUT diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 7941a94cd..d7dff8975 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -283,7 +283,7 @@ endmodule // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L238-L250 -(* abc9_box_id=1001, lib_whitebox, abc9_flop *) +(* abc9_box_id=1100, lib_whitebox, abc9_flop *) module FDRE ( (* abc9_arrival=303 *) output reg Q, @@ -307,7 +307,7 @@ module FDRE ( endcase endgenerate endmodule -(* abc9_box_id=1002, lib_whitebox, abc9_flop *) +(* abc9_box_id=1101, lib_whitebox, abc9_flop *) module FDRE_1 ( (* abc9_arrival=303 *) output reg Q, @@ -355,7 +355,7 @@ module FDRSE ( Q <= d; endmodule -(* abc9_box_id=1003, lib_whitebox, abc9_flop *) +(* abc9_box_id=1102, lib_whitebox, abc9_flop *) module FDCE ( (* abc9_arrival=303 *) output reg Q, @@ -381,7 +381,7 @@ module FDCE ( endcase endgenerate endmodule -(* abc9_box_id=1004, lib_whitebox, abc9_flop *) +(* abc9_box_id=1103, lib_whitebox, abc9_flop *) module FDCE_1 ( (* abc9_arrival=303 *) output reg Q, @@ -394,7 +394,7 @@ module FDCE_1 ( always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; endmodule -(* abc9_box_id=1005, lib_whitebox, abc9_flop *) +(* abc9_box_id=1104, lib_whitebox, abc9_flop *) module FDPE ( (* abc9_arrival=303 *) output reg Q, @@ -420,7 +420,7 @@ module FDPE ( endcase endgenerate endmodule -(* abc9_box_id=1006, lib_whitebox, abc9_flop *) +(* abc9_box_id=1105, lib_whitebox, abc9_flop *) module FDPE_1 ( (* abc9_arrival=303 *) output reg Q, @@ -433,7 +433,7 @@ module FDPE_1 ( always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule -(* abc9_box_id=1007, lib_whitebox, abc9_flop *) +(* abc9_box_id=1106, lib_whitebox, abc9_flop *) module FDSE ( (* abc9_arrival=303 *) output reg Q, @@ -457,7 +457,7 @@ module FDSE ( endcase endgenerate endmodule -(* abc9_box_id=1008, lib_whitebox, abc9_flop *) +(* abc9_box_id=1107, lib_whitebox, abc9_flop *) module FDSE_1 ( (* abc9_arrival=303 *) output reg Q, -- cgit v1.2.3 From 45f0f1486bbe30cdbf22c94b165879568af1a37a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Dec 2019 11:24:39 -0800 Subject: Add RAM{32,64}M to abc9_map.v --- techlibs/xilinx/abc9_map.v | 78 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index b36d93c5d..d2d7d9114 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -446,6 +446,84 @@ module RAM128X1D ( \$__ABC9_LUT7 dpo (.A(\$DPO ), .S(DPRA), .Y(DPO)); endmodule +module RAM32M ( + output [1:0] DOA, + output [1:0] DOB, + output [1:0] DOC, + output [1:0] DOD, + (* techmap_autopurge *) input [4:0] ADDRA, + (* techmap_autopurge *) input [4:0] ADDRB, + (* techmap_autopurge *) input [4:0] ADDRC, + (* techmap_autopurge *) input [4:0] ADDRD, + (* techmap_autopurge *) input [1:0] DIA, + (* techmap_autopurge *) input [1:0] DIB, + (* techmap_autopurge *) input [1:0] DIC, + (* techmap_autopurge *) input [1:0] DID, + (* techmap_autopurge *) input WCLK, + (* techmap_autopurge *) input WE +); + parameter [63:0] INIT_A = 64'h0000000000000000; + parameter [63:0] INIT_B = 64'h0000000000000000; + parameter [63:0] INIT_C = 64'h0000000000000000; + parameter [63:0] INIT_D = 64'h0000000000000000; + parameter [0:0] IS_WCLK_INVERTED = 1'b0; + wire [1:0] \$DOA , \$DOB , \$DOC , \$DOD ; + RAM32M #( + .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), + .IS_WCLK_INVERTED(IS_WCLK_INVERTED) + ) _TECHMAP_REPLACE_ ( + .DOA(\$DOA ), .DOB(\$DOB ), .DOC(\$DOC ), .DOD(\$DOD ), + .WCLK(WCLK), .WE(WE), + .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), + .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) + ); + \$__ABC9_LUT6 doa0 (.A(\$DOA [0]), .S({1'b1, ADDRA}), .Y(DOA[0])); + \$__ABC9_LUT6 doa1 (.A(\$DOA [1]), .S({1'b1, ADDRA}), .Y(DOA[1])); + \$__ABC9_LUT6 dob0 (.A(\$DOB [0]), .S({1'b1, ADDRB}), .Y(DOB[0])); + \$__ABC9_LUT6 dob1 (.A(\$DOB [1]), .S({1'b1, ADDRB}), .Y(DOB[1])); + \$__ABC9_LUT6 doc0 (.A(\$DOC [0]), .S({1'b1, ADDRC}), .Y(DOC[0])); + \$__ABC9_LUT6 doc1 (.A(\$DOC [1]), .S({1'b1, ADDRC}), .Y(DOC[1])); + \$__ABC9_LUT6 dod0 (.A(\$DOD [0]), .S({1'b1, ADDRD}), .Y(DOD[0])); + \$__ABC9_LUT6 dod1 (.A(\$DOD [1]), .S({1'b1, ADDRD}), .Y(DOD[1])); +endmodule + +module RAM64M ( + output DOA, + output DOB, + output DOC, + output DOD, + (* techmap_autopurge *) input [5:0] ADDRA, + (* techmap_autopurge *) input [5:0] ADDRB, + (* techmap_autopurge *) input [5:0] ADDRC, + (* techmap_autopurge *) input [5:0] ADDRD, + (* techmap_autopurge *) input DIA, + (* techmap_autopurge *) input DIB, + (* techmap_autopurge *) input DIC, + (* techmap_autopurge *) input DID, + (* techmap_autopurge *) input WCLK, + (* techmap_autopurge *) input WE +); + parameter [63:0] INIT_A = 64'h0000000000000000; + parameter [63:0] INIT_B = 64'h0000000000000000; + parameter [63:0] INIT_C = 64'h0000000000000000; + parameter [63:0] INIT_D = 64'h0000000000000000; + parameter [0:0] IS_WCLK_INVERTED = 1'b0; + wire \$DOA , \$DOB , \$DOC , \$DOD ; + RAM64M #( + .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), + .IS_WCLK_INVERTED(IS_WCLK_INVERTED) + ) _TECHMAP_REPLACE_ ( + .DOA(\$DOA ), .DOB(\$DOB ), .DOC(\$DOC ), .DOD(\$DOD ), + .WCLK(WCLK), .WE(WE), + .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), + .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) + ); + \$__ABC9_LUT6 doa (.A(\$DOA ), .S(ADDRA), .Y(DOA)); + \$__ABC9_LUT6 dob (.A(\$DOB ), .S(ADDRB), .Y(DOB)); + \$__ABC9_LUT6 doc (.A(\$DOC ), .S(ADDRC), .Y(DOC)); + \$__ABC9_LUT6 dod (.A(\$DOD ), .S(ADDRD), .Y(DOD)); +endmodule + module SRL16E ( output Q, (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D -- cgit v1.2.3 From 2fcf683af427aa86ff57bcbed8b027e97fd03f96 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 21 Dec 2019 11:56:41 +0100 Subject: Make iopad option default for all xilinx flows --- techlibs/xilinx/synth_xilinx.cc | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 971089b28..006679eb1 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -64,7 +64,7 @@ struct SynthXilinxPass : public ScriptPass log(" (this feature is experimental and incomplete)\n"); log("\n"); log(" -ise\n"); - log(" generate an output netlist suitable for ISE (enables -iopad)\n"); + log(" generate an output netlist suitable for ISE\n"); log("\n"); log(" -nobram\n"); log(" do not use block RAM cells in output netlist\n"); @@ -84,11 +84,8 @@ struct SynthXilinxPass : public ScriptPass log(" -nodsp\n"); log(" do not use DSP48E1s to implement multipliers and associated logic\n"); log("\n"); - log(" -iopad\n"); - log(" enable I/O buffer insertion (selected automatically by -ise)\n"); - log("\n"); log(" -noiopad\n"); - log(" disable I/O buffer insertion (only useful with -ise)\n"); + log(" disable I/O buffer insertion\n"); log("\n"); log(" -noclkbuf\n"); log(" disable automatic clock buffer insertion\n"); @@ -122,7 +119,7 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, family; - bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram, abc9; + bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram, abc9; bool flatten_before_abc; int widemux; @@ -136,7 +133,6 @@ struct SynthXilinxPass : public ScriptPass retime = false; vpr = false; ise = false; - iopad = false; noiopad = false; noclkbuf = false; nocarry = false; @@ -212,10 +208,6 @@ struct SynthXilinxPass : public ScriptPass ise = true; continue; } - if (args[argidx] == "-iopad") { - iopad = true; - continue; - } if (args[argidx] == "-noiopad") { noiopad = true; continue; @@ -282,7 +274,6 @@ struct SynthXilinxPass : public ScriptPass void script() YS_OVERRIDE { - bool do_iopad = iopad || (ise && !noiopad); std::string ff_map_file; if (help_mode) ff_map_file = "+/xilinx/{family}_ff_map.v"; @@ -514,8 +505,8 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_cells")) { // Needs to be done before logic optimization, so that inverters (OE vs T) are handled. - if (help_mode || do_iopad) - run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top", "(only if '-iopad' or '-ise' and not '-noiopad')"); + if (help_mode || !noiopad) + run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top", "(only if not '-noiopad')"); std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v"; if (widemux > 0) techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux); -- cgit v1.2.3 From 477e43d921d204c6bc6403109fea6506802c948c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 21 Dec 2019 13:18:44 +0100 Subject: Fix xilinx tests, when iopads are default --- tests/arch/xilinx/add_sub.ys | 2 +- tests/arch/xilinx/adffs.ys | 8 ++++---- tests/arch/xilinx/bug1460.ys | 2 +- tests/arch/xilinx/counter.ys | 2 +- tests/arch/xilinx/dffs.ys | 4 ++-- tests/arch/xilinx/dsp_fastfir.ys | 2 +- tests/arch/xilinx/fsm.ys | 2 +- tests/arch/xilinx/latches.ys | 6 +++--- tests/arch/xilinx/logic.ys | 2 +- tests/arch/xilinx/lutram.ys | 14 +++++++------- tests/arch/xilinx/macc.ys | 4 ++-- tests/arch/xilinx/mul.ys | 2 +- tests/arch/xilinx/mul_unsigned.ys | 2 +- tests/arch/xilinx/mux.ys | 8 ++++---- tests/arch/xilinx/shifter.ys | 2 +- tests/arch/xilinx/tribuf.ys | 6 ++++-- tests/arch/xilinx/xilinx_dffopt.ys | 18 +++++++++--------- 17 files changed, 44 insertions(+), 42 deletions(-) diff --git a/tests/arch/xilinx/add_sub.ys b/tests/arch/xilinx/add_sub.ys index 9dbddce47..920717a3d 100644 --- a/tests/arch/xilinx/add_sub.ys +++ b/tests/arch/xilinx/add_sub.ys @@ -7,5 +7,5 @@ cd top # Constrain all select calls below inside the top module select -assert-count 14 t:LUT2 select -assert-count 6 t:MUXCY select -assert-count 8 t:XORCY -select -assert-none t:LUT2 t:MUXCY t:XORCY %% t:* %D +select -assert-none t:LUT2 t:MUXCY t:XORCY t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/adffs.ys b/tests/arch/xilinx/adffs.ys index c0ff6a2e2..ba9ddf90f 100644 --- a/tests/arch/xilinx/adffs.ys +++ b/tests/arch/xilinx/adffs.ys @@ -9,7 +9,7 @@ cd adff # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:FDCE -select -assert-none t:BUFG t:FDCE %% t:* %D +select -assert-none t:BUFG t:FDCE t:IBUF t:OBUF %% t:* %D design -load read @@ -22,7 +22,7 @@ select -assert-count 1 t:BUFG select -assert-count 1 t:FDCE select -assert-count 1 t:INV -select -assert-none t:BUFG t:FDCE t:INV %% t:* %D +select -assert-none t:BUFG t:FDCE t:INV t:IBUF t:OBUF %% t:* %D design -load read @@ -34,7 +34,7 @@ cd dffs # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:FDSE -select -assert-none t:BUFG t:FDSE %% t:* %D +select -assert-none t:BUFG t:FDSE t:IBUF t:OBUF %% t:* %D design -load read @@ -47,4 +47,4 @@ select -assert-count 1 t:BUFG select -assert-count 1 t:FDRE_1 select -assert-count 1 t:INV -select -assert-none t:BUFG t:FDRE_1 t:INV %% t:* %D +select -assert-none t:BUFG t:FDRE_1 t:INV t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/bug1460.ys b/tests/arch/xilinx/bug1460.ys index 2018071cc..73fb662dc 100644 --- a/tests/arch/xilinx/bug1460.ys +++ b/tests/arch/xilinx/bug1460.ys @@ -31,4 +31,4 @@ EOT synth_xilinx cd register_file select -assert-count 32 t:RAM32M -select -assert-none t:* t:BUFG %d t:RAM32M %d +select -assert-none t:* t:BUFG %d t:IBUF %d t:OBUF %d t:RAM32M %d diff --git a/tests/arch/xilinx/counter.ys b/tests/arch/xilinx/counter.ys index 604acdbfc..e4217bbaf 100644 --- a/tests/arch/xilinx/counter.ys +++ b/tests/arch/xilinx/counter.ys @@ -11,4 +11,4 @@ select -assert-count 8 t:FDCE select -assert-count 1 t:INV select -assert-count 7 t:MUXCY select -assert-count 8 t:XORCY -select -assert-none t:BUFG t:FDCE t:INV t:MUXCY t:XORCY %% t:* %D +select -assert-none t:BUFG t:FDCE t:INV t:MUXCY t:XORCY t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/dffs.ys b/tests/arch/xilinx/dffs.ys index 0bba4858f..b2cb70323 100644 --- a/tests/arch/xilinx/dffs.ys +++ b/tests/arch/xilinx/dffs.ys @@ -9,7 +9,7 @@ cd dff # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:FDRE -select -assert-none t:BUFG t:FDRE %% t:* %D +select -assert-none t:BUFG t:FDRE t:IBUF t:OBUF %% t:* %D design -load read @@ -21,5 +21,5 @@ cd dffe # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:FDRE -select -assert-none t:BUFG t:FDRE %% t:* %D +select -assert-none t:BUFG t:FDRE t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/dsp_fastfir.ys b/tests/arch/xilinx/dsp_fastfir.ys index 0067a822b..05e1785d8 100644 --- a/tests/arch/xilinx/dsp_fastfir.ys +++ b/tests/arch/xilinx/dsp_fastfir.ys @@ -66,4 +66,4 @@ EOT synth_xilinx cd fastfir_dynamictaps select -assert-count 2 t:DSP48E1 -select -assert-none t:* t:DSP48E1 %d t:BUFG %d +select -assert-none t:* t:DSP48E1 %d t:BUFG %d t:IBUF %d t:OBUF %d diff --git a/tests/arch/xilinx/fsm.ys b/tests/arch/xilinx/fsm.ys index f03400fe7..d60695e2c 100644 --- a/tests/arch/xilinx/fsm.ys +++ b/tests/arch/xilinx/fsm.ys @@ -16,4 +16,4 @@ select -assert-count 1 t:FDSE select -assert-count 1 t:LUT2 select -assert-count 3 t:LUT5 select -assert-count 1 t:LUT6 -select -assert-none t:BUFG t:FDRE t:FDSE t:LUT2 t:LUT5 t:LUT6 %% t:* %D +select -assert-none t:BUFG t:IBUF t:OBUF t:FDRE t:FDSE t:LUT2 t:LUT5 t:LUT6 %% t:* %D diff --git a/tests/arch/xilinx/latches.ys b/tests/arch/xilinx/latches.ys index c87a8e38b..c1caea27a 100644 --- a/tests/arch/xilinx/latches.ys +++ b/tests/arch/xilinx/latches.ys @@ -8,7 +8,7 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd latchp # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE -select -assert-none t:LDCE %% t:* %D +select -assert-none t:LDCE t:IBUF t:OBUF %% t:* %D design -load read @@ -20,7 +20,7 @@ cd latchn # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE select -assert-count 1 t:INV -select -assert-none t:LDCE t:INV %% t:* %D +select -assert-none t:LDCE t:INV t:IBUF t:OBUF %% t:* %D design -load read @@ -32,4 +32,4 @@ cd latchsr # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE select -assert-count 2 t:LUT3 -select -assert-none t:LDCE t:LUT3 %% t:* %D +select -assert-none t:LDCE t:LUT3 t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/logic.ys b/tests/arch/xilinx/logic.ys index d5b5c1a37..2372cca61 100644 --- a/tests/arch/xilinx/logic.ys +++ b/tests/arch/xilinx/logic.ys @@ -8,4 +8,4 @@ cd top # Constrain all select calls below inside the top module select -assert-count 1 t:INV select -assert-count 6 t:LUT2 select -assert-count 2 t:LUT4 -select -assert-none t:INV t:LUT2 t:LUT4 %% t:* %D +select -assert-none t:INV t:LUT2 t:LUT4 t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/lutram.ys b/tests/arch/xilinx/lutram.ys index 6c9d1eae1..951517fa9 100644 --- a/tests/arch/xilinx/lutram.ys +++ b/tests/arch/xilinx/lutram.ys @@ -14,7 +14,7 @@ #select -assert-count 1 t:BUFG #select -assert-count 8 t:FDRE #select -assert-count 8 t:RAM16X1D -#select -assert-none t:BUFG t:FDRE t:RAM16X1D %% t:* %D +#select -assert-none t:BUFG t:FDRE t:RAM16X1D t:IBUF t:OBUF %% t:* %D design -reset @@ -34,7 +34,7 @@ cd lutram_1w1r select -assert-count 1 t:BUFG select -assert-count 8 t:FDRE select -assert-count 8 t:RAM32X1D -select -assert-none t:BUFG t:FDRE t:RAM32X1D %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM32X1D t:IBUF t:OBUF %% t:* %D design -reset @@ -54,7 +54,7 @@ cd lutram_1w1r select -assert-count 1 t:BUFG select -assert-count 8 t:FDRE select -assert-count 8 t:RAM64X1D -select -assert-none t:BUFG t:FDRE t:RAM64X1D %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM64X1D t:IBUF t:OBUF %% t:* %D design -reset @@ -74,7 +74,7 @@ cd lutram_1w3r select -assert-count 1 t:BUFG select -assert-count 24 t:FDRE select -assert-count 4 t:RAM32M -select -assert-none t:BUFG t:FDRE t:RAM32M %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM32M t:IBUF t:OBUF %% t:* %D design -reset @@ -94,7 +94,7 @@ cd lutram_1w3r select -assert-count 1 t:BUFG select -assert-count 24 t:FDRE select -assert-count 8 t:RAM64M -select -assert-none t:BUFG t:FDRE t:RAM64M %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM64M t:IBUF t:OBUF %% t:* %D design -reset @@ -114,7 +114,7 @@ cd lutram_1w1r select -assert-count 1 t:BUFG select -assert-count 6 t:FDRE select -assert-count 1 t:RAM32M -select -assert-none t:BUFG t:FDRE t:RAM32M %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM32M t:IBUF t:OBUF %% t:* %D design -reset @@ -134,4 +134,4 @@ cd lutram_1w1r select -assert-count 1 t:BUFG select -assert-count 6 t:FDRE select -assert-count 2 t:RAM64M -select -assert-none t:BUFG t:FDRE t:RAM64M %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM64M t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/macc.ys b/tests/arch/xilinx/macc.ys index 11e959976..0869a8dae 100644 --- a/tests/arch/xilinx/macc.ys +++ b/tests/arch/xilinx/macc.ys @@ -12,7 +12,7 @@ cd macc # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:FDRE select -assert-count 1 t:DSP48E1 -select -assert-none t:BUFG t:FDRE t:DSP48E1 %% t:* %D +select -assert-none t:BUFG t:FDRE t:DSP48E1 t:IBUF t:OBUF %% t:* %D design -load read hierarchy -top macc2 @@ -29,4 +29,4 @@ select -assert-count 1 t:DSP48E1 select -assert-count 1 t:FDRE select -assert-count 1 t:LUT2 select -assert-count 40 t:LUT3 -select -assert-none t:BUFG t:DSP48E1 t:FDRE t:LUT2 t:LUT3 %% t:* %D +select -assert-none t:BUFG t:DSP48E1 t:FDRE t:LUT2 t:LUT3 t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/mul.ys b/tests/arch/xilinx/mul.ys index d76814966..100de6629 100644 --- a/tests/arch/xilinx/mul.ys +++ b/tests/arch/xilinx/mul.ys @@ -6,4 +6,4 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd top # Constrain all select calls below inside the top module select -assert-count 1 t:DSP48E1 -select -assert-none t:DSP48E1 %% t:* %D +select -assert-none t:DSP48E1 t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/mul_unsigned.ys b/tests/arch/xilinx/mul_unsigned.ys index 62495b90c..59ead5cda 100644 --- a/tests/arch/xilinx/mul_unsigned.ys +++ b/tests/arch/xilinx/mul_unsigned.ys @@ -8,4 +8,4 @@ cd mul_unsigned # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:DSP48E1 select -assert-count 30 t:FDRE -select -assert-none t:DSP48E1 t:FDRE t:BUFG %% t:* %D +select -assert-none t:DSP48E1 t:FDRE t:BUFG t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/mux.ys b/tests/arch/xilinx/mux.ys index 388272449..faad64cc5 100644 --- a/tests/arch/xilinx/mux.ys +++ b/tests/arch/xilinx/mux.ys @@ -8,7 +8,7 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd mux2 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT3 -select -assert-none t:LUT3 %% t:* %D +select -assert-none t:LUT3 t:IBUF t:OBUF %% t:* %D design -load read @@ -19,7 +19,7 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd mux4 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT6 -select -assert-none t:LUT6 %% t:* %D +select -assert-none t:LUT6 t:IBUF t:OBUF %% t:* %D design -load read @@ -31,7 +31,7 @@ cd mux8 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT3 select -assert-count 2 t:LUT6 -select -assert-none t:LUT3 t:LUT6 %% t:* %D +select -assert-none t:LUT3 t:LUT6 t:IBUF t:OBUF %% t:* %D design -load read @@ -44,4 +44,4 @@ select -assert-min 5 t:LUT6 select -assert-max 7 t:LUT6 select -assert-max 2 t:MUXF7 -select -assert-none t:LUT6 t:MUXF7 %% t:* %D +select -assert-none t:LUT6 t:MUXF7 t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/shifter.ys b/tests/arch/xilinx/shifter.ys index 455437f18..4d63ba9c2 100644 --- a/tests/arch/xilinx/shifter.ys +++ b/tests/arch/xilinx/shifter.ys @@ -8,4 +8,4 @@ cd top # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 8 t:FDRE -select -assert-none t:BUFG t:FDRE %% t:* %D +select -assert-none t:BUFG t:FDRE t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/xilinx/tribuf.ys b/tests/arch/xilinx/tribuf.ys index 4697703ca..55e20c37b 100644 --- a/tests/arch/xilinx/tribuf.ys +++ b/tests/arch/xilinx/tribuf.ys @@ -8,5 +8,7 @@ equiv_opt -assert -map +/xilinx/cells_sim.v -map +/simcells.v synth_xilinx # equ design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd tristate # Constrain all select calls below inside the top module # TODO :: Tristate logic not yet supported; see https://github.com/YosysHQ/yosys/issues/1225 -select -assert-count 1 t:$_TBUF_ -select -assert-none t:$_TBUF_ %% t:* %D +select -assert-count 2 t:IBUF +select -assert-count 1 t:INV +select -assert-count 1 t:OBUFT +select -assert-none t:IBUF t:INV t:OBUFT %% t:* %D diff --git a/tests/arch/xilinx/xilinx_dffopt.ys b/tests/arch/xilinx/xilinx_dffopt.ys index dc036acfd..5dbe11b27 100644 --- a/tests/arch/xilinx/xilinx_dffopt.ys +++ b/tests/arch/xilinx/xilinx_dffopt.ys @@ -28,7 +28,7 @@ clean select -assert-count 1 t:FDRE select -assert-count 1 t:LUT6 select -assert-count 3 t:LUT2 -select -assert-none t:FDRE t:LUT6 t:LUT2 %% t:* %D +select -assert-none t:FDRE t:LUT6 t:LUT2 t:IBUF t:OBUF %% t:* %D design -load t0 @@ -39,7 +39,7 @@ clean select -assert-count 1 t:FDRE select -assert-count 1 t:LUT4 select -assert-count 3 t:LUT2 -select -assert-none t:FDRE t:LUT4 t:LUT2 %% t:* %D +select -assert-none t:FDRE t:LUT4 t:LUT2 t:IBUF t:OBUF %% t:* %D design -reset @@ -74,7 +74,7 @@ clean select -assert-count 1 t:FDSE select -assert-count 1 t:LUT6 select -assert-count 3 t:LUT2 -select -assert-none t:FDSE t:LUT6 t:LUT2 %% t:* %D +select -assert-none t:FDSE t:LUT6 t:LUT2 t:IBUF t:OBUF %% t:* %D design -load t0 @@ -85,7 +85,7 @@ clean select -assert-count 1 t:FDSE select -assert-count 1 t:LUT4 select -assert-count 3 t:LUT2 -select -assert-none t:FDSE t:LUT4 t:LUT2 %% t:* %D +select -assert-none t:FDSE t:LUT4 t:LUT2 t:IBUF t:OBUF %% t:* %D design -reset @@ -120,7 +120,7 @@ clean select -assert-count 1 t:FDCE select -assert-count 1 t:LUT4 select -assert-count 3 t:LUT2 -select -assert-none t:FDCE t:LUT4 t:LUT2 %% t:* %D +select -assert-none t:FDCE t:LUT4 t:LUT2 t:IBUF t:OBUF %% t:* %D design -reset @@ -154,7 +154,7 @@ clean select -assert-count 1 t:FDSE select -assert-count 1 t:LUT5 select -assert-count 2 t:LUT2 -select -assert-none t:FDSE t:LUT5 t:LUT2 %% t:* %D +select -assert-none t:FDSE t:LUT5 t:LUT2 t:IBUF t:OBUF %% t:* %D design -load t0 @@ -164,7 +164,7 @@ clean select -assert-count 1 t:FDSE select -assert-count 2 t:LUT2 -select -assert-none t:FDSE t:LUT2 %% t:* %D +select -assert-none t:FDSE t:LUT2 t:IBUF t:OBUF %% t:* %D design -reset @@ -200,7 +200,7 @@ clean select -assert-count 1 t:FDRSE select -assert-count 1 t:LUT6 select -assert-count 4 t:LUT2 -select -assert-none t:FDRSE t:LUT6 t:LUT2 %% t:* %D +select -assert-none t:FDRSE t:LUT6 t:LUT2 t:IBUF t:OBUF %% t:* %D design -load t0 @@ -211,6 +211,6 @@ clean select -assert-count 1 t:FDRSE select -assert-count 1 t:LUT4 select -assert-count 4 t:LUT2 -select -assert-none t:FDRSE t:LUT4 t:LUT2 %% t:* %D +select -assert-none t:FDRSE t:LUT4 t:LUT2 t:IBUF t:OBUF %% t:* %D design -reset -- cgit v1.2.3 From 1937091f622a37d8050e5cc1e7c486707fd90b2f Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 21 Dec 2019 13:21:45 +0100 Subject: iopad no op for compatibility with old scripts --- techlibs/xilinx/synth_xilinx.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 006679eb1..c66e1d750 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -208,6 +208,9 @@ struct SynthXilinxPass : public ScriptPass ise = true; continue; } + if (args[argidx] == "-iopad") { + continue; + } if (args[argidx] == "-noiopad") { noiopad = true; continue; -- cgit v1.2.3 From 436fea9e6990c66369d7c30b571920ae115efb44 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 21 Dec 2019 20:23:23 +0100 Subject: Addressed review comments --- techlibs/xilinx/synth_xilinx.cc | 5 +++-- tests/arch/xilinx/tribuf.ys | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c66e1d750..90ab688e5 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -85,7 +85,8 @@ struct SynthXilinxPass : public ScriptPass log(" do not use DSP48E1s to implement multipliers and associated logic\n"); log("\n"); log(" -noiopad\n"); - log(" disable I/O buffer insertion\n"); + log(" disable I/O buffer insertion (useful for hierarchical or \n"); + log(" out-of-context flows)\n"); log("\n"); log(" -noclkbuf\n"); log(" disable automatic clock buffer insertion\n"); @@ -210,7 +211,7 @@ struct SynthXilinxPass : public ScriptPass } if (args[argidx] == "-iopad") { continue; - } + } if (args[argidx] == "-noiopad") { noiopad = true; continue; diff --git a/tests/arch/xilinx/tribuf.ys b/tests/arch/xilinx/tribuf.ys index 55e20c37b..eaccab126 100644 --- a/tests/arch/xilinx/tribuf.ys +++ b/tests/arch/xilinx/tribuf.ys @@ -7,7 +7,6 @@ synth equiv_opt -assert -map +/xilinx/cells_sim.v -map +/simcells.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd tristate # Constrain all select calls below inside the top module -# TODO :: Tristate logic not yet supported; see https://github.com/YosysHQ/yosys/issues/1225 select -assert-count 2 t:IBUF select -assert-count 1 t:INV select -assert-count 1 t:OBUFT -- 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(-) 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 509070f82fa458ccc8515eb4b09f1e4ab7068110 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Dec 2019 08:36:20 -0800 Subject: Disable clock domain partitioning in Yosys pass, let ABC do it --- passes/techmap/abc9.cc | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index def347c21..857f1a0a6 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1080,14 +1080,17 @@ struct Abc9Pass : public Pass { assign_map.set(module); + typedef SigSpec clkdomain_t; + dict clk_to_mergeability; + std::vector all_cells = module->selected_cells(); +#if 0 pool unassigned_cells(all_cells.begin(), all_cells.end()); pool expand_queue, next_expand_queue; pool expand_queue_up, next_expand_queue_up; pool expand_queue_down, next_expand_queue_down; - typedef SigSpec clkdomain_t; std::map> assigned_cells; std::map assigned_cells_reverse; @@ -1109,6 +1112,7 @@ struct Abc9Pass : public Pass { bit_to_cell_up[bit].insert(cell); } } +#endif for (auto cell : all_cells) { auto inst_module = design->module(cell->type); @@ -1120,13 +1124,16 @@ struct Abc9Pass : public Pass { log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); SigSpec abc9_clock = assign_map(abc9_clock_wire); + clkdomain_t key(abc9_clock); +#if 0 unassigned_cells.erase(cell); expand_queue_up.insert(cell); - clkdomain_t key(abc9_clock); assigned_cells[key].insert(cell->name); assigned_cells_reverse[cell] = key; +#endif - auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), 1)); + auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1)); + auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); log_assert(r2.second); Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str())); @@ -1139,6 +1146,7 @@ struct Abc9Pass : public Pass { r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); log_assert(r2.second); +#if 0 // Also assign these special ABC9 cells to the // same clock domain for (auto b : cell_to_bit_down[cell]) @@ -1162,8 +1170,10 @@ struct Abc9Pass : public Pass { expand_queue.insert(cell); expand_queue_down.insert(cell); +#endif } +#if 0 while (!expand_queue_up.empty() || !expand_queue_down.empty()) { if (!expand_queue_up.empty()) @@ -1234,11 +1244,14 @@ struct Abc9Pass : public Pass { } log_header(design, "Summary of detected clock domains:\n"); - for (auto &it : assigned_cells) + for (auto &it : assigned_cells) { log(" %d cells in clk=%s\n", GetSize(it.second), log_signal(it.first)); + } +#endif - design->selection_stack.emplace_back(false); design->selected_active_module = module->name.str(); +#if 0 + design->selection_stack.emplace_back(false); for (auto &it : assigned_cells) { std::string target = delay_target; if (target.empty()) { @@ -1254,12 +1267,15 @@ struct Abc9Pass : public Pass { } RTLIL::Selection& sel = design->selection_stack.back(); sel.selected_members[module->name] = std::move(it.second); +#endif abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, false, "$", - keepff, target, lutin_shared, fast_mode, show_tempdir, + keepff, delay_target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, wire_delay, box_lookup, nomfs); +#if 0 assign_map.set(module); } design->selection_stack.pop_back(); +#endif design->selected_active_module.clear(); } -- 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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 d45869855c6fc86dc6a0225018a8e383866dacb4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 16:44:57 -0800 Subject: Add #1598 testcase --- tests/arch/ecp5/bug1598.ys | 16 ++++++++++++++++ tests/arch/ice40/bug1598.ys | 16 ++++++++++++++++ tests/arch/xilinx/bug1598.ys | 16 ++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 tests/arch/ecp5/bug1598.ys create mode 100644 tests/arch/ice40/bug1598.ys create mode 100644 tests/arch/xilinx/bug1598.ys diff --git a/tests/arch/ecp5/bug1598.ys b/tests/arch/ecp5/bug1598.ys new file mode 100644 index 000000000..1d1682fcd --- /dev/null +++ b/tests/arch/ecp5/bug1598.ys @@ -0,0 +1,16 @@ +read_verilog < Date: Fri, 27 Dec 2019 16:57:08 -0800 Subject: Nitpick cleanup for ecp5 --- techlibs/ecp5/cells_sim.v | 12 ++---------- techlibs/ecp5/synth_ecp5.cc | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index f467218cc..0d3ec4e5b 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -1,5 +1,6 @@ // --------------------------------------- +(* lib_whitebox *) module LUT4(input A, B, C, D, output Z); parameter [15:0] INIT = 16'h0000; wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0]; @@ -31,13 +32,8 @@ module CCU2C( // First half wire LUT4_0, LUT2_0; -`ifdef _ABC - assign LUT4_0 = INIT0[{D0, C0, B0, A0}]; - assign LUT2_0 = INIT0[{2'b00, B0, A0}]; -`else LUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0)); LUT2 #(.INIT(INIT0[3:0])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0)); -`endif wire gated_cin_0 = (INJECT1_0 == "YES") ? 1'b0 : CIN; assign S0 = LUT4_0 ^ gated_cin_0; @@ -46,13 +42,8 @@ module CCU2C( // Second half wire LUT4_1, LUT2_1; -`ifdef _ABC - assign LUT4_1 = INIT1[{D1, C1, B1, A1}]; - assign LUT2_1 = INIT1[{2'b00, B1, A1}]; -`else LUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1)); LUT2 #(.INIT(INIT1[3:0])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1)); -`endif wire gated_cin_1 = (INJECT1_1 == "YES") ? 1'b0 : cout_0; assign S1 = LUT4_1 ^ gated_cin_1; @@ -209,6 +200,7 @@ endmodule // --------------------------------------- +(* lib_whitebox *) module LUT2(input A, B, output Z); parameter [3:0] INIT = 4'h0; wire [1:0] s1 = B ? INIT[ 3:2] : INIT[1:0]; diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index b71bb2395..a0ea6d1f9 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -230,7 +230,7 @@ struct SynthEcp5Pass : public ScriptPass { if (check_label("begin")) { - run("read_verilog -D_ABC -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v"); + run("read_verilog -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); } -- cgit v1.2.3 From 011f749ecfe37711552be7b9c7712931e82c3757 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 28 Dec 2019 02:15:11 -0800 Subject: Update resource count --- tests/arch/ecp5/mux.ys | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/arch/ecp5/mux.ys b/tests/arch/ecp5/mux.ys index 92463aa32..22866832d 100644 --- a/tests/arch/ecp5/mux.ys +++ b/tests/arch/ecp5/mux.ys @@ -39,8 +39,8 @@ proc equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module -select -assert-count 8 t:L6MUX21 -select -assert-count 26 t:LUT4 -select -assert-count 12 t:PFUMX +select -assert-count 12 t:L6MUX21 +select -assert-count 34 t:LUT4 +select -assert-count 17 t:PFUMX select -assert-none t:LUT4 t:L6MUX21 t:PFUMX %% t:* %D -- cgit v1.2.3 From ec2539480867fcc05c904043747b2f3cba9a9866 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 28 Dec 2019 03:16:28 -0800 Subject: Rename abc9.cc -> abc9_techmap.cc --- passes/techmap/Makefile.inc | 1 + passes/techmap/abc9.cc | 1310 ---------------------------------------- passes/techmap/abc9_techmap.cc | 1310 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1311 insertions(+), 1310 deletions(-) delete mode 100644 passes/techmap/abc9.cc create mode 100644 passes/techmap/abc9_techmap.cc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index cd357d72a..a7c8d8c2b 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -8,6 +8,7 @@ OBJS += passes/techmap/libparse.o ifeq ($(ENABLE_ABC),1) OBJS += passes/techmap/abc.o OBJS += passes/techmap/abc9.o +OBJS += passes/techmap/abc9_techmap.o ifneq ($(ABCEXTERNAL),) passes/techmap/abc.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' passes/techmap/abc9.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc deleted file mode 100644 index d03e5da8e..000000000 --- a/passes/techmap/abc9.cc +++ /dev/null @@ -1,1310 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Eddie Hung - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -// [[CITE]] ABC -// Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification -// http://www.eecs.berkeley.edu/~alanmi/abc/ - -#if 0 -// Based on &flow3 - better QoR but more experimental -#define ABC_COMMAND_LUT "&st; &ps -l; &sweep -v; &scorr; " \ - "&st; &if {W}; &save; &st; &syn2; &if {W} -v; &save; &load; "\ - "&st; &if -g -K 6; &dch -f; &if {W} -v; &save; &load; "\ - "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ - "&mfs; &ps -l" -#else -#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" -#endif - - -#define ABC_FAST_COMMAND_LUT "&st; &if {W} {D}" - -#include "kernel/register.h" -#include "kernel/sigtools.h" -#include "kernel/celltypes.h" -#include "kernel/cost.h" -#include "kernel/log.h" -#include -#include -#include -#include -#include -#include - -#ifndef _WIN32 -# include -# include -#endif - -#include "frontends/aiger/aigerparse.h" -#include "kernel/utils.h" - -#ifdef YOSYS_LINK_ABC -extern "C" int Abc_RealMain(int argc, char *argv[]); -#endif - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -bool markgroups; -int map_autoidx; -SigMap assign_map; -RTLIL::Module *module; - -bool clk_polarity, en_polarity; -RTLIL::SigSpec clk_sig, en_sig; - -inline std::string remap_name(RTLIL::IdString abc9_name) -{ - return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1); -} - -void handle_loops(RTLIL::Design *design) -{ - Pass::call(design, "scc -set_attr abc9_scc_id {}"); - - // For every unique SCC found, (arbitrarily) find the first - // cell in the component, and select (and mark) all its output - // wires - pool ids_seen; - for (auto cell : module->cells()) { - auto it = cell->attributes.find(ID(abc9_scc_id)); - if (it != cell->attributes.end()) { - auto r = ids_seen.insert(it->second); - if (r.second) { - for (auto &c : cell->connections_) { - if (c.second.is_fully_const()) continue; - if (cell->output(c.first)) { - SigBit b = c.second.as_bit(); - Wire *w = b.wire; - if (w->port_input) { - // In this case, hopefully the loop break has been already created - // Get the non-prefixed wire - Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str())); - log_assert(wo != nullptr); - log_assert(wo->port_output); - log_assert(b.offset < GetSize(wo)); - c.second = RTLIL::SigBit(wo, b.offset); - } - else { - // Create a new output/input loop break - w->port_input = true; - w = module->wire(stringf("%s.abco", w->name.c_str())); - if (!w) { - w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire)); - w->port_output = true; - } - else { - log_assert(w->port_input); - log_assert(b.offset < GetSize(w)); - } - w->set_bool_attribute(ID(abc9_scc_break)); - c.second = RTLIL::SigBit(w, b.offset); - } - } - } - } - cell->attributes.erase(it); - } - } - - module->fixup_ports(); -} - -std::string add_echos_to_abc9_cmd(std::string str) -{ - std::string new_str, token; - for (size_t i = 0; i < str.size(); i++) { - token += str[i]; - if (str[i] == ';') { - while (i+1 < str.size() && str[i+1] == ' ') - i++; - new_str += "echo + " + token + " " + token + " "; - token.clear(); - } - } - - if (!token.empty()) { - if (!new_str.empty()) - new_str += "echo + " + token + "; "; - new_str += token; - } - - return new_str; -} - -std::string fold_abc9_cmd(std::string str) -{ - std::string token, new_str = " "; - int char_counter = 10; - - for (size_t i = 0; i <= str.size(); i++) { - if (i < str.size()) - token += str[i]; - if (i == str.size() || str[i] == ';') { - if (char_counter + token.size() > 75) - new_str += "\n ", char_counter = 14; - new_str += token, char_counter += token.size(); - token.clear(); - } - } - - return new_str; -} - -std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir) -{ - if (show_tempdir) - return text; - - while (1) { - size_t pos = text.find(tempdir_name); - if (pos == std::string::npos) - break; - text = text.substr(0, pos) + "" + text.substr(pos + GetSize(tempdir_name)); - } - - std::string selfdir_name = proc_self_dirname(); - if (selfdir_name != "/") { - while (1) { - size_t pos = text.find(selfdir_name); - if (pos == std::string::npos) - break; - text = text.substr(0, pos) + "/" + text.substr(pos + GetSize(selfdir_name)); - } - } - - return text; -} - -struct abc9_output_filter -{ - bool got_cr; - int escape_seq_state; - std::string linebuf; - std::string tempdir_name; - bool show_tempdir; - - abc9_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir) - { - got_cr = false; - escape_seq_state = 0; - } - - void next_char(char ch) - { - if (escape_seq_state == 0 && ch == '\033') { - escape_seq_state = 1; - return; - } - if (escape_seq_state == 1) { - escape_seq_state = ch == '[' ? 2 : 0; - return; - } - if (escape_seq_state == 2) { - if ((ch < '0' || '9' < ch) && ch != ';') - escape_seq_state = 0; - return; - } - escape_seq_state = 0; - if (ch == '\r') { - got_cr = true; - return; - } - if (ch == '\n') { - log("ABC: %s\n", replace_tempdir(linebuf, tempdir_name, show_tempdir).c_str()); - got_cr = false, linebuf.clear(); - return; - } - if (got_cr) - got_cr = false, linebuf.clear(); - linebuf += ch; - } - - void next_line(const std::string &line) - { - //int pi, po; - //if (sscanf(line.c_str(), "Start-point = pi%d. End-point = po%d.", &pi, &po) == 2) { - // log("ABC: Start-point = pi%d (%s). End-point = po%d (%s).\n", - // pi, pi_map.count(pi) ? pi_map.at(pi).c_str() : "???", - // po, po_map.count(po) ? po_map.at(po).c_str() : "???"); - // return; - //} - - for (char ch : line) - next_char(ch); - } -}; - -void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, - bool cleanup, vector lut_costs, bool dff_mode, std::string clk_str, - bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, - bool show_tempdir, std::string box_file, std::string lut_file, - std::string wire_delay, const dict &box_lookup, bool nomfs -) -{ - module = current_module; - map_autoidx = autoidx++; - - if (clk_str != "$") - { - clk_polarity = true; - clk_sig = RTLIL::SigSpec(); - - en_polarity = true; - en_sig = RTLIL::SigSpec(); - } - - if (!clk_str.empty() && clk_str != "$") - { - if (clk_str.find(',') != std::string::npos) { - int pos = clk_str.find(','); - std::string en_str = clk_str.substr(pos+1); - clk_str = clk_str.substr(0, pos); - if (en_str[0] == '!') { - en_polarity = false; - en_str = en_str.substr(1); - } - if (module->wires_.count(RTLIL::escape_id(en_str)) != 0) - en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0)); - } - if (clk_str[0] == '!') { - clk_polarity = false; - clk_str = clk_str.substr(1); - } - if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0) - clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0)); - } - - if (dff_mode && clk_sig.empty()) - log_cmd_error("Clock domain %s not found.\n", clk_str.c_str()); - - std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; - if (!cleanup) - tempdir_name[0] = tempdir_name[4] = '_'; - tempdir_name = make_temp_dir(tempdir_name); - log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", - module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); - - std::string abc9_script; - - if (!lut_costs.empty()) { - abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); - if (!box_file.empty()) - abc9_script += stringf("read_box -v %s; ", box_file.c_str()); - } - else - if (!lut_file.empty()) { - abc9_script += stringf("read_lut %s; ", lut_file.c_str()); - if (!box_file.empty()) - abc9_script += stringf("read_box -v %s; ", box_file.c_str()); - } - else - log_abort(); - - abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); - - if (!script_file.empty()) { - if (script_file[0] == '+') { - for (size_t i = 1; i < script_file.size(); i++) - if (script_file[i] == '\'') - abc9_script += "'\\''"; - else if (script_file[i] == ',') - abc9_script += " "; - else - abc9_script += script_file[i]; - } else - abc9_script += stringf("source %s", script_file.c_str()); - } else if (!lut_costs.empty() || !lut_file.empty()) { - //bool all_luts_cost_same = true; - //for (int this_cost : lut_costs) - // if (this_cost != lut_costs.front()) - // all_luts_cost_same = false; - abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; - //if (all_luts_cost_same && !fast_mode) - // abc9_script += "; lutpack {S}"; - } else - log_abort(); - - //if (script_file.empty() && !delay_target.empty()) - // for (size_t pos = abc9_script.find("dretime;"); pos != std::string::npos; pos = abc9_script.find("dretime;", pos+1)) - // abc9_script = abc9_script.substr(0, pos) + "dretime; retime -o {D};" + abc9_script.substr(pos+8); - - for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos)) - abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3); - - //for (size_t pos = abc9_script.find("{S}"); pos != std::string::npos; pos = abc9_script.find("{S}", pos)) - // abc9_script = abc9_script.substr(0, pos) + lutin_shared + abc9_script.substr(pos+3); - - for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos)) - abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3); - - if (nomfs) - for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) - abc9_script = abc9_script.erase(pos, strlen("&mfs")); - - abc9_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); - abc9_script = add_echos_to_abc9_cmd(abc9_script); - - for (size_t i = 0; i+1 < abc9_script.size(); i++) - if (abc9_script[i] == ';' && abc9_script[i+1] == ' ') - abc9_script[i+1] = '\n'; - - FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); - fprintf(f, "%s\n", abc9_script.c_str()); - fclose(f); - - if (dff_mode || !clk_str.empty()) - { - if (clk_sig.size() == 0) - log("No%s clock domain found. Not extracting any FF cells.\n", clk_str.empty() ? "" : " matching"); - else { - log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); - if (en_sig.size() != 0) - log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); - log("\n"); - } - } - - bool count_output = false; - for (auto port_name : module->ports) { - RTLIL::Wire *port_wire = module->wire(port_name); - log_assert(port_wire); - if (port_wire->port_output) { - count_output = true; - break; - } - } - - log_push(); - - if (count_output) - { - design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = design->selection_stack.back(); - sel.select(module); - - handle_loops(design); - - Pass::call(design, "aigmap"); - - //log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", - // count_gates, GetSize(signal_list), count_input, count_output); - - Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); - - std::string buffer; - std::ifstream ifs; -#if 0 - buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig"); - ifs.open(buffer); - if (ifs.fail()) - log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); - buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); - log_assert(!design->module(ID($__abc9__))); - { - AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); - reader.parse_xaiger(); - } - ifs.close(); - Pass::call(design, stringf("write_verilog -noexpr -norename")); - design->remove(design->module(ID($__abc9__))); -#endif - - design->selection_stack.pop_back(); - - log_header(design, "Executing ABC9.\n"); - - if (!lut_costs.empty()) { - buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); - f = fopen(buffer.c_str(), "wt"); - if (f == NULL) - log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); - for (int i = 0; i < GetSize(lut_costs); i++) - fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i)); - fclose(f); - } - - buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str()); - log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str()); - -#ifndef YOSYS_LINK_ABC - abc9_output_filter filt(tempdir_name, show_tempdir); - int ret = run_command(buffer, std::bind(&abc9_output_filter::next_line, filt, std::placeholders::_1)); -#else - // These needs to be mutable, supposedly due to getopt - char *abc9_argv[5]; - string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str()); - abc9_argv[0] = strdup(exe_file.c_str()); - abc9_argv[1] = strdup("-s"); - abc9_argv[2] = strdup("-f"); - abc9_argv[3] = strdup(tmp_script_name.c_str()); - abc9_argv[4] = 0; - int ret = Abc_RealMain(4, abc9_argv); - free(abc9_argv[0]); - free(abc9_argv[1]); - free(abc9_argv[2]); - free(abc9_argv[3]); -#endif - if (ret != 0) - log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); - - buffer = stringf("%s/%s", tempdir_name.c_str(), "output.aig"); - ifs.open(buffer, std::ifstream::binary); - if (ifs.fail()) - log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); - - buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); - log_assert(!design->module(ID($__abc9__))); - - AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); - reader.parse_xaiger(box_lookup); - ifs.close(); - -#if 0 - Pass::call(design, stringf("write_verilog -noexpr -norename")); -#endif - - log_header(design, "Re-integrating ABC9 results.\n"); - RTLIL::Module *mapped_mod = design->module(ID($__abc9__)); - if (mapped_mod == NULL) - log_error("ABC output file does not contain a module `$__abc9__'.\n"); - - pool output_bits; - for (auto &it : mapped_mod->wires_) { - RTLIL::Wire *w = it.second; - RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w)); - if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx; - if (w->port_output) { - RTLIL::Wire *wire = module->wire(w->name); - log_assert(wire); - for (int i = 0; i < GetSize(w); i++) - output_bits.insert({wire, i}); - } - } - - for (auto &it : module->connections_) { - auto &signal = it.first; - auto bits = signal.bits(); - for (auto &b : bits) - if (output_bits.count(b)) - b = module->addWire(NEW_ID); - signal = std::move(bits); - } - - dict abc9_box; - vector boxes; - for (const auto &it : module->cells_) { - auto cell = it.second; - if (cell->type.in(ID($_AND_), ID($_NOT_))) { - module->remove(cell); - continue; - } - auto jt = abc9_box.find(cell->type); - if (jt == abc9_box.end()) { - RTLIL::Module* box_module = design->module(cell->type); - jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; - } - if (jt->second) - boxes.emplace_back(cell); - } - - dict> bit_drivers, bit_users; - TopoSort toposort; - dict not2drivers; - dict> bit2sinks; - - std::map cell_stats; - for (auto c : mapped_mod->cells()) - { - toposort.node(c->name); - - RTLIL::Cell *cell = nullptr; - if (c->type == ID($_NOT_)) { - RTLIL::SigBit a_bit = c->getPort(ID::A); - RTLIL::SigBit y_bit = c->getPort(ID::Y); - bit_users[a_bit].insert(c->name); - bit_drivers[y_bit].insert(c->name); - - if (!a_bit.wire) { - c->setPort(ID::Y, module->addWire(NEW_ID)); - RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); - log_assert(wire); - module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1); - } - else if (!lut_costs.empty() || !lut_file.empty()) { - RTLIL::Cell* driver_lut = nullptr; - // ABC can return NOT gates that drive POs - if (!a_bit.wire->port_input) { - // If it's not a NOT gate that that comes from a PI directly, - // find the driver LUT and clone that to guarantee that we won't - // increase the max logic depth - // (TODO: Optimise by not cloning unless will increase depth) - RTLIL::IdString driver_name; - if (GetSize(a_bit.wire) == 1) - driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); - else - driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); - driver_lut = mapped_mod->cell(driver_name); - } - - if (!driver_lut) { - // If a driver couldn't be found (could be from PI or box CI) - // then implement using a LUT - cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), - RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), - RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), - RTLIL::Const::from_string("01")); - bit2sinks[cell->getPort(ID::A)].push_back(cell); - cell_stats[ID($lut)]++; - } - else - not2drivers[c] = driver_lut; - continue; - } - else - log_abort(); - if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; - continue; - } - cell_stats[c->type]++; - - RTLIL::Cell *existing_cell = nullptr; - if (c->type == ID($lut)) { - if (GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) { - SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID::A).as_wire()->name)); - SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID::Y).as_wire()->name)); - module->connect(my_y, my_a); - if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx; - log_abort(); - continue; - } - cell = module->addCell(remap_name(c->name), c->type); - } - else { - existing_cell = module->cell(c->name); - log_assert(existing_cell); - cell = module->addCell(remap_name(c->name), c->type); - } - - if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; - if (existing_cell) { - cell->parameters = existing_cell->parameters; - cell->attributes = existing_cell->attributes; - } - else { - cell->parameters = c->parameters; - cell->attributes = c->attributes; - } - for (auto &conn : c->connections()) { - RTLIL::SigSpec newsig; - for (auto c : conn.second.chunks()) { - if (c.width == 0) - continue; - //log_assert(c.width == 1); - if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); - newsig.append(c); - } - cell->setPort(conn.first, newsig); - - if (cell->input(conn.first)) { - for (auto i : newsig) - bit2sinks[i].push_back(cell); - for (auto i : conn.second) - bit_users[i].insert(c->name); - } - if (cell->output(conn.first)) - for (auto i : conn.second) - bit_drivers[i].insert(c->name); - } - } - - for (auto existing_cell : boxes) { - Cell *cell = module->cell(remap_name(existing_cell->name)); - if (cell) { - for (auto &conn : existing_cell->connections()) { - if (!conn.second.is_wire()) - continue; - Wire *wire = conn.second.as_wire(); - if (!wire->get_bool_attribute(ID(abc9_padding))) - continue; - cell->unsetPort(conn.first); - log_debug("Dropping padded port connection for %s (%s) .%s (%s )\n", log_id(cell), cell->type.c_str(), log_id(conn.first), log_signal(conn.second)); - } - module->swap_names(cell, existing_cell); - } - module->remove(existing_cell); - } - - // Copy connections (and rename) from mapped_mod to module - for (auto conn : mapped_mod->connections()) { - if (!conn.first.is_fully_const()) { - auto chunks = conn.first.chunks(); - for (auto &c : chunks) - c.wire = module->wires_.at(remap_name(c.wire->name)); - conn.first = std::move(chunks); - } - if (!conn.second.is_fully_const()) { - auto chunks = conn.second.chunks(); - for (auto &c : chunks) - if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); - conn.second = std::move(chunks); - } - module->connect(conn); - } - - for (auto &it : cell_stats) - log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); - int in_wires = 0, out_wires = 0; - - // Stitch in mapped_mod's inputs/outputs into module - for (auto port : mapped_mod->ports) { - RTLIL::Wire *w = mapped_mod->wire(port); - RTLIL::Wire *wire = module->wire(port); - log_assert(wire); - RTLIL::Wire *remap_wire = module->wire(remap_name(port)); - RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); - log_assert(GetSize(signal) >= GetSize(remap_wire)); - - RTLIL::SigSig conn; - if (w->port_output) { - conn.first = signal; - conn.second = remap_wire; - out_wires++; - module->connect(conn); - } - else if (w->port_input) { - conn.first = remap_wire; - conn.second = signal; - in_wires++; - module->connect(conn); - } - } - - 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); - bool no_loops YS_ATTRIBUTE(unused) = toposort.sort(); - log_assert(no_loops); - - for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) { - RTLIL::Cell *not_cell = mapped_mod->cell(*ii); - log_assert(not_cell); - if (not_cell->type != ID($_NOT_)) - continue; - auto it = not2drivers.find(not_cell); - if (it == not2drivers.end()) - continue; - RTLIL::Cell *driver_lut = it->second; - RTLIL::SigBit a_bit = not_cell->getPort(ID::A); - RTLIL::SigBit y_bit = not_cell->getPort(ID::Y); - RTLIL::Const driver_mask; - - a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); - y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); - - auto jt = bit2sinks.find(a_bit); - if (jt == bit2sinks.end()) - goto clone_lut; - - for (auto sink_cell : jt->second) - if (sink_cell->type != ID($lut)) - goto clone_lut; - - // Push downstream LUTs past inverter - for (auto sink_cell : jt->second) { - SigSpec A = sink_cell->getPort(ID::A); - RTLIL::Const mask = sink_cell->getParam(ID(LUT)); - int index = 0; - for (; index < GetSize(A); index++) - if (A[index] == a_bit) - break; - log_assert(index < GetSize(A)); - int i = 0; - while (i < GetSize(mask)) { - for (int j = 0; j < (1 << index); j++) - std::swap(mask[i+j], mask[i+j+(1 << index)]); - i += 1 << (index+1); - } - A[index] = y_bit; - sink_cell->setPort(ID::A, A); - sink_cell->setParam(ID(LUT), mask); - } - - // Since we have rewritten all sinks (which we know - // to be only LUTs) to be after the inverter, we can - // go ahead and clone the LUT with the expectation - // that the original driving LUT will become dangling - // and get cleaned away -clone_lut: - driver_mask = driver_lut->getParam(ID(LUT)); - for (auto &b : driver_mask.bits) { - if (b == RTLIL::State::S0) b = RTLIL::State::S1; - else if (b == RTLIL::State::S1) b = RTLIL::State::S0; - } - auto cell = module->addLut(NEW_ID, - driver_lut->getPort(ID::A), - y_bit, - driver_mask); - for (auto &bit : cell->connections_.at(ID::A)) { - bit.wire = module->wires_.at(remap_name(bit.wire->name)); - bit2sinks[bit].push_back(cell); - } - } - - // Now 'unexpose' those wires by undoing - // the expose operation -- remove them from PO/PI - // and re-connecting them back together - for (auto wire : module->wires()) { - auto it = wire->attributes.find(ID(abc9_scc_break)); - if (it != wire->attributes.end()) { - wire->attributes.erase(it); - log_assert(wire->port_output); - wire->port_output = false; - std::string name = wire->name.str(); - RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5)); - log_assert(i_wire); - log_assert(i_wire->port_input); - i_wire->port_input = false; - module->connect(i_wire, wire); - } - } - module->fixup_ports(); - - //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); - log("ABC RESULTS: input signals: %8d\n", in_wires); - log("ABC RESULTS: output signals: %8d\n", out_wires); - - design->remove(mapped_mod); - } - else - { - log("Don't call ABC as there is nothing to map.\n"); - } - - if (cleanup) - { - log("Removing temp directory.\n"); - remove_directory(tempdir_name); - } - - log_pop(); -} - -struct Abc9Pass : public Pass { - Abc9Pass() : Pass("abc9", "use ABC9 for technology mapping") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" abc9 [options] [selection]\n"); - log("\n"); - log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); - log("library to a target architecture.\n"); - log("\n"); - log(" -exe \n"); -#ifdef ABCEXTERNAL - log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); -#else - log(" use the specified command instead of \"/yosys-abc\" to execute ABC.\n"); -#endif - log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n"); - log("\n"); - log(" -script \n"); - log(" use the specified ABC script file instead of the default script.\n"); - log("\n"); - log(" if starts with a plus sign (+), then the rest of the filename\n"); - log(" string is interpreted as the command string to be passed to ABC. The\n"); - log(" leading plus sign is removed and all commas (,) in the string are\n"); - log(" replaced with blanks before the string is passed to ABC.\n"); - log("\n"); - log(" if no -script parameter is given, the following scripts are used:\n"); - log("\n"); - log(" for -lut/-luts (only one LUT size):\n"); - log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); - log("\n"); - log(" for -lut/-luts (different LUT sizes):\n"); - log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); - log("\n"); - log(" -fast\n"); - log(" use different default scripts that are slightly faster (at the cost\n"); - log(" of output quality):\n"); - log("\n"); - log(" for -lut/-luts:\n"); - log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str()); - log("\n"); - log(" -D \n"); - log(" set delay target. the string {D} in the default scripts above is\n"); - log(" replaced by this option when used, and an empty string otherwise\n"); - log(" (indicating best possible delay).\n"); -// log(" This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); -// log(" default scripts above.\n"); - log("\n"); -// log(" -S \n"); -// log(" maximum number of LUT inputs shared.\n"); -// log(" (replaces {S} in the default scripts above, default: -S 1)\n"); -// log("\n"); - log(" -lut \n"); - log(" generate netlist using luts of (max) the specified width.\n"); - log("\n"); - log(" -lut :\n"); - log(" generate netlist using luts of (max) the specified width . All\n"); - log(" luts with width <= have constant cost. for luts larger than \n"); - log(" the area cost doubles with each additional input bit. the delay cost\n"); - log(" is still constant for all lut widths.\n"); - log("\n"); - log(" -lut \n"); - log(" pass this file with lut library to ABC.\n"); - log("\n"); - log(" -luts ,,,:,..\n"); - log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); - log(" 2, 3, .. inputs.\n"); - log("\n"); -// log(" -dff\n"); -// log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n"); -// log(" clock domains are automatically partitioned in clock domains and each\n"); -// log(" domain is passed through ABC independently.\n"); -// log("\n"); -// log(" -clk [!][,[!]]\n"); -// log(" use only the specified clock domain. this is like -dff, but only FF\n"); -// log(" cells that belong to the specified clock domain are used.\n"); -// log("\n"); -// log(" -keepff\n"); -// log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n"); -// log(" them, for example for equivalence checking.)\n"); -// log("\n"); - log(" -nocleanup\n"); - log(" when this option is used, the temporary files created by this pass\n"); - log(" are not removed. this is useful for debugging.\n"); - log("\n"); - log(" -showtmp\n"); - log(" print the temp dir name in log. usually this is suppressed so that the\n"); - log(" command output is identical across runs.\n"); - log("\n"); - log(" -markgroups\n"); - log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n"); - log(" this attribute is a unique integer for each ABC process started. This\n"); - log(" is useful for debugging the partitioning of clock domains.\n"); - log("\n"); - log(" -box \n"); - log(" pass this file with box library to ABC. Use with -lut.\n"); - log("\n"); - log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); - log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); - log("ABC on logic snippets extracted from your design. You will not get any useful\n"); - log("output when passing an ABC script that writes a file. Instead write your full\n"); - log("design as BLIF file with write_blif and then load that into ABC externally if\n"); - log("you want to use ABC to convert your design into another format.\n"); - log("\n"); - log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing ABC9 pass (technology mapping using ABC9).\n"); - log_push(); - - assign_map.clear(); - -#ifdef ABCEXTERNAL - std::string exe_file = ABCEXTERNAL; -#else - std::string exe_file = proc_self_dirname() + "yosys-abc"; -#endif - std::string script_file, clk_str, box_file, lut_file; - std::string delay_target, lutin_shared = "-S 1", wire_delay; - bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; - bool show_tempdir = false; - bool nomfs = false; - vector lut_costs; - markgroups = false; - -#if 0 - cleanup = false; - show_tempdir = true; -#endif - -#ifdef _WIN32 -#ifndef ABCEXTERNAL - if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe")) - exe_file = proc_self_dirname() + "..\\yosys-abc"; -#endif -#endif - - size_t argidx; - char pwd [PATH_MAX]; - if (!getcwd(pwd, sizeof(pwd))) { - log_cmd_error("getcwd failed: %s\n", strerror(errno)); - log_abort(); - } - for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-exe" && argidx+1 < args.size()) { - exe_file = args[++argidx]; - continue; - } - if (arg == "-script" && argidx+1 < args.size()) { - script_file = args[++argidx]; - rewrite_filename(script_file); - if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+') - script_file = std::string(pwd) + "/" + script_file; - continue; - } - if (arg == "-D" && argidx+1 < args.size()) { - delay_target = "-D " + args[++argidx]; - continue; - } - //if (arg == "-S" && argidx+1 < args.size()) { - // lutin_shared = "-S " + args[++argidx]; - // continue; - //} - if (arg == "-lut" && argidx+1 < args.size()) { - string arg = args[++argidx]; - if (arg.find_first_not_of("0123456789:") == std::string::npos) { - size_t pos = arg.find_first_of(':'); - int lut_mode = 0, lut_mode2 = 0; - if (pos != string::npos) { - lut_mode = atoi(arg.substr(0, pos).c_str()); - lut_mode2 = atoi(arg.substr(pos+1).c_str()); - } else { - lut_mode = atoi(arg.c_str()); - lut_mode2 = lut_mode; - } - lut_costs.clear(); - for (int i = 0; i < lut_mode; i++) - lut_costs.push_back(1); - for (int i = lut_mode; i < lut_mode2; i++) - lut_costs.push_back(2 << (i - lut_mode)); - } - else { - lut_file = arg; - rewrite_filename(lut_file); - if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+') - lut_file = std::string(pwd) + "/" + lut_file; - } - continue; - } - if (arg == "-luts" && argidx+1 < args.size()) { - lut_costs.clear(); - for (auto &tok : split_tokens(args[++argidx], ",")) { - auto parts = split_tokens(tok, ":"); - if (GetSize(parts) == 0 && !lut_costs.empty()) - lut_costs.push_back(lut_costs.back()); - else if (GetSize(parts) == 1) - lut_costs.push_back(atoi(parts.at(0).c_str())); - else if (GetSize(parts) == 2) - while (GetSize(lut_costs) < atoi(parts.at(0).c_str())) - lut_costs.push_back(atoi(parts.at(1).c_str())); - else - log_cmd_error("Invalid -luts syntax.\n"); - } - continue; - } - if (arg == "-fast") { - fast_mode = true; - continue; - } - //if (arg == "-dff") { - // dff_mode = true; - // continue; - //} - //if (arg == "-clk" && argidx+1 < args.size()) { - // clk_str = args[++argidx]; - // dff_mode = true; - // continue; - //} - //if (arg == "-keepff") { - // keepff = true; - // continue; - //} - if (arg == "-nocleanup") { - cleanup = false; - continue; - } - if (arg == "-showtmp") { - show_tempdir = true; - continue; - } - if (arg == "-markgroups") { - markgroups = true; - continue; - } - if (arg == "-box" && argidx+1 < args.size()) { - box_file = args[++argidx]; - continue; - } - if (arg == "-W" && argidx+1 < args.size()) { - wire_delay = "-W " + args[++argidx]; - continue; - } - if (arg == "-nomfs") { - nomfs = true; - continue; - } - break; - } - extra_args(args, argidx, design); - - // ABC expects a box file for XAIG - if (box_file.empty()) - box_file = "+/dummy.box"; - - rewrite_filename(box_file); - if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+') - box_file = std::string(pwd) + "/" + box_file; - - dict box_lookup; - for (auto m : design->modules()) { - auto it = m->attributes.find(ID(abc9_box_id)); - if (it == m->attributes.end()) - continue; - if (m->name.begins_with("$paramod")) - continue; - auto id = it->second.as_int(); - auto r = box_lookup.insert(std::make_pair(id, m->name)); - if (!r.second) - log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - log_id(m), id, log_id(r.first->second)); - log_assert(r.second); - - RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; - for (auto p : m->ports) { - auto w = m->wire(p); - log_assert(w); - if (w->attributes.count(ID(abc9_carry))) { - if (w->port_input) { - if (carry_in) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); - carry_in = w; - } - else if (w->port_output) { - if (carry_out) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); - carry_out = w; - } - } - } - if (carry_in || carry_out) { - if (carry_in && !carry_out) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); - if (!carry_in && carry_out) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); - // Make carry_in the last PI, and carry_out the last PO - // since ABC requires it this way - auto &ports = m->ports; - for (auto it = ports.begin(); it != ports.end(); ) { - RTLIL::Wire* w = m->wire(*it); - log_assert(w); - if (w == carry_in || w == carry_out) { - it = ports.erase(it); - continue; - } - if (w->port_id > carry_in->port_id) - --w->port_id; - if (w->port_id > carry_out->port_id) - --w->port_id; - log_assert(w->port_input || w->port_output); - log_assert(ports[w->port_id-1] == w->name); - ++it; - } - ports.push_back(carry_in->name); - carry_in->port_id = ports.size(); - ports.push_back(carry_out->name); - carry_out->port_id = ports.size(); - } - } - - for (auto mod : design->selected_modules()) - { - if (mod->attributes.count(ID(abc9_box_id))) - continue; - - if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); - continue; - } - - assign_map.set(mod); - - if (!dff_mode || !clk_str.empty()) { - abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, - delay_target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay, box_lookup, nomfs); - continue; - } - - CellTypes ct(design); - - std::vector all_cells = mod->selected_cells(); - std::set unassigned_cells(all_cells.begin(), all_cells.end()); - - std::set expand_queue, next_expand_queue; - std::set expand_queue_up, next_expand_queue_up; - std::set expand_queue_down, next_expand_queue_down; - - typedef tuple clkdomain_t; - std::map> assigned_cells; - std::map assigned_cells_reverse; - - std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; - std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; - - for (auto cell : all_cells) - { - clkdomain_t key; - - for (auto &conn : cell->connections()) - for (auto bit : conn.second) { - bit = assign_map(bit); - if (bit.wire != nullptr) { - cell_to_bit[cell].insert(bit); - bit_to_cell[bit].insert(cell); - if (ct.cell_input(cell->type, conn.first)) { - cell_to_bit_up[cell].insert(bit); - bit_to_cell_down[bit].insert(cell); - } - if (ct.cell_output(cell->type, conn.first)) { - cell_to_bit_down[cell].insert(bit); - bit_to_cell_up[bit].insert(cell); - } - } - } - - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) - { - key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); - } - else - if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - { - bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); - bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E)))); - } - else - continue; - - unassigned_cells.erase(cell); - expand_queue.insert(cell); - expand_queue_up.insert(cell); - expand_queue_down.insert(cell); - - assigned_cells[key].push_back(cell); - assigned_cells_reverse[cell] = key; - } - - while (!expand_queue_up.empty() || !expand_queue_down.empty()) - { - if (!expand_queue_up.empty()) - { - RTLIL::Cell *cell = *expand_queue_up.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue_up.erase(cell); - - for (auto bit : cell_to_bit_up[cell]) - for (auto c : bit_to_cell_up[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (!expand_queue_down.empty()) - { - RTLIL::Cell *cell = *expand_queue_down.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue_down.erase(cell); - - for (auto bit : cell_to_bit_down[cell]) - for (auto c : bit_to_cell_down[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (expand_queue_up.empty() && expand_queue_down.empty()) { - expand_queue_up.swap(next_expand_queue_up); - expand_queue_down.swap(next_expand_queue_down); - } - } - - while (!expand_queue.empty()) - { - RTLIL::Cell *cell = *expand_queue.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue.erase(cell); - - for (auto bit : cell_to_bit.at(cell)) { - for (auto c : bit_to_cell[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue.insert(c); - assigned_cells[key].push_back(c); - assigned_cells_reverse[c] = key; - } - bit_to_cell[bit].clear(); - } - - if (expand_queue.empty()) - expand_queue.swap(next_expand_queue); - } - - clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); - for (auto cell : unassigned_cells) { - assigned_cells[key].push_back(cell); - assigned_cells_reverse[cell] = key; - } - - log_header(design, "Summary of detected clock domains:\n"); - for (auto &it : assigned_cells) - log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), - std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), - std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); - - for (auto &it : assigned_cells) { - clk_polarity = std::get<0>(it.first); - clk_sig = assign_map(std::get<1>(it.first)); - en_polarity = std::get<2>(it.first); - en_sig = assign_map(std::get<3>(it.first)); - abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$", - keepff, delay_target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay, box_lookup, nomfs); - assign_map.set(mod); - } - } - - assign_map.clear(); - - log_pop(); - } -} Abc9Pass; - -PRIVATE_NAMESPACE_END diff --git a/passes/techmap/abc9_techmap.cc b/passes/techmap/abc9_techmap.cc new file mode 100644 index 000000000..7ff68f382 --- /dev/null +++ b/passes/techmap/abc9_techmap.cc @@ -0,0 +1,1310 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// [[CITE]] ABC +// Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification +// http://www.eecs.berkeley.edu/~alanmi/abc/ + +#if 0 +// Based on &flow3 - better QoR but more experimental +#define ABC_COMMAND_LUT "&st; &ps -l; &sweep -v; &scorr; " \ + "&st; &if {W}; &save; &st; &syn2; &if {W} -v; &save; &load; "\ + "&st; &if -g -K 6; &dch -f; &if {W} -v; &save; &load; "\ + "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ + "&mfs; &ps -l" +#else +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" +#endif + + +#define ABC_FAST_COMMAND_LUT "&st; &if {W} {D}" + +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/celltypes.h" +#include "kernel/cost.h" +#include "kernel/log.h" +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +# include +# include +#endif + +#include "frontends/aiger/aigerparse.h" +#include "kernel/utils.h" + +#ifdef YOSYS_LINK_ABC +extern "C" int Abc_RealMain(int argc, char *argv[]); +#endif + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +bool markgroups; +int map_autoidx; +SigMap assign_map; +RTLIL::Module *module; + +bool clk_polarity, en_polarity; +RTLIL::SigSpec clk_sig, en_sig; + +inline std::string remap_name(RTLIL::IdString abc9_name) +{ + return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1); +} + +void handle_loops(RTLIL::Design *design) +{ + Pass::call(design, "scc -set_attr abc9_scc_id {}"); + + // For every unique SCC found, (arbitrarily) find the first + // cell in the component, and select (and mark) all its output + // wires + pool ids_seen; + for (auto cell : module->cells()) { + auto it = cell->attributes.find(ID(abc9_scc_id)); + if (it != cell->attributes.end()) { + auto r = ids_seen.insert(it->second); + if (r.second) { + for (auto &c : cell->connections_) { + if (c.second.is_fully_const()) continue; + if (cell->output(c.first)) { + SigBit b = c.second.as_bit(); + Wire *w = b.wire; + if (w->port_input) { + // In this case, hopefully the loop break has been already created + // Get the non-prefixed wire + Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str())); + log_assert(wo != nullptr); + log_assert(wo->port_output); + log_assert(b.offset < GetSize(wo)); + c.second = RTLIL::SigBit(wo, b.offset); + } + else { + // Create a new output/input loop break + w->port_input = true; + w = module->wire(stringf("%s.abco", w->name.c_str())); + if (!w) { + w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire)); + w->port_output = true; + } + else { + log_assert(w->port_input); + log_assert(b.offset < GetSize(w)); + } + w->set_bool_attribute(ID(abc9_scc_break)); + c.second = RTLIL::SigBit(w, b.offset); + } + } + } + } + cell->attributes.erase(it); + } + } + + module->fixup_ports(); +} + +std::string add_echos_to_abc9_cmd(std::string str) +{ + std::string new_str, token; + for (size_t i = 0; i < str.size(); i++) { + token += str[i]; + if (str[i] == ';') { + while (i+1 < str.size() && str[i+1] == ' ') + i++; + new_str += "echo + " + token + " " + token + " "; + token.clear(); + } + } + + if (!token.empty()) { + if (!new_str.empty()) + new_str += "echo + " + token + "; "; + new_str += token; + } + + return new_str; +} + +std::string fold_abc9_cmd(std::string str) +{ + std::string token, new_str = " "; + int char_counter = 10; + + for (size_t i = 0; i <= str.size(); i++) { + if (i < str.size()) + token += str[i]; + if (i == str.size() || str[i] == ';') { + if (char_counter + token.size() > 75) + new_str += "\n ", char_counter = 14; + new_str += token, char_counter += token.size(); + token.clear(); + } + } + + return new_str; +} + +std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir) +{ + if (show_tempdir) + return text; + + while (1) { + size_t pos = text.find(tempdir_name); + if (pos == std::string::npos) + break; + text = text.substr(0, pos) + "" + text.substr(pos + GetSize(tempdir_name)); + } + + std::string selfdir_name = proc_self_dirname(); + if (selfdir_name != "/") { + while (1) { + size_t pos = text.find(selfdir_name); + if (pos == std::string::npos) + break; + text = text.substr(0, pos) + "/" + text.substr(pos + GetSize(selfdir_name)); + } + } + + return text; +} + +struct abc9_output_filter +{ + bool got_cr; + int escape_seq_state; + std::string linebuf; + std::string tempdir_name; + bool show_tempdir; + + abc9_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir) + { + got_cr = false; + escape_seq_state = 0; + } + + void next_char(char ch) + { + if (escape_seq_state == 0 && ch == '\033') { + escape_seq_state = 1; + return; + } + if (escape_seq_state == 1) { + escape_seq_state = ch == '[' ? 2 : 0; + return; + } + if (escape_seq_state == 2) { + if ((ch < '0' || '9' < ch) && ch != ';') + escape_seq_state = 0; + return; + } + escape_seq_state = 0; + if (ch == '\r') { + got_cr = true; + return; + } + if (ch == '\n') { + log("ABC: %s\n", replace_tempdir(linebuf, tempdir_name, show_tempdir).c_str()); + got_cr = false, linebuf.clear(); + return; + } + if (got_cr) + got_cr = false, linebuf.clear(); + linebuf += ch; + } + + void next_line(const std::string &line) + { + //int pi, po; + //if (sscanf(line.c_str(), "Start-point = pi%d. End-point = po%d.", &pi, &po) == 2) { + // log("ABC: Start-point = pi%d (%s). End-point = po%d (%s).\n", + // pi, pi_map.count(pi) ? pi_map.at(pi).c_str() : "???", + // po, po_map.count(po) ? po_map.at(po).c_str() : "???"); + // return; + //} + + for (char ch : line) + next_char(ch); + } +}; + +void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, + bool cleanup, vector lut_costs, bool dff_mode, std::string clk_str, + bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, + bool show_tempdir, std::string box_file, std::string lut_file, + std::string wire_delay, const dict &box_lookup, bool nomfs +) +{ + module = current_module; + map_autoidx = autoidx++; + + if (clk_str != "$") + { + clk_polarity = true; + clk_sig = RTLIL::SigSpec(); + + en_polarity = true; + en_sig = RTLIL::SigSpec(); + } + + if (!clk_str.empty() && clk_str != "$") + { + if (clk_str.find(',') != std::string::npos) { + int pos = clk_str.find(','); + std::string en_str = clk_str.substr(pos+1); + clk_str = clk_str.substr(0, pos); + if (en_str[0] == '!') { + en_polarity = false; + en_str = en_str.substr(1); + } + if (module->wires_.count(RTLIL::escape_id(en_str)) != 0) + en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0)); + } + if (clk_str[0] == '!') { + clk_polarity = false; + clk_str = clk_str.substr(1); + } + if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0) + clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0)); + } + + if (dff_mode && clk_sig.empty()) + log_cmd_error("Clock domain %s not found.\n", clk_str.c_str()); + + std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; + if (!cleanup) + tempdir_name[0] = tempdir_name[4] = '_'; + tempdir_name = make_temp_dir(tempdir_name); + log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", + module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); + + std::string abc9_script; + + if (!lut_costs.empty()) { + abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); + if (!box_file.empty()) + abc9_script += stringf("read_box -v %s; ", box_file.c_str()); + } + else + if (!lut_file.empty()) { + abc9_script += stringf("read_lut %s; ", lut_file.c_str()); + if (!box_file.empty()) + abc9_script += stringf("read_box -v %s; ", box_file.c_str()); + } + else + log_abort(); + + abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); + + if (!script_file.empty()) { + if (script_file[0] == '+') { + for (size_t i = 1; i < script_file.size(); i++) + if (script_file[i] == '\'') + abc9_script += "'\\''"; + else if (script_file[i] == ',') + abc9_script += " "; + else + abc9_script += script_file[i]; + } else + abc9_script += stringf("source %s", script_file.c_str()); + } else if (!lut_costs.empty() || !lut_file.empty()) { + //bool all_luts_cost_same = true; + //for (int this_cost : lut_costs) + // if (this_cost != lut_costs.front()) + // all_luts_cost_same = false; + abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; + //if (all_luts_cost_same && !fast_mode) + // abc9_script += "; lutpack {S}"; + } else + log_abort(); + + //if (script_file.empty() && !delay_target.empty()) + // for (size_t pos = abc9_script.find("dretime;"); pos != std::string::npos; pos = abc9_script.find("dretime;", pos+1)) + // abc9_script = abc9_script.substr(0, pos) + "dretime; retime -o {D};" + abc9_script.substr(pos+8); + + for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos)) + abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3); + + //for (size_t pos = abc9_script.find("{S}"); pos != std::string::npos; pos = abc9_script.find("{S}", pos)) + // abc9_script = abc9_script.substr(0, pos) + lutin_shared + abc9_script.substr(pos+3); + + for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos)) + abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3); + + if (nomfs) + for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) + abc9_script = abc9_script.erase(pos, strlen("&mfs")); + + abc9_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); + abc9_script = add_echos_to_abc9_cmd(abc9_script); + + for (size_t i = 0; i+1 < abc9_script.size(); i++) + if (abc9_script[i] == ';' && abc9_script[i+1] == ' ') + abc9_script[i+1] = '\n'; + + FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); + fprintf(f, "%s\n", abc9_script.c_str()); + fclose(f); + + if (dff_mode || !clk_str.empty()) + { + if (clk_sig.size() == 0) + log("No%s clock domain found. Not extracting any FF cells.\n", clk_str.empty() ? "" : " matching"); + else { + log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); + if (en_sig.size() != 0) + log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); + log("\n"); + } + } + + bool count_output = false; + for (auto port_name : module->ports) { + RTLIL::Wire *port_wire = module->wire(port_name); + log_assert(port_wire); + if (port_wire->port_output) { + count_output = true; + break; + } + } + + log_push(); + + if (count_output) + { + design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = design->selection_stack.back(); + sel.select(module); + + handle_loops(design); + + Pass::call(design, "aigmap"); + + //log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", + // count_gates, GetSize(signal_list), count_input, count_output); + + Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); + + std::string buffer; + std::ifstream ifs; +#if 0 + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig"); + ifs.open(buffer); + if (ifs.fail()) + log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); + log_assert(!design->module(ID($__abc9__))); + { + AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); + reader.parse_xaiger(); + } + ifs.close(); + Pass::call(design, stringf("write_verilog -noexpr -norename")); + design->remove(design->module(ID($__abc9__))); +#endif + + design->selection_stack.pop_back(); + + log_header(design, "Executing ABC9_MAP.\n"); + + if (!lut_costs.empty()) { + buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); + f = fopen(buffer.c_str(), "wt"); + if (f == NULL) + log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); + for (int i = 0; i < GetSize(lut_costs); i++) + fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i)); + fclose(f); + } + + buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str()); + log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str()); + +#ifndef YOSYS_LINK_ABC + abc9_output_filter filt(tempdir_name, show_tempdir); + int ret = run_command(buffer, std::bind(&abc9_output_filter::next_line, filt, std::placeholders::_1)); +#else + // These needs to be mutable, supposedly due to getopt + char *abc9_argv[5]; + string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str()); + abc9_argv[0] = strdup(exe_file.c_str()); + abc9_argv[1] = strdup("-s"); + abc9_argv[2] = strdup("-f"); + abc9_argv[3] = strdup(tmp_script_name.c_str()); + abc9_argv[4] = 0; + int ret = Abc_RealMain(4, abc9_argv); + free(abc9_argv[0]); + free(abc9_argv[1]); + free(abc9_argv[2]); + free(abc9_argv[3]); +#endif + if (ret != 0) + log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); + + buffer = stringf("%s/%s", tempdir_name.c_str(), "output.aig"); + ifs.open(buffer, std::ifstream::binary); + if (ifs.fail()) + log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); + + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); + log_assert(!design->module(ID($__abc9__))); + + AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); + reader.parse_xaiger(box_lookup); + ifs.close(); + +#if 0 + Pass::call(design, stringf("write_verilog -noexpr -norename")); +#endif + + log_header(design, "Re-integrating ABC9 results.\n"); + RTLIL::Module *mapped_mod = design->module(ID($__abc9__)); + if (mapped_mod == NULL) + log_error("ABC output file does not contain a module `$__abc9__'.\n"); + + pool output_bits; + for (auto &it : mapped_mod->wires_) { + RTLIL::Wire *w = it.second; + RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w)); + if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx; + if (w->port_output) { + RTLIL::Wire *wire = module->wire(w->name); + log_assert(wire); + for (int i = 0; i < GetSize(w); i++) + output_bits.insert({wire, i}); + } + } + + for (auto &it : module->connections_) { + auto &signal = it.first; + auto bits = signal.bits(); + for (auto &b : bits) + if (output_bits.count(b)) + b = module->addWire(NEW_ID); + signal = std::move(bits); + } + + dict abc9_box; + vector boxes; + for (const auto &it : module->cells_) { + auto cell = it.second; + if (cell->type.in(ID($_AND_), ID($_NOT_))) { + module->remove(cell); + continue; + } + auto jt = abc9_box.find(cell->type); + if (jt == abc9_box.end()) { + RTLIL::Module* box_module = design->module(cell->type); + jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; + } + if (jt->second) + boxes.emplace_back(cell); + } + + dict> bit_drivers, bit_users; + TopoSort toposort; + dict not2drivers; + dict> bit2sinks; + + std::map cell_stats; + for (auto c : mapped_mod->cells()) + { + toposort.node(c->name); + + RTLIL::Cell *cell = nullptr; + if (c->type == ID($_NOT_)) { + RTLIL::SigBit a_bit = c->getPort(ID::A); + RTLIL::SigBit y_bit = c->getPort(ID::Y); + bit_users[a_bit].insert(c->name); + bit_drivers[y_bit].insert(c->name); + + if (!a_bit.wire) { + c->setPort(ID::Y, module->addWire(NEW_ID)); + RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); + log_assert(wire); + module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1); + } + else if (!lut_costs.empty() || !lut_file.empty()) { + RTLIL::Cell* driver_lut = nullptr; + // ABC can return NOT gates that drive POs + if (!a_bit.wire->port_input) { + // If it's not a NOT gate that that comes from a PI directly, + // find the driver LUT and clone that to guarantee that we won't + // increase the max logic depth + // (TODO: Optimise by not cloning unless will increase depth) + RTLIL::IdString driver_name; + if (GetSize(a_bit.wire) == 1) + driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); + else + driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); + driver_lut = mapped_mod->cell(driver_name); + } + + if (!driver_lut) { + // If a driver couldn't be found (could be from PI or box CI) + // then implement using a LUT + cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), + RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), + RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), + RTLIL::Const::from_string("01")); + bit2sinks[cell->getPort(ID::A)].push_back(cell); + cell_stats[ID($lut)]++; + } + else + not2drivers[c] = driver_lut; + continue; + } + else + log_abort(); + if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + continue; + } + cell_stats[c->type]++; + + RTLIL::Cell *existing_cell = nullptr; + if (c->type == ID($lut)) { + if (GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) { + SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID::A).as_wire()->name)); + SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID::Y).as_wire()->name)); + module->connect(my_y, my_a); + if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx; + log_abort(); + continue; + } + cell = module->addCell(remap_name(c->name), c->type); + } + else { + existing_cell = module->cell(c->name); + log_assert(existing_cell); + cell = module->addCell(remap_name(c->name), c->type); + } + + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + if (existing_cell) { + cell->parameters = existing_cell->parameters; + cell->attributes = existing_cell->attributes; + } + else { + cell->parameters = c->parameters; + cell->attributes = c->attributes; + } + for (auto &conn : c->connections()) { + RTLIL::SigSpec newsig; + for (auto c : conn.second.chunks()) { + if (c.width == 0) + continue; + //log_assert(c.width == 1); + if (c.wire) + c.wire = module->wires_.at(remap_name(c.wire->name)); + newsig.append(c); + } + cell->setPort(conn.first, newsig); + + if (cell->input(conn.first)) { + for (auto i : newsig) + bit2sinks[i].push_back(cell); + for (auto i : conn.second) + bit_users[i].insert(c->name); + } + if (cell->output(conn.first)) + for (auto i : conn.second) + bit_drivers[i].insert(c->name); + } + } + + for (auto existing_cell : boxes) { + Cell *cell = module->cell(remap_name(existing_cell->name)); + if (cell) { + for (auto &conn : existing_cell->connections()) { + if (!conn.second.is_wire()) + continue; + Wire *wire = conn.second.as_wire(); + if (!wire->get_bool_attribute(ID(abc9_padding))) + continue; + cell->unsetPort(conn.first); + log_debug("Dropping padded port connection for %s (%s) .%s (%s )\n", log_id(cell), cell->type.c_str(), log_id(conn.first), log_signal(conn.second)); + } + module->swap_names(cell, existing_cell); + } + module->remove(existing_cell); + } + + // Copy connections (and rename) from mapped_mod to module + for (auto conn : mapped_mod->connections()) { + if (!conn.first.is_fully_const()) { + auto chunks = conn.first.chunks(); + for (auto &c : chunks) + c.wire = module->wires_.at(remap_name(c.wire->name)); + conn.first = std::move(chunks); + } + if (!conn.second.is_fully_const()) { + auto chunks = conn.second.chunks(); + for (auto &c : chunks) + if (c.wire) + c.wire = module->wires_.at(remap_name(c.wire->name)); + conn.second = std::move(chunks); + } + module->connect(conn); + } + + for (auto &it : cell_stats) + log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); + int in_wires = 0, out_wires = 0; + + // Stitch in mapped_mod's inputs/outputs into module + for (auto port : mapped_mod->ports) { + RTLIL::Wire *w = mapped_mod->wire(port); + RTLIL::Wire *wire = module->wire(port); + log_assert(wire); + RTLIL::Wire *remap_wire = module->wire(remap_name(port)); + RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); + log_assert(GetSize(signal) >= GetSize(remap_wire)); + + RTLIL::SigSig conn; + if (w->port_output) { + conn.first = signal; + conn.second = remap_wire; + out_wires++; + module->connect(conn); + } + else if (w->port_input) { + conn.first = remap_wire; + conn.second = signal; + in_wires++; + module->connect(conn); + } + } + + 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); + bool no_loops YS_ATTRIBUTE(unused) = toposort.sort(); + log_assert(no_loops); + + for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) { + RTLIL::Cell *not_cell = mapped_mod->cell(*ii); + log_assert(not_cell); + if (not_cell->type != ID($_NOT_)) + continue; + auto it = not2drivers.find(not_cell); + if (it == not2drivers.end()) + continue; + RTLIL::Cell *driver_lut = it->second; + RTLIL::SigBit a_bit = not_cell->getPort(ID::A); + RTLIL::SigBit y_bit = not_cell->getPort(ID::Y); + RTLIL::Const driver_mask; + + a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); + y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); + + auto jt = bit2sinks.find(a_bit); + if (jt == bit2sinks.end()) + goto clone_lut; + + for (auto sink_cell : jt->second) + if (sink_cell->type != ID($lut)) + goto clone_lut; + + // Push downstream LUTs past inverter + for (auto sink_cell : jt->second) { + SigSpec A = sink_cell->getPort(ID::A); + RTLIL::Const mask = sink_cell->getParam(ID(LUT)); + int index = 0; + for (; index < GetSize(A); index++) + if (A[index] == a_bit) + break; + log_assert(index < GetSize(A)); + int i = 0; + while (i < GetSize(mask)) { + for (int j = 0; j < (1 << index); j++) + std::swap(mask[i+j], mask[i+j+(1 << index)]); + i += 1 << (index+1); + } + A[index] = y_bit; + sink_cell->setPort(ID::A, A); + sink_cell->setParam(ID(LUT), mask); + } + + // Since we have rewritten all sinks (which we know + // to be only LUTs) to be after the inverter, we can + // go ahead and clone the LUT with the expectation + // that the original driving LUT will become dangling + // and get cleaned away +clone_lut: + driver_mask = driver_lut->getParam(ID(LUT)); + for (auto &b : driver_mask.bits) { + if (b == RTLIL::State::S0) b = RTLIL::State::S1; + else if (b == RTLIL::State::S1) b = RTLIL::State::S0; + } + auto cell = module->addLut(NEW_ID, + driver_lut->getPort(ID::A), + y_bit, + driver_mask); + for (auto &bit : cell->connections_.at(ID::A)) { + bit.wire = module->wires_.at(remap_name(bit.wire->name)); + bit2sinks[bit].push_back(cell); + } + } + + // Now 'unexpose' those wires by undoing + // the expose operation -- remove them from PO/PI + // and re-connecting them back together + for (auto wire : module->wires()) { + auto it = wire->attributes.find(ID(abc9_scc_break)); + if (it != wire->attributes.end()) { + wire->attributes.erase(it); + log_assert(wire->port_output); + wire->port_output = false; + std::string name = wire->name.str(); + RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5)); + log_assert(i_wire); + log_assert(i_wire->port_input); + i_wire->port_input = false; + module->connect(i_wire, wire); + } + } + module->fixup_ports(); + + //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); + log("ABC RESULTS: input signals: %8d\n", in_wires); + log("ABC RESULTS: output signals: %8d\n", out_wires); + + design->remove(mapped_mod); + } + else + { + log("Don't call ABC as there is nothing to map.\n"); + } + + if (cleanup) + { + log("Removing temp directory.\n"); + remove_directory(tempdir_name); + } + + log_pop(); +} + +struct Abc9TechmapPass : public Pass { + Abc9TechmapPass() : Pass("abc9_map", "use ABC9 for technology mapping") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" abc9_map [options] [selection]\n"); + log("\n"); + log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); + log("library to a target architecture.\n"); + log("\n"); + log(" -exe \n"); +#ifdef ABCEXTERNAL + log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); +#else + log(" use the specified command instead of \"/yosys-abc\" to execute ABC.\n"); +#endif + log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n"); + log("\n"); + log(" -script \n"); + log(" use the specified ABC script file instead of the default script.\n"); + log("\n"); + log(" if starts with a plus sign (+), then the rest of the filename\n"); + log(" string is interpreted as the command string to be passed to ABC. The\n"); + log(" leading plus sign is removed and all commas (,) in the string are\n"); + log(" replaced with blanks before the string is passed to ABC.\n"); + log("\n"); + log(" if no -script parameter is given, the following scripts are used:\n"); + log("\n"); + log(" for -lut/-luts (only one LUT size):\n"); + log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); + log("\n"); + log(" for -lut/-luts (different LUT sizes):\n"); + log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); + log("\n"); + log(" -fast\n"); + log(" use different default scripts that are slightly faster (at the cost\n"); + log(" of output quality):\n"); + log("\n"); + log(" for -lut/-luts:\n"); + log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str()); + log("\n"); + log(" -D \n"); + log(" set delay target. the string {D} in the default scripts above is\n"); + log(" replaced by this option when used, and an empty string otherwise\n"); + log(" (indicating best possible delay).\n"); +// log(" This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); +// log(" default scripts above.\n"); + log("\n"); +// log(" -S \n"); +// log(" maximum number of LUT inputs shared.\n"); +// log(" (replaces {S} in the default scripts above, default: -S 1)\n"); +// log("\n"); + log(" -lut \n"); + log(" generate netlist using luts of (max) the specified width.\n"); + log("\n"); + log(" -lut :\n"); + log(" generate netlist using luts of (max) the specified width . All\n"); + log(" luts with width <= have constant cost. for luts larger than \n"); + log(" the area cost doubles with each additional input bit. the delay cost\n"); + log(" is still constant for all lut widths.\n"); + log("\n"); + log(" -lut \n"); + log(" pass this file with lut library to ABC.\n"); + log("\n"); + log(" -luts ,,,:,..\n"); + log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); + log(" 2, 3, .. inputs.\n"); + log("\n"); +// log(" -dff\n"); +// log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n"); +// log(" clock domains are automatically partitioned in clock domains and each\n"); +// log(" domain is passed through ABC independently.\n"); +// log("\n"); +// log(" -clk [!][,[!]]\n"); +// log(" use only the specified clock domain. this is like -dff, but only FF\n"); +// log(" cells that belong to the specified clock domain are used.\n"); +// log("\n"); +// log(" -keepff\n"); +// log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n"); +// log(" them, for example for equivalence checking.)\n"); +// log("\n"); + log(" -nocleanup\n"); + log(" when this option is used, the temporary files created by this pass\n"); + log(" are not removed. this is useful for debugging.\n"); + log("\n"); + log(" -showtmp\n"); + log(" print the temp dir name in log. usually this is suppressed so that the\n"); + log(" command output is identical across runs.\n"); + log("\n"); + log(" -markgroups\n"); + log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n"); + log(" this attribute is a unique integer for each ABC process started. This\n"); + log(" is useful for debugging the partitioning of clock domains.\n"); + log("\n"); + log(" -box \n"); + log(" pass this file with box library to ABC. Use with -lut.\n"); + log("\n"); + log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); + log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); + log("ABC on logic snippets extracted from your design. You will not get any useful\n"); + log("output when passing an ABC script that writes a file. Instead write your full\n"); + log("design as BLIF file with write_blif and then load that into ABC externally if\n"); + log("you want to use ABC to convert your design into another format.\n"); + log("\n"); + log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing ABC9 pass (technology mapping using ABC9).\n"); + log_push(); + + assign_map.clear(); + +#ifdef ABCEXTERNAL + std::string exe_file = ABCEXTERNAL; +#else + std::string exe_file = proc_self_dirname() + "yosys-abc"; +#endif + std::string script_file, clk_str, box_file, lut_file; + std::string delay_target, lutin_shared = "-S 1", wire_delay; + bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; + bool show_tempdir = false; + bool nomfs = false; + vector lut_costs; + markgroups = false; + +#if 0 + cleanup = false; + show_tempdir = true; +#endif + +#ifdef _WIN32 +#ifndef ABCEXTERNAL + if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe")) + exe_file = proc_self_dirname() + "..\\yosys-abc"; +#endif +#endif + + size_t argidx; + char pwd [PATH_MAX]; + if (!getcwd(pwd, sizeof(pwd))) { + log_cmd_error("getcwd failed: %s\n", strerror(errno)); + log_abort(); + } + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-exe" && argidx+1 < args.size()) { + exe_file = args[++argidx]; + continue; + } + if (arg == "-script" && argidx+1 < args.size()) { + script_file = args[++argidx]; + rewrite_filename(script_file); + if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+') + script_file = std::string(pwd) + "/" + script_file; + continue; + } + if (arg == "-D" && argidx+1 < args.size()) { + delay_target = "-D " + args[++argidx]; + continue; + } + //if (arg == "-S" && argidx+1 < args.size()) { + // lutin_shared = "-S " + args[++argidx]; + // continue; + //} + if (arg == "-lut" && argidx+1 < args.size()) { + string arg = args[++argidx]; + if (arg.find_first_not_of("0123456789:") == std::string::npos) { + size_t pos = arg.find_first_of(':'); + int lut_mode = 0, lut_mode2 = 0; + if (pos != string::npos) { + lut_mode = atoi(arg.substr(0, pos).c_str()); + lut_mode2 = atoi(arg.substr(pos+1).c_str()); + } else { + lut_mode = atoi(arg.c_str()); + lut_mode2 = lut_mode; + } + lut_costs.clear(); + for (int i = 0; i < lut_mode; i++) + lut_costs.push_back(1); + for (int i = lut_mode; i < lut_mode2; i++) + lut_costs.push_back(2 << (i - lut_mode)); + } + else { + lut_file = arg; + rewrite_filename(lut_file); + if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+') + lut_file = std::string(pwd) + "/" + lut_file; + } + continue; + } + if (arg == "-luts" && argidx+1 < args.size()) { + lut_costs.clear(); + for (auto &tok : split_tokens(args[++argidx], ",")) { + auto parts = split_tokens(tok, ":"); + if (GetSize(parts) == 0 && !lut_costs.empty()) + lut_costs.push_back(lut_costs.back()); + else if (GetSize(parts) == 1) + lut_costs.push_back(atoi(parts.at(0).c_str())); + else if (GetSize(parts) == 2) + while (GetSize(lut_costs) < atoi(parts.at(0).c_str())) + lut_costs.push_back(atoi(parts.at(1).c_str())); + else + log_cmd_error("Invalid -luts syntax.\n"); + } + continue; + } + if (arg == "-fast") { + fast_mode = true; + continue; + } + //if (arg == "-dff") { + // dff_mode = true; + // continue; + //} + //if (arg == "-clk" && argidx+1 < args.size()) { + // clk_str = args[++argidx]; + // dff_mode = true; + // continue; + //} + //if (arg == "-keepff") { + // keepff = true; + // continue; + //} + if (arg == "-nocleanup") { + cleanup = false; + continue; + } + if (arg == "-showtmp") { + show_tempdir = true; + continue; + } + if (arg == "-markgroups") { + markgroups = true; + continue; + } + if (arg == "-box" && argidx+1 < args.size()) { + box_file = args[++argidx]; + continue; + } + if (arg == "-W" && argidx+1 < args.size()) { + wire_delay = "-W " + args[++argidx]; + continue; + } + if (arg == "-nomfs") { + nomfs = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + // ABC expects a box file for XAIG + if (box_file.empty()) + box_file = "+/dummy.box"; + + rewrite_filename(box_file); + if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+') + box_file = std::string(pwd) + "/" + box_file; + + dict box_lookup; + for (auto m : design->modules()) { + auto it = m->attributes.find(ID(abc9_box_id)); + if (it == m->attributes.end()) + continue; + if (m->name.begins_with("$paramod")) + continue; + auto id = it->second.as_int(); + auto r = box_lookup.insert(std::make_pair(id, m->name)); + if (!r.second) + log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", + log_id(m), id, log_id(r.first->second)); + log_assert(r.second); + + RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; + for (auto p : m->ports) { + auto w = m->wire(p); + log_assert(w); + if (w->attributes.count(ID(abc9_carry))) { + if (w->port_input) { + if (carry_in) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); + carry_in = w; + } + else if (w->port_output) { + if (carry_out) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); + carry_out = w; + } + } + } + if (carry_in || carry_out) { + if (carry_in && !carry_out) + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); + if (!carry_in && carry_out) + log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); + // Make carry_in the last PI, and carry_out the last PO + // since ABC requires it this way + auto &ports = m->ports; + for (auto it = ports.begin(); it != ports.end(); ) { + RTLIL::Wire* w = m->wire(*it); + log_assert(w); + if (w == carry_in || w == carry_out) { + it = ports.erase(it); + continue; + } + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); + ++it; + } + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); + } + } + + for (auto mod : design->selected_modules()) + { + if (mod->attributes.count(ID(abc9_box_id))) + continue; + + if (mod->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(mod)); + continue; + } + + assign_map.set(mod); + + if (!dff_mode || !clk_str.empty()) { + abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, + delay_target, lutin_shared, fast_mode, show_tempdir, + box_file, lut_file, wire_delay, box_lookup, nomfs); + continue; + } + + CellTypes ct(design); + + std::vector all_cells = mod->selected_cells(); + std::set unassigned_cells(all_cells.begin(), all_cells.end()); + + std::set expand_queue, next_expand_queue; + std::set expand_queue_up, next_expand_queue_up; + std::set expand_queue_down, next_expand_queue_down; + + typedef tuple clkdomain_t; + std::map> assigned_cells; + std::map assigned_cells_reverse; + + std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; + std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; + + for (auto cell : all_cells) + { + clkdomain_t key; + + for (auto &conn : cell->connections()) + for (auto bit : conn.second) { + bit = assign_map(bit); + if (bit.wire != nullptr) { + cell_to_bit[cell].insert(bit); + bit_to_cell[bit].insert(cell); + if (ct.cell_input(cell->type, conn.first)) { + cell_to_bit_up[cell].insert(bit); + bit_to_cell_down[bit].insert(cell); + } + if (ct.cell_output(cell->type, conn.first)) { + cell_to_bit_down[cell].insert(bit); + bit_to_cell_up[bit].insert(cell); + } + } + } + + if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) + { + key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); + } + else + if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + { + bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); + bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E)))); + } + else + continue; + + unassigned_cells.erase(cell); + expand_queue.insert(cell); + expand_queue_up.insert(cell); + expand_queue_down.insert(cell); + + assigned_cells[key].push_back(cell); + assigned_cells_reverse[cell] = key; + } + + while (!expand_queue_up.empty() || !expand_queue_down.empty()) + { + if (!expand_queue_up.empty()) + { + RTLIL::Cell *cell = *expand_queue_up.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_up.erase(cell); + + for (auto bit : cell_to_bit_up[cell]) + for (auto c : bit_to_cell_up[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (!expand_queue_down.empty()) + { + RTLIL::Cell *cell = *expand_queue_down.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_down.erase(cell); + + for (auto bit : cell_to_bit_down[cell]) + for (auto c : bit_to_cell_down[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (expand_queue_up.empty() && expand_queue_down.empty()) { + expand_queue_up.swap(next_expand_queue_up); + expand_queue_down.swap(next_expand_queue_down); + } + } + + while (!expand_queue.empty()) + { + RTLIL::Cell *cell = *expand_queue.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue.erase(cell); + + for (auto bit : cell_to_bit.at(cell)) { + for (auto c : bit_to_cell[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + } + bit_to_cell[bit].clear(); + } + + if (expand_queue.empty()) + expand_queue.swap(next_expand_queue); + } + + clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); + for (auto cell : unassigned_cells) { + assigned_cells[key].push_back(cell); + assigned_cells_reverse[cell] = key; + } + + log_header(design, "Summary of detected clock domains:\n"); + for (auto &it : assigned_cells) + log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), + std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), + std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + + for (auto &it : assigned_cells) { + clk_polarity = std::get<0>(it.first); + clk_sig = assign_map(std::get<1>(it.first)); + en_polarity = std::get<2>(it.first); + en_sig = assign_map(std::get<3>(it.first)); + abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$", + keepff, delay_target, lutin_shared, fast_mode, show_tempdir, + box_file, lut_file, wire_delay, box_lookup, nomfs); + assign_map.set(mod); + } + } + + assign_map.clear(); + + log_pop(); + } +} Abc9TechmapPass; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From f348ffa44d4ec00537499ffe79ce627beeeefe85 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 28 Dec 2019 05:07:46 -0800 Subject: abc9_techmap -> _map; called from abc9 script pass along with abc9_ops --- passes/techmap/Makefile.inc | 3 +- passes/techmap/abc9.cc | 231 +++++++ passes/techmap/abc9_map.cc | 1215 +++++++++++++++++++++++++++++++++++++ passes/techmap/abc9_ops.cc | 139 +++++ passes/techmap/abc9_techmap.cc | 1310 ---------------------------------------- 5 files changed, 1587 insertions(+), 1311 deletions(-) create mode 100644 passes/techmap/abc9.cc create mode 100644 passes/techmap/abc9_map.cc create mode 100644 passes/techmap/abc9_ops.cc delete mode 100644 passes/techmap/abc9_techmap.cc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index a7c8d8c2b..734d6c10f 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -8,7 +8,8 @@ OBJS += passes/techmap/libparse.o ifeq ($(ENABLE_ABC),1) OBJS += passes/techmap/abc.o OBJS += passes/techmap/abc9.o -OBJS += passes/techmap/abc9_techmap.o +OBJS += passes/techmap/abc9_map.o +OBJS += passes/techmap/abc9_ops.o ifneq ($(ABCEXTERNAL),) passes/techmap/abc.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' passes/techmap/abc9.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc new file mode 100644 index 000000000..e1cf188ce --- /dev/null +++ b/passes/techmap/abc9.cc @@ -0,0 +1,231 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * (C) 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +#define XC7_WIRE_DELAY 300 // Number with which ABC will map a 6-input gate + // to one LUT6 (instead of a LUT5 + LUT2) + +struct Abc9Pass : public ScriptPass +{ + Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { } + + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" abc9 [options] [selection]\n"); + log("\n"); + log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); + log("library to a target architecture.\n"); + log("\n"); + log(" -exe \n"); +#ifdef ABCEXTERNAL + log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); +#else + log(" use the specified command instead of \"/yosys-abc\" to execute ABC.\n"); +#endif + log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n"); + log("\n"); + log(" -script \n"); + log(" use the specified ABC script file instead of the default script.\n"); + log("\n"); + log(" if starts with a plus sign (+), then the rest of the filename\n"); + log(" string is interpreted as the command string to be passed to ABC. The\n"); + log(" leading plus sign is removed and all commas (,) in the string are\n"); + log(" replaced with blanks before the string is passed to ABC.\n"); + log("\n"); + log(" if no -script parameter is given, the following scripts are used:\n"); + log("\n"); + log(" for -lut/-luts (only one LUT size):\n"); + // FIXME + //log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); + log("\n"); + log(" for -lut/-luts (different LUT sizes):\n"); + // FIXME + //log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); + log("\n"); + log(" -fast\n"); + log(" use different default scripts that are slightly faster (at the cost\n"); + log(" of output quality):\n"); + log("\n"); + log(" for -lut/-luts:\n"); + // FIXME + //log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str()); + log("\n"); + log(" -D \n"); + log(" set delay target. the string {D} in the default scripts above is\n"); + log(" replaced by this option when used, and an empty string otherwise\n"); + log(" (indicating best possible delay).\n"); +// log(" This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); +// log(" default scripts above.\n"); + log("\n"); +// log(" -S \n"); +// log(" maximum number of LUT inputs shared.\n"); +// log(" (replaces {S} in the default scripts above, default: -S 1)\n"); +// log("\n"); + log(" -lut \n"); + log(" generate netlist using luts of (max) the specified width.\n"); + log("\n"); + log(" -lut :\n"); + log(" generate netlist using luts of (max) the specified width . All\n"); + log(" luts with width <= have constant cost. for luts larger than \n"); + log(" the area cost doubles with each additional input bit. the delay cost\n"); + log(" is still constant for all lut widths.\n"); + log("\n"); + log(" -lut \n"); + log(" pass this file with lut library to ABC.\n"); + log("\n"); + log(" -luts ,,,:,..\n"); + log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); + log(" 2, 3, .. inputs.\n"); + log("\n"); +// log(" -dff\n"); +// log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n"); +// log(" clock domains are automatically partitioned in clock domains and each\n"); +// log(" domain is passed through ABC independently.\n"); +// log("\n"); +// log(" -clk [!][,[!]]\n"); +// log(" use only the specified clock domain. this is like -dff, but only FF\n"); +// log(" cells that belong to the specified clock domain are used.\n"); +// log("\n"); +// log(" -keepff\n"); +// log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n"); +// log(" them, for example for equivalence checking.)\n"); +// log("\n"); + log(" -nocleanup\n"); + log(" when this option is used, the temporary files created by this pass\n"); + log(" are not removed. this is useful for debugging.\n"); + log("\n"); + log(" -showtmp\n"); + log(" print the temp dir name in log. usually this is suppressed so that the\n"); + log(" command output is identical across runs.\n"); + log("\n"); + log(" -markgroups\n"); + log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n"); + log(" this attribute is a unique integer for each ABC process started. This\n"); + log(" is useful for debugging the partitioning of clock domains.\n"); + log("\n"); + log(" -box \n"); + log(" pass this file with box library to ABC. Use with -lut.\n"); + log("\n"); + log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); + log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); + log("ABC on logic snippets extracted from your design. You will not get any useful\n"); + log("output when passing an ABC script that writes a file. Instead write your full\n"); + log("design as BLIF file with write_blif and then load that into ABC externally if\n"); + log("you want to use ABC to convert your design into another format.\n"); + log("\n"); + log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); + log("\n"); + help_script(); + log("\n"); + } + + std::stringstream map_cmd; + bool cleanup; + + void clear_flags() YS_OVERRIDE + { + map_cmd.str(""); + map_cmd << "abc9_map"; + cleanup = true; + } + + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + std::string run_from, run_to; + clear_flags(); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if ((arg == "-exe" || arg == "-script" || arg == "-D" || + /* arg == "-S" || */ arg == "-lut" || arg == "-luts" || + arg == "-clk" || arg == "-box" || arg == "-W") && + argidx+1 < args.size()) { + map_cmd << " " << arg << " " << args[++argidx]; + continue; + } + if (arg == "-fast" || /*arg == "-dff" ||*/ arg == "-keepff" + /*|| arg == "-nocleanup"*/ || arg == "-showtmp" || arg == "-markgroups" + || arg == "-nomfs") { + map_cmd << " " << arg; + continue; + } + if (arg == "-nocleanup") { + cleanup = false; + continue; + } + break; + } + extra_args(args, argidx, design); + + log_header(design, "Executing ABC9 pass.\n"); + + run_script(design, run_from, run_to); + } + + void script() YS_OVERRIDE + { + auto selected_modules = active_design->selected_modules(); + active_design->selection_stack.emplace_back(false); + + for (auto mod : selected_modules) { + log_push(); + + active_design->selection().select(mod); + + std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; + if (!cleanup) + tempdir_name[0] = tempdir_name[4] = '_'; + tempdir_name = make_temp_dir(tempdir_name); + + run("scc -set_attr abc9_scc_id {}"); + run("abc9_ops -break_scc"); + run("aigmap"); + run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()), + "write_xaiger -map /input.sym /input.xaig"); + run(stringf("%s -tempdir %s", map_cmd.str().c_str(), tempdir_name.c_str()), + "abc9_map [options] -tempdir "); + run("abc9_ops -unbreak_scc"); + + if (cleanup) + { + log("Removing temp directory.\n"); + remove_directory(tempdir_name); + } + + active_design->selection().selected_modules.clear(); + + log_pop(); + } + + active_design->selection_stack.pop_back(); + } +} Abc9Pass; + +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/abc9_map.cc b/passes/techmap/abc9_map.cc new file mode 100644 index 000000000..40ff4bbf0 --- /dev/null +++ b/passes/techmap/abc9_map.cc @@ -0,0 +1,1215 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// [[CITE]] ABC +// Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification +// http://www.eecs.berkeley.edu/~alanmi/abc/ + +#if 0 +// Based on &flow3 - better QoR but more experimental +#define ABC_COMMAND_LUT "&st; &ps -l; &sweep -v; &scorr; " \ + "&st; &if {W}; &save; &st; &syn2; &if {W} -v; &save; &load; "\ + "&st; &if -g -K 6; &dch -f; &if {W} -v; &save; &load; "\ + "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ + "&mfs; &ps -l" +#else +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" +#endif + + +#define ABC_FAST_COMMAND_LUT "&st; &if {W} {D}" + +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/celltypes.h" +#include "kernel/cost.h" +#include "kernel/log.h" +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +# include +# include +#endif + +#include "frontends/aiger/aigerparse.h" +#include "kernel/utils.h" + +#ifdef YOSYS_LINK_ABC +extern "C" int Abc_RealMain(int argc, char *argv[]); +#endif + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +bool markgroups; +int map_autoidx; +SigMap assign_map; +RTLIL::Module *module; + +bool clk_polarity, en_polarity; +RTLIL::SigSpec clk_sig, en_sig; + +inline std::string remap_name(RTLIL::IdString abc9_name) +{ + return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1); +} + +std::string add_echos_to_abc9_cmd(std::string str) +{ + std::string new_str, token; + for (size_t i = 0; i < str.size(); i++) { + token += str[i]; + if (str[i] == ';') { + while (i+1 < str.size() && str[i+1] == ' ') + i++; + new_str += "echo + " + token + " " + token + " "; + token.clear(); + } + } + + if (!token.empty()) { + if (!new_str.empty()) + new_str += "echo + " + token + "; "; + new_str += token; + } + + return new_str; +} + +std::string fold_abc9_cmd(std::string str) +{ + std::string token, new_str = " "; + int char_counter = 10; + + for (size_t i = 0; i <= str.size(); i++) { + if (i < str.size()) + token += str[i]; + if (i == str.size() || str[i] == ';') { + if (char_counter + token.size() > 75) + new_str += "\n ", char_counter = 14; + new_str += token, char_counter += token.size(); + token.clear(); + } + } + + return new_str; +} + +std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir) +{ + if (show_tempdir) + return text; + + while (1) { + size_t pos = text.find(tempdir_name); + if (pos == std::string::npos) + break; + text = text.substr(0, pos) + "" + text.substr(pos + GetSize(tempdir_name)); + } + + std::string selfdir_name = proc_self_dirname(); + if (selfdir_name != "/") { + while (1) { + size_t pos = text.find(selfdir_name); + if (pos == std::string::npos) + break; + text = text.substr(0, pos) + "/" + text.substr(pos + GetSize(selfdir_name)); + } + } + + return text; +} + +struct abc9_output_filter +{ + bool got_cr; + int escape_seq_state; + std::string linebuf; + std::string tempdir_name; + bool show_tempdir; + + abc9_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir) + { + got_cr = false; + escape_seq_state = 0; + } + + void next_char(char ch) + { + if (escape_seq_state == 0 && ch == '\033') { + escape_seq_state = 1; + return; + } + if (escape_seq_state == 1) { + escape_seq_state = ch == '[' ? 2 : 0; + return; + } + if (escape_seq_state == 2) { + if ((ch < '0' || '9' < ch) && ch != ';') + escape_seq_state = 0; + return; + } + escape_seq_state = 0; + if (ch == '\r') { + got_cr = true; + return; + } + if (ch == '\n') { + log("ABC: %s\n", replace_tempdir(linebuf, tempdir_name, show_tempdir).c_str()); + got_cr = false, linebuf.clear(); + return; + } + if (got_cr) + got_cr = false, linebuf.clear(); + linebuf += ch; + } + + void next_line(const std::string &line) + { + //int pi, po; + //if (sscanf(line.c_str(), "Start-point = pi%d. End-point = po%d.", &pi, &po) == 2) { + // log("ABC: Start-point = pi%d (%s). End-point = po%d (%s).\n", + // pi, pi_map.count(pi) ? pi_map.at(pi).c_str() : "???", + // po, po_map.count(po) ? po_map.at(po).c_str() : "???"); + // return; + //} + + for (char ch : line) + next_char(ch); + } +}; + +void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, + /*bool cleanup,*/ vector lut_costs, bool dff_mode, std::string clk_str, + bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, + bool show_tempdir, std::string box_file, std::string lut_file, + std::string wire_delay, const dict &box_lookup, bool nomfs, std::string tempdir_name +) +{ + module = current_module; + map_autoidx = autoidx++; + + if (clk_str != "$") + { + clk_polarity = true; + clk_sig = RTLIL::SigSpec(); + + en_polarity = true; + en_sig = RTLIL::SigSpec(); + } + + if (!clk_str.empty() && clk_str != "$") + { + if (clk_str.find(',') != std::string::npos) { + int pos = clk_str.find(','); + std::string en_str = clk_str.substr(pos+1); + clk_str = clk_str.substr(0, pos); + if (en_str[0] == '!') { + en_polarity = false; + en_str = en_str.substr(1); + } + if (module->wires_.count(RTLIL::escape_id(en_str)) != 0) + en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0)); + } + if (clk_str[0] == '!') { + clk_polarity = false; + clk_str = clk_str.substr(1); + } + if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0) + clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0)); + } + + if (dff_mode && clk_sig.empty()) + log_cmd_error("Clock domain %s not found.\n", clk_str.c_str()); + + log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", + module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); + + std::string abc9_script; + + if (!lut_costs.empty()) { + abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); + if (!box_file.empty()) + abc9_script += stringf("read_box -v %s; ", box_file.c_str()); + } + else + if (!lut_file.empty()) { + abc9_script += stringf("read_lut %s; ", lut_file.c_str()); + if (!box_file.empty()) + abc9_script += stringf("read_box -v %s; ", box_file.c_str()); + } + else + log_abort(); + + abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); + + if (!script_file.empty()) { + if (script_file[0] == '+') { + for (size_t i = 1; i < script_file.size(); i++) + if (script_file[i] == '\'') + abc9_script += "'\\''"; + else if (script_file[i] == ',') + abc9_script += " "; + else + abc9_script += script_file[i]; + } else + abc9_script += stringf("source %s", script_file.c_str()); + } else if (!lut_costs.empty() || !lut_file.empty()) { + //bool all_luts_cost_same = true; + //for (int this_cost : lut_costs) + // if (this_cost != lut_costs.front()) + // all_luts_cost_same = false; + abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; + //if (all_luts_cost_same && !fast_mode) + // abc9_script += "; lutpack {S}"; + } else + log_abort(); + + //if (script_file.empty() && !delay_target.empty()) + // for (size_t pos = abc9_script.find("dretime;"); pos != std::string::npos; pos = abc9_script.find("dretime;", pos+1)) + // abc9_script = abc9_script.substr(0, pos) + "dretime; retime -o {D};" + abc9_script.substr(pos+8); + + for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos)) + abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3); + + //for (size_t pos = abc9_script.find("{S}"); pos != std::string::npos; pos = abc9_script.find("{S}", pos)) + // abc9_script = abc9_script.substr(0, pos) + lutin_shared + abc9_script.substr(pos+3); + + for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos)) + abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3); + + if (nomfs) + for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) + abc9_script = abc9_script.erase(pos, strlen("&mfs")); + + abc9_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); + abc9_script = add_echos_to_abc9_cmd(abc9_script); + + for (size_t i = 0; i+1 < abc9_script.size(); i++) + if (abc9_script[i] == ';' && abc9_script[i+1] == ' ') + abc9_script[i+1] = '\n'; + + FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); + fprintf(f, "%s\n", abc9_script.c_str()); + fclose(f); + + if (dff_mode || !clk_str.empty()) + { + if (clk_sig.size() == 0) + log("No%s clock domain found. Not extracting any FF cells.\n", clk_str.empty() ? "" : " matching"); + else { + log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); + if (en_sig.size() != 0) + log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); + log("\n"); + } + } + + log_push(); + + //if (count_output) + { + std::string buffer; + std::ifstream ifs; +#if 0 + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig"); + ifs.open(buffer); + if (ifs.fail()) + log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); + log_assert(!design->module(ID($__abc9__))); + { + AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); + reader.parse_xaiger(); + } + ifs.close(); + Pass::call(design, stringf("write_verilog -noexpr -norename")); + design->remove(design->module(ID($__abc9__))); +#endif + + log_header(design, "Executing ABC9_MAP.\n"); + + if (!lut_costs.empty()) { + buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); + f = fopen(buffer.c_str(), "wt"); + if (f == NULL) + log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); + for (int i = 0; i < GetSize(lut_costs); i++) + fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i)); + fclose(f); + } + + buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str()); + log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str()); + +#ifndef YOSYS_LINK_ABC + abc9_output_filter filt(tempdir_name, show_tempdir); + int ret = run_command(buffer, std::bind(&abc9_output_filter::next_line, filt, std::placeholders::_1)); +#else + // These needs to be mutable, supposedly due to getopt + char *abc9_argv[5]; + string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str()); + abc9_argv[0] = strdup(exe_file.c_str()); + abc9_argv[1] = strdup("-s"); + abc9_argv[2] = strdup("-f"); + abc9_argv[3] = strdup(tmp_script_name.c_str()); + abc9_argv[4] = 0; + int ret = Abc_RealMain(4, abc9_argv); + free(abc9_argv[0]); + free(abc9_argv[1]); + free(abc9_argv[2]); + free(abc9_argv[3]); +#endif + if (ret != 0) + log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); + + buffer = stringf("%s/%s", tempdir_name.c_str(), "output.aig"); + ifs.open(buffer, std::ifstream::binary); + if (ifs.fail()) + log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); + + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); + log_assert(!design->module(ID($__abc9__))); + + AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); + reader.parse_xaiger(box_lookup); + ifs.close(); + +#if 0 + Pass::call(design, stringf("write_verilog -noexpr -norename")); +#endif + + log_header(design, "Re-integrating ABC9 results.\n"); + RTLIL::Module *mapped_mod = design->module(ID($__abc9__)); + if (mapped_mod == NULL) + log_error("ABC output file does not contain a module `$__abc9__'.\n"); + + pool output_bits; + for (auto &it : mapped_mod->wires_) { + RTLIL::Wire *w = it.second; + RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w)); + if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx; + if (w->port_output) { + RTLIL::Wire *wire = module->wire(w->name); + log_assert(wire); + for (int i = 0; i < GetSize(w); i++) + output_bits.insert({wire, i}); + } + } + + for (auto &it : module->connections_) { + auto &signal = it.first; + auto bits = signal.bits(); + for (auto &b : bits) + if (output_bits.count(b)) + b = module->addWire(NEW_ID); + signal = std::move(bits); + } + + dict abc9_box; + vector boxes; + for (const auto &it : module->cells_) { + auto cell = it.second; + if (cell->type.in(ID($_AND_), ID($_NOT_))) { + module->remove(cell); + continue; + } + auto jt = abc9_box.find(cell->type); + if (jt == abc9_box.end()) { + RTLIL::Module* box_module = design->module(cell->type); + jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; + } + if (jt->second) + boxes.emplace_back(cell); + } + + dict> bit_drivers, bit_users; + TopoSort toposort; + dict not2drivers; + dict> bit2sinks; + + std::map cell_stats; + for (auto c : mapped_mod->cells()) + { + toposort.node(c->name); + + RTLIL::Cell *cell = nullptr; + if (c->type == ID($_NOT_)) { + RTLIL::SigBit a_bit = c->getPort(ID::A); + RTLIL::SigBit y_bit = c->getPort(ID::Y); + bit_users[a_bit].insert(c->name); + bit_drivers[y_bit].insert(c->name); + + if (!a_bit.wire) { + c->setPort(ID::Y, module->addWire(NEW_ID)); + RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); + log_assert(wire); + module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1); + } + else if (!lut_costs.empty() || !lut_file.empty()) { + RTLIL::Cell* driver_lut = nullptr; + // ABC can return NOT gates that drive POs + if (!a_bit.wire->port_input) { + // If it's not a NOT gate that that comes from a PI directly, + // find the driver LUT and clone that to guarantee that we won't + // increase the max logic depth + // (TODO: Optimise by not cloning unless will increase depth) + RTLIL::IdString driver_name; + if (GetSize(a_bit.wire) == 1) + driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); + else + driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); + driver_lut = mapped_mod->cell(driver_name); + } + + if (!driver_lut) { + // If a driver couldn't be found (could be from PI or box CI) + // then implement using a LUT + cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), + RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), + RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), + RTLIL::Const::from_string("01")); + bit2sinks[cell->getPort(ID::A)].push_back(cell); + cell_stats[ID($lut)]++; + } + else + not2drivers[c] = driver_lut; + continue; + } + else + log_abort(); + if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + continue; + } + cell_stats[c->type]++; + + RTLIL::Cell *existing_cell = nullptr; + if (c->type == ID($lut)) { + if (GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) { + SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID::A).as_wire()->name)); + SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID::Y).as_wire()->name)); + module->connect(my_y, my_a); + if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx; + log_abort(); + continue; + } + cell = module->addCell(remap_name(c->name), c->type); + } + else { + existing_cell = module->cell(c->name); + log_assert(existing_cell); + cell = module->addCell(remap_name(c->name), c->type); + } + + if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; + if (existing_cell) { + cell->parameters = existing_cell->parameters; + cell->attributes = existing_cell->attributes; + } + else { + cell->parameters = c->parameters; + cell->attributes = c->attributes; + } + for (auto &conn : c->connections()) { + RTLIL::SigSpec newsig; + for (auto c : conn.second.chunks()) { + if (c.width == 0) + continue; + //log_assert(c.width == 1); + if (c.wire) + c.wire = module->wires_.at(remap_name(c.wire->name)); + newsig.append(c); + } + cell->setPort(conn.first, newsig); + + if (cell->input(conn.first)) { + for (auto i : newsig) + bit2sinks[i].push_back(cell); + for (auto i : conn.second) + bit_users[i].insert(c->name); + } + if (cell->output(conn.first)) + for (auto i : conn.second) + bit_drivers[i].insert(c->name); + } + } + + for (auto existing_cell : boxes) { + Cell *cell = module->cell(remap_name(existing_cell->name)); + if (cell) { + for (auto &conn : existing_cell->connections()) { + if (!conn.second.is_wire()) + continue; + Wire *wire = conn.second.as_wire(); + if (!wire->get_bool_attribute(ID(abc9_padding))) + continue; + cell->unsetPort(conn.first); + log_debug("Dropping padded port connection for %s (%s) .%s (%s )\n", log_id(cell), cell->type.c_str(), log_id(conn.first), log_signal(conn.second)); + } + module->swap_names(cell, existing_cell); + } + module->remove(existing_cell); + } + + // Copy connections (and rename) from mapped_mod to module + for (auto conn : mapped_mod->connections()) { + if (!conn.first.is_fully_const()) { + auto chunks = conn.first.chunks(); + for (auto &c : chunks) + c.wire = module->wires_.at(remap_name(c.wire->name)); + conn.first = std::move(chunks); + } + if (!conn.second.is_fully_const()) { + auto chunks = conn.second.chunks(); + for (auto &c : chunks) + if (c.wire) + c.wire = module->wires_.at(remap_name(c.wire->name)); + conn.second = std::move(chunks); + } + module->connect(conn); + } + + for (auto &it : cell_stats) + log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); + int in_wires = 0, out_wires = 0; + + // Stitch in mapped_mod's inputs/outputs into module + for (auto port : mapped_mod->ports) { + RTLIL::Wire *w = mapped_mod->wire(port); + RTLIL::Wire *wire = module->wire(port); + log_assert(wire); + RTLIL::Wire *remap_wire = module->wire(remap_name(port)); + RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); + log_assert(GetSize(signal) >= GetSize(remap_wire)); + + RTLIL::SigSig conn; + if (w->port_output) { + conn.first = signal; + conn.second = remap_wire; + out_wires++; + module->connect(conn); + } + else if (w->port_input) { + conn.first = remap_wire; + conn.second = signal; + in_wires++; + module->connect(conn); + } + } + + 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); + bool no_loops YS_ATTRIBUTE(unused) = toposort.sort(); + log_assert(no_loops); + + for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) { + RTLIL::Cell *not_cell = mapped_mod->cell(*ii); + log_assert(not_cell); + if (not_cell->type != ID($_NOT_)) + continue; + auto it = not2drivers.find(not_cell); + if (it == not2drivers.end()) + continue; + RTLIL::Cell *driver_lut = it->second; + RTLIL::SigBit a_bit = not_cell->getPort(ID::A); + RTLIL::SigBit y_bit = not_cell->getPort(ID::Y); + RTLIL::Const driver_mask; + + a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); + y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); + + auto jt = bit2sinks.find(a_bit); + if (jt == bit2sinks.end()) + goto clone_lut; + + for (auto sink_cell : jt->second) + if (sink_cell->type != ID($lut)) + goto clone_lut; + + // Push downstream LUTs past inverter + for (auto sink_cell : jt->second) { + SigSpec A = sink_cell->getPort(ID::A); + RTLIL::Const mask = sink_cell->getParam(ID(LUT)); + int index = 0; + for (; index < GetSize(A); index++) + if (A[index] == a_bit) + break; + log_assert(index < GetSize(A)); + int i = 0; + while (i < GetSize(mask)) { + for (int j = 0; j < (1 << index); j++) + std::swap(mask[i+j], mask[i+j+(1 << index)]); + i += 1 << (index+1); + } + A[index] = y_bit; + sink_cell->setPort(ID::A, A); + sink_cell->setParam(ID(LUT), mask); + } + + // Since we have rewritten all sinks (which we know + // to be only LUTs) to be after the inverter, we can + // go ahead and clone the LUT with the expectation + // that the original driving LUT will become dangling + // and get cleaned away +clone_lut: + driver_mask = driver_lut->getParam(ID(LUT)); + for (auto &b : driver_mask.bits) { + if (b == RTLIL::State::S0) b = RTLIL::State::S1; + else if (b == RTLIL::State::S1) b = RTLIL::State::S0; + } + auto cell = module->addLut(NEW_ID, + driver_lut->getPort(ID::A), + y_bit, + driver_mask); + for (auto &bit : cell->connections_.at(ID::A)) { + bit.wire = module->wires_.at(remap_name(bit.wire->name)); + bit2sinks[bit].push_back(cell); + } + } + + //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); + log("ABC RESULTS: input signals: %8d\n", in_wires); + log("ABC RESULTS: output signals: %8d\n", out_wires); + + design->remove(mapped_mod); + } + //else + //{ + // log("Don't call ABC as there is nothing to map.\n"); + //} + + log_pop(); +} + +struct Abc9TechmapPass : public Pass { + Abc9TechmapPass() : Pass("abc9_map", "use ABC9 for technology mapping") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" abc9_map [options] [selection]\n"); + log("\n"); + log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); + log("library to a target architecture.\n"); + log("\n"); + log(" -exe \n"); +#ifdef ABCEXTERNAL + log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); +#else + log(" use the specified command instead of \"/yosys-abc\" to execute ABC.\n"); +#endif + log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n"); + log("\n"); + log(" -script \n"); + log(" use the specified ABC script file instead of the default script.\n"); + log("\n"); + log(" if starts with a plus sign (+), then the rest of the filename\n"); + log(" string is interpreted as the command string to be passed to ABC. The\n"); + log(" leading plus sign is removed and all commas (,) in the string are\n"); + log(" replaced with blanks before the string is passed to ABC.\n"); + log("\n"); + log(" if no -script parameter is given, the following scripts are used:\n"); + log("\n"); + log(" for -lut/-luts (only one LUT size):\n"); + log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); + log("\n"); + log(" for -lut/-luts (different LUT sizes):\n"); + log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); + log("\n"); + log(" -fast\n"); + log(" use different default scripts that are slightly faster (at the cost\n"); + log(" of output quality):\n"); + log("\n"); + log(" for -lut/-luts:\n"); + log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str()); + log("\n"); + log(" -D \n"); + log(" set delay target. the string {D} in the default scripts above is\n"); + log(" replaced by this option when used, and an empty string otherwise\n"); + log(" (indicating best possible delay).\n"); +// log(" This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); +// log(" default scripts above.\n"); + log("\n"); +// log(" -S \n"); +// log(" maximum number of LUT inputs shared.\n"); +// log(" (replaces {S} in the default scripts above, default: -S 1)\n"); +// log("\n"); + log(" -lut \n"); + log(" generate netlist using luts of (max) the specified width.\n"); + log("\n"); + log(" -lut :\n"); + log(" generate netlist using luts of (max) the specified width . All\n"); + log(" luts with width <= have constant cost. for luts larger than \n"); + log(" the area cost doubles with each additional input bit. the delay cost\n"); + log(" is still constant for all lut widths.\n"); + log("\n"); + log(" -lut \n"); + log(" pass this file with lut library to ABC.\n"); + log("\n"); + log(" -luts ,,,:,..\n"); + log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); + log(" 2, 3, .. inputs.\n"); + log("\n"); +// log(" -dff\n"); +// log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n"); +// log(" clock domains are automatically partitioned in clock domains and each\n"); +// log(" domain is passed through ABC independently.\n"); +// log("\n"); +// log(" -clk [!][,[!]]\n"); +// log(" use only the specified clock domain. this is like -dff, but only FF\n"); +// log(" cells that belong to the specified clock domain are used.\n"); +// log("\n"); +// log(" -keepff\n"); +// log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n"); +// log(" them, for example for equivalence checking.)\n"); +// log("\n"); +// log(" -nocleanup\n"); +// log(" when this option is used, the temporary files created by this pass\n"); +// log(" are not removed. this is useful for debugging.\n"); +// log("\n"); + log(" -showtmp\n"); + log(" print the temp dir name in log. usually this is suppressed so that the\n"); + log(" command output is identical across runs.\n"); + log("\n"); + log(" -markgroups\n"); + log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n"); + log(" this attribute is a unique integer for each ABC process started. This\n"); + log(" is useful for debugging the partitioning of clock domains.\n"); + log("\n"); + log(" -box \n"); + log(" pass this file with box library to ABC. Use with -lut.\n"); + log("\n"); + log(" -tempdir \n"); + log(" use this as the temp dir.\n"); + log("\n"); + log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); + log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); + log("ABC on logic snippets extracted from your design. You will not get any useful\n"); + log("output when passing an ABC script that writes a file. Instead write your full\n"); + log("design as BLIF file with write_blif and then load that into ABC externally if\n"); + log("you want to use ABC to convert your design into another format.\n"); + log("\n"); + log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing ABC9_MAP pass (technology mapping using ABC9).\n"); + log_push(); + + assign_map.clear(); + +#ifdef ABCEXTERNAL + std::string exe_file = ABCEXTERNAL; +#else + std::string exe_file = proc_self_dirname() + "yosys-abc"; +#endif + std::string script_file, clk_str, box_file, lut_file; + std::string delay_target, lutin_shared = "-S 1", wire_delay; + std::string tempdir_name; + bool fast_mode = false, dff_mode = false, keepff = false /*, cleanup = true*/; + bool show_tempdir = false; + bool nomfs = false; + vector lut_costs; + markgroups = false; + +#if 0 + cleanup = false; + show_tempdir = true; +#endif + +#ifdef _WIN32 +#ifndef ABCEXTERNAL + if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe")) + exe_file = proc_self_dirname() + "..\\yosys-abc"; +#endif +#endif + + size_t argidx; + char pwd [PATH_MAX]; + if (!getcwd(pwd, sizeof(pwd))) { + log_cmd_error("getcwd failed: %s\n", strerror(errno)); + log_abort(); + } + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-exe" && argidx+1 < args.size()) { + exe_file = args[++argidx]; + continue; + } + if (arg == "-script" && argidx+1 < args.size()) { + script_file = args[++argidx]; + rewrite_filename(script_file); + if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+') + script_file = std::string(pwd) + "/" + script_file; + continue; + } + if (arg == "-D" && argidx+1 < args.size()) { + delay_target = "-D " + args[++argidx]; + continue; + } + //if (arg == "-S" && argidx+1 < args.size()) { + // lutin_shared = "-S " + args[++argidx]; + // continue; + //} + if (arg == "-lut" && argidx+1 < args.size()) { + string arg = args[++argidx]; + if (arg.find_first_not_of("0123456789:") == std::string::npos) { + size_t pos = arg.find_first_of(':'); + int lut_mode = 0, lut_mode2 = 0; + if (pos != string::npos) { + lut_mode = atoi(arg.substr(0, pos).c_str()); + lut_mode2 = atoi(arg.substr(pos+1).c_str()); + } else { + lut_mode = atoi(arg.c_str()); + lut_mode2 = lut_mode; + } + lut_costs.clear(); + for (int i = 0; i < lut_mode; i++) + lut_costs.push_back(1); + for (int i = lut_mode; i < lut_mode2; i++) + lut_costs.push_back(2 << (i - lut_mode)); + } + else { + lut_file = arg; + rewrite_filename(lut_file); + if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+') + lut_file = std::string(pwd) + "/" + lut_file; + } + continue; + } + if (arg == "-luts" && argidx+1 < args.size()) { + lut_costs.clear(); + for (auto &tok : split_tokens(args[++argidx], ",")) { + auto parts = split_tokens(tok, ":"); + if (GetSize(parts) == 0 && !lut_costs.empty()) + lut_costs.push_back(lut_costs.back()); + else if (GetSize(parts) == 1) + lut_costs.push_back(atoi(parts.at(0).c_str())); + else if (GetSize(parts) == 2) + while (GetSize(lut_costs) < atoi(parts.at(0).c_str())) + lut_costs.push_back(atoi(parts.at(1).c_str())); + else + log_cmd_error("Invalid -luts syntax.\n"); + } + continue; + } + if (arg == "-fast") { + fast_mode = true; + continue; + } + //if (arg == "-dff") { + // dff_mode = true; + // continue; + //} + //if (arg == "-clk" && argidx+1 < args.size()) { + // clk_str = args[++argidx]; + // dff_mode = true; + // continue; + //} + //if (arg == "-keepff") { + // keepff = true; + // continue; + //} + //if (arg == "-nocleanup") { + // cleanup = false; + // continue; + //} + if (arg == "-showtmp") { + show_tempdir = true; + continue; + } + if (arg == "-markgroups") { + markgroups = true; + continue; + } + if (arg == "-box" && argidx+1 < args.size()) { + box_file = args[++argidx]; + continue; + } + if (arg == "-W" && argidx+1 < args.size()) { + wire_delay = "-W " + args[++argidx]; + continue; + } + if (arg == "-nomfs") { + nomfs = true; + continue; + } + if (arg == "-tempdir" && argidx+1 < args.size()) { + tempdir_name = args[++argidx]; + continue; + } + break; + } + extra_args(args, argidx, design); + + // ABC expects a box file for XAIG + if (box_file.empty()) + box_file = "+/dummy.box"; + + rewrite_filename(box_file); + if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+') + box_file = std::string(pwd) + "/" + box_file; + + if (tempdir_name.empty()) + log_cmd_error("abc9_map '-tempdir' option is mandatory.\n"); + + dict box_lookup; + for (auto m : design->modules()) { + auto it = m->attributes.find(ID(abc9_box_id)); + if (it == m->attributes.end()) + continue; + if (m->name.begins_with("$paramod")) + continue; + auto id = it->second.as_int(); + auto r = box_lookup.insert(std::make_pair(id, m->name)); + if (!r.second) + log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", + log_id(m), id, log_id(r.first->second)); + log_assert(r.second); + + RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; + for (auto p : m->ports) { + auto w = m->wire(p); + log_assert(w); + if (w->attributes.count(ID(abc9_carry))) { + if (w->port_input) { + if (carry_in) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); + carry_in = w; + } + else if (w->port_output) { + if (carry_out) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); + carry_out = w; + } + } + } + if (carry_in || carry_out) { + if (carry_in && !carry_out) + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); + if (!carry_in && carry_out) + log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); + // Make carry_in the last PI, and carry_out the last PO + // since ABC requires it this way + auto &ports = m->ports; + for (auto it = ports.begin(); it != ports.end(); ) { + RTLIL::Wire* w = m->wire(*it); + log_assert(w); + if (w == carry_in || w == carry_out) { + it = ports.erase(it); + continue; + } + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); + ++it; + } + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); + } + } + + for (auto mod : design->selected_modules()) + { + if (mod->attributes.count(ID(abc9_box_id))) + continue; + + if (mod->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(mod)); + continue; + } + + assign_map.set(mod); + + if (!dff_mode || !clk_str.empty()) { + abc9_module(design, mod, script_file, exe_file, /*cleanup,*/ lut_costs, dff_mode, clk_str, keepff, + delay_target, lutin_shared, fast_mode, show_tempdir, + box_file, lut_file, wire_delay, box_lookup, nomfs, tempdir_name); + continue; + } + + CellTypes ct(design); + + std::vector all_cells = mod->selected_cells(); + std::set unassigned_cells(all_cells.begin(), all_cells.end()); + + std::set expand_queue, next_expand_queue; + std::set expand_queue_up, next_expand_queue_up; + std::set expand_queue_down, next_expand_queue_down; + + typedef tuple clkdomain_t; + std::map> assigned_cells; + std::map assigned_cells_reverse; + + std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; + std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; + + for (auto cell : all_cells) + { + clkdomain_t key; + + for (auto &conn : cell->connections()) + for (auto bit : conn.second) { + bit = assign_map(bit); + if (bit.wire != nullptr) { + cell_to_bit[cell].insert(bit); + bit_to_cell[bit].insert(cell); + if (ct.cell_input(cell->type, conn.first)) { + cell_to_bit_up[cell].insert(bit); + bit_to_cell_down[bit].insert(cell); + } + if (ct.cell_output(cell->type, conn.first)) { + cell_to_bit_down[cell].insert(bit); + bit_to_cell_up[bit].insert(cell); + } + } + } + + if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) + { + key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); + } + else + if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + { + bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); + bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E)))); + } + else + continue; + + unassigned_cells.erase(cell); + expand_queue.insert(cell); + expand_queue_up.insert(cell); + expand_queue_down.insert(cell); + + assigned_cells[key].push_back(cell); + assigned_cells_reverse[cell] = key; + } + + while (!expand_queue_up.empty() || !expand_queue_down.empty()) + { + if (!expand_queue_up.empty()) + { + RTLIL::Cell *cell = *expand_queue_up.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_up.erase(cell); + + for (auto bit : cell_to_bit_up[cell]) + for (auto c : bit_to_cell_up[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (!expand_queue_down.empty()) + { + RTLIL::Cell *cell = *expand_queue_down.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_down.erase(cell); + + for (auto bit : cell_to_bit_down[cell]) + for (auto c : bit_to_cell_down[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (expand_queue_up.empty() && expand_queue_down.empty()) { + expand_queue_up.swap(next_expand_queue_up); + expand_queue_down.swap(next_expand_queue_down); + } + } + + while (!expand_queue.empty()) + { + RTLIL::Cell *cell = *expand_queue.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue.erase(cell); + + for (auto bit : cell_to_bit.at(cell)) { + for (auto c : bit_to_cell[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + } + bit_to_cell[bit].clear(); + } + + if (expand_queue.empty()) + expand_queue.swap(next_expand_queue); + } + + clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); + for (auto cell : unassigned_cells) { + assigned_cells[key].push_back(cell); + assigned_cells_reverse[cell] = key; + } + + log_header(design, "Summary of detected clock domains:\n"); + for (auto &it : assigned_cells) + log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), + std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), + std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + + for (auto &it : assigned_cells) { + clk_polarity = std::get<0>(it.first); + clk_sig = assign_map(std::get<1>(it.first)); + en_polarity = std::get<2>(it.first); + en_sig = assign_map(std::get<3>(it.first)); + abc9_module(design, mod, script_file, exe_file, /*cleanup,*/ lut_costs, !clk_sig.empty(), "$", + keepff, delay_target, lutin_shared, fast_mode, show_tempdir, + box_file, lut_file, wire_delay, box_lookup, nomfs, tempdir_name); + assign_map.set(mod); + } + } + + assign_map.clear(); + + log_pop(); + } +} Abc9TechmapPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc new file mode 100644 index 000000000..4c30efd06 --- /dev/null +++ b/passes/techmap/abc9_ops.cc @@ -0,0 +1,139 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void break_scc(RTLIL::Module *module) +{ + // For every unique SCC found, (arbitrarily) find the first + // cell in the component, and convert all wires driven by + // its output ports into a new PO, and drive its previous + // sinks with a new PI + pool ids_seen; + for (auto cell : module->selected_cells()) { + auto it = cell->attributes.find(ID(abc9_scc_id)); + if (it == cell->attributes.end()) + continue; + auto r = ids_seen.insert(it->second); + cell->attributes.erase(it); + if (!r.second) + continue; + for (auto &c : cell->connections_) { + if (c.second.is_fully_const()) continue; + if (cell->output(c.first)) { + SigBit b = c.second.as_bit(); + Wire *w = b.wire; + if (w->port_input) { + // In this case, hopefully the loop break has been already created + // Get the non-prefixed wire + Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str())); + log_assert(wo != nullptr); + log_assert(wo->port_output); + log_assert(b.offset < GetSize(wo)); + c.second = RTLIL::SigBit(wo, b.offset); + } + else { + // Create a new output/input loop break + w->port_input = true; + w = module->wire(stringf("%s.abco", w->name.c_str())); + if (!w) { + w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire)); + w->port_output = true; + } + else { + log_assert(w->port_input); + log_assert(b.offset < GetSize(w)); + } + w->set_bool_attribute(ID(abc9_scc_break)); + c.second = RTLIL::SigBit(w, b.offset); + } + } + } + } + + module->fixup_ports(); +} + +void unbreak_scc(RTLIL::Module *module) { + // Now 'unexpose' those wires by undoing + // the expose operation -- remove them from PO/PI + // and re-connecting them back together + for (auto wire : module->wires()) { + auto it = wire->attributes.find(ID(abc9_scc_break)); + if (it != wire->attributes.end()) { + wire->attributes.erase(it); + log_assert(wire->port_output); + wire->port_output = false; + std::string name = wire->name.str(); + RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5)); + log_assert(i_wire); + log_assert(i_wire->port_input); + i_wire->port_input = false; + module->connect(i_wire, wire); + } + } + module->fixup_ports(); +} + +struct Abc9PrepPass : public Pass { + Abc9PrepPass() : Pass("abc9_ops", "helper functions for ABC9") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" abc9_ops [options] [selection]\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing ABC9_OPS pass (helper functions for ABC9).\n"); + log_push(); + + bool break_scc_mode = false; + bool unbreak_scc_mode = false; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-break_scc") { + break_scc_mode = true; + continue; + } + if (arg == "-unbreak_scc") { + unbreak_scc_mode = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + for (auto mod : design->selected_modules()) { + if (break_scc_mode) + break_scc(mod); + if (unbreak_scc_mode) + unbreak_scc(mod); + } + } +} Abc9PrepPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/abc9_techmap.cc b/passes/techmap/abc9_techmap.cc deleted file mode 100644 index 7ff68f382..000000000 --- a/passes/techmap/abc9_techmap.cc +++ /dev/null @@ -1,1310 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Eddie Hung - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -// [[CITE]] ABC -// Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification -// http://www.eecs.berkeley.edu/~alanmi/abc/ - -#if 0 -// Based on &flow3 - better QoR but more experimental -#define ABC_COMMAND_LUT "&st; &ps -l; &sweep -v; &scorr; " \ - "&st; &if {W}; &save; &st; &syn2; &if {W} -v; &save; &load; "\ - "&st; &if -g -K 6; &dch -f; &if {W} -v; &save; &load; "\ - "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ - "&mfs; &ps -l" -#else -#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" -#endif - - -#define ABC_FAST_COMMAND_LUT "&st; &if {W} {D}" - -#include "kernel/register.h" -#include "kernel/sigtools.h" -#include "kernel/celltypes.h" -#include "kernel/cost.h" -#include "kernel/log.h" -#include -#include -#include -#include -#include -#include - -#ifndef _WIN32 -# include -# include -#endif - -#include "frontends/aiger/aigerparse.h" -#include "kernel/utils.h" - -#ifdef YOSYS_LINK_ABC -extern "C" int Abc_RealMain(int argc, char *argv[]); -#endif - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -bool markgroups; -int map_autoidx; -SigMap assign_map; -RTLIL::Module *module; - -bool clk_polarity, en_polarity; -RTLIL::SigSpec clk_sig, en_sig; - -inline std::string remap_name(RTLIL::IdString abc9_name) -{ - return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1); -} - -void handle_loops(RTLIL::Design *design) -{ - Pass::call(design, "scc -set_attr abc9_scc_id {}"); - - // For every unique SCC found, (arbitrarily) find the first - // cell in the component, and select (and mark) all its output - // wires - pool ids_seen; - for (auto cell : module->cells()) { - auto it = cell->attributes.find(ID(abc9_scc_id)); - if (it != cell->attributes.end()) { - auto r = ids_seen.insert(it->second); - if (r.second) { - for (auto &c : cell->connections_) { - if (c.second.is_fully_const()) continue; - if (cell->output(c.first)) { - SigBit b = c.second.as_bit(); - Wire *w = b.wire; - if (w->port_input) { - // In this case, hopefully the loop break has been already created - // Get the non-prefixed wire - Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str())); - log_assert(wo != nullptr); - log_assert(wo->port_output); - log_assert(b.offset < GetSize(wo)); - c.second = RTLIL::SigBit(wo, b.offset); - } - else { - // Create a new output/input loop break - w->port_input = true; - w = module->wire(stringf("%s.abco", w->name.c_str())); - if (!w) { - w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire)); - w->port_output = true; - } - else { - log_assert(w->port_input); - log_assert(b.offset < GetSize(w)); - } - w->set_bool_attribute(ID(abc9_scc_break)); - c.second = RTLIL::SigBit(w, b.offset); - } - } - } - } - cell->attributes.erase(it); - } - } - - module->fixup_ports(); -} - -std::string add_echos_to_abc9_cmd(std::string str) -{ - std::string new_str, token; - for (size_t i = 0; i < str.size(); i++) { - token += str[i]; - if (str[i] == ';') { - while (i+1 < str.size() && str[i+1] == ' ') - i++; - new_str += "echo + " + token + " " + token + " "; - token.clear(); - } - } - - if (!token.empty()) { - if (!new_str.empty()) - new_str += "echo + " + token + "; "; - new_str += token; - } - - return new_str; -} - -std::string fold_abc9_cmd(std::string str) -{ - std::string token, new_str = " "; - int char_counter = 10; - - for (size_t i = 0; i <= str.size(); i++) { - if (i < str.size()) - token += str[i]; - if (i == str.size() || str[i] == ';') { - if (char_counter + token.size() > 75) - new_str += "\n ", char_counter = 14; - new_str += token, char_counter += token.size(); - token.clear(); - } - } - - return new_str; -} - -std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir) -{ - if (show_tempdir) - return text; - - while (1) { - size_t pos = text.find(tempdir_name); - if (pos == std::string::npos) - break; - text = text.substr(0, pos) + "" + text.substr(pos + GetSize(tempdir_name)); - } - - std::string selfdir_name = proc_self_dirname(); - if (selfdir_name != "/") { - while (1) { - size_t pos = text.find(selfdir_name); - if (pos == std::string::npos) - break; - text = text.substr(0, pos) + "/" + text.substr(pos + GetSize(selfdir_name)); - } - } - - return text; -} - -struct abc9_output_filter -{ - bool got_cr; - int escape_seq_state; - std::string linebuf; - std::string tempdir_name; - bool show_tempdir; - - abc9_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir) - { - got_cr = false; - escape_seq_state = 0; - } - - void next_char(char ch) - { - if (escape_seq_state == 0 && ch == '\033') { - escape_seq_state = 1; - return; - } - if (escape_seq_state == 1) { - escape_seq_state = ch == '[' ? 2 : 0; - return; - } - if (escape_seq_state == 2) { - if ((ch < '0' || '9' < ch) && ch != ';') - escape_seq_state = 0; - return; - } - escape_seq_state = 0; - if (ch == '\r') { - got_cr = true; - return; - } - if (ch == '\n') { - log("ABC: %s\n", replace_tempdir(linebuf, tempdir_name, show_tempdir).c_str()); - got_cr = false, linebuf.clear(); - return; - } - if (got_cr) - got_cr = false, linebuf.clear(); - linebuf += ch; - } - - void next_line(const std::string &line) - { - //int pi, po; - //if (sscanf(line.c_str(), "Start-point = pi%d. End-point = po%d.", &pi, &po) == 2) { - // log("ABC: Start-point = pi%d (%s). End-point = po%d (%s).\n", - // pi, pi_map.count(pi) ? pi_map.at(pi).c_str() : "???", - // po, po_map.count(po) ? po_map.at(po).c_str() : "???"); - // return; - //} - - for (char ch : line) - next_char(ch); - } -}; - -void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, - bool cleanup, vector lut_costs, bool dff_mode, std::string clk_str, - bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, - bool show_tempdir, std::string box_file, std::string lut_file, - std::string wire_delay, const dict &box_lookup, bool nomfs -) -{ - module = current_module; - map_autoidx = autoidx++; - - if (clk_str != "$") - { - clk_polarity = true; - clk_sig = RTLIL::SigSpec(); - - en_polarity = true; - en_sig = RTLIL::SigSpec(); - } - - if (!clk_str.empty() && clk_str != "$") - { - if (clk_str.find(',') != std::string::npos) { - int pos = clk_str.find(','); - std::string en_str = clk_str.substr(pos+1); - clk_str = clk_str.substr(0, pos); - if (en_str[0] == '!') { - en_polarity = false; - en_str = en_str.substr(1); - } - if (module->wires_.count(RTLIL::escape_id(en_str)) != 0) - en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0)); - } - if (clk_str[0] == '!') { - clk_polarity = false; - clk_str = clk_str.substr(1); - } - if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0) - clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0)); - } - - if (dff_mode && clk_sig.empty()) - log_cmd_error("Clock domain %s not found.\n", clk_str.c_str()); - - std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; - if (!cleanup) - tempdir_name[0] = tempdir_name[4] = '_'; - tempdir_name = make_temp_dir(tempdir_name); - log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", - module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); - - std::string abc9_script; - - if (!lut_costs.empty()) { - abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); - if (!box_file.empty()) - abc9_script += stringf("read_box -v %s; ", box_file.c_str()); - } - else - if (!lut_file.empty()) { - abc9_script += stringf("read_lut %s; ", lut_file.c_str()); - if (!box_file.empty()) - abc9_script += stringf("read_box -v %s; ", box_file.c_str()); - } - else - log_abort(); - - abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); - - if (!script_file.empty()) { - if (script_file[0] == '+') { - for (size_t i = 1; i < script_file.size(); i++) - if (script_file[i] == '\'') - abc9_script += "'\\''"; - else if (script_file[i] == ',') - abc9_script += " "; - else - abc9_script += script_file[i]; - } else - abc9_script += stringf("source %s", script_file.c_str()); - } else if (!lut_costs.empty() || !lut_file.empty()) { - //bool all_luts_cost_same = true; - //for (int this_cost : lut_costs) - // if (this_cost != lut_costs.front()) - // all_luts_cost_same = false; - abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; - //if (all_luts_cost_same && !fast_mode) - // abc9_script += "; lutpack {S}"; - } else - log_abort(); - - //if (script_file.empty() && !delay_target.empty()) - // for (size_t pos = abc9_script.find("dretime;"); pos != std::string::npos; pos = abc9_script.find("dretime;", pos+1)) - // abc9_script = abc9_script.substr(0, pos) + "dretime; retime -o {D};" + abc9_script.substr(pos+8); - - for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos)) - abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3); - - //for (size_t pos = abc9_script.find("{S}"); pos != std::string::npos; pos = abc9_script.find("{S}", pos)) - // abc9_script = abc9_script.substr(0, pos) + lutin_shared + abc9_script.substr(pos+3); - - for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos)) - abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3); - - if (nomfs) - for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) - abc9_script = abc9_script.erase(pos, strlen("&mfs")); - - abc9_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); - abc9_script = add_echos_to_abc9_cmd(abc9_script); - - for (size_t i = 0; i+1 < abc9_script.size(); i++) - if (abc9_script[i] == ';' && abc9_script[i+1] == ' ') - abc9_script[i+1] = '\n'; - - FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); - fprintf(f, "%s\n", abc9_script.c_str()); - fclose(f); - - if (dff_mode || !clk_str.empty()) - { - if (clk_sig.size() == 0) - log("No%s clock domain found. Not extracting any FF cells.\n", clk_str.empty() ? "" : " matching"); - else { - log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); - if (en_sig.size() != 0) - log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); - log("\n"); - } - } - - bool count_output = false; - for (auto port_name : module->ports) { - RTLIL::Wire *port_wire = module->wire(port_name); - log_assert(port_wire); - if (port_wire->port_output) { - count_output = true; - break; - } - } - - log_push(); - - if (count_output) - { - design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = design->selection_stack.back(); - sel.select(module); - - handle_loops(design); - - Pass::call(design, "aigmap"); - - //log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", - // count_gates, GetSize(signal_list), count_input, count_output); - - Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); - - std::string buffer; - std::ifstream ifs; -#if 0 - buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig"); - ifs.open(buffer); - if (ifs.fail()) - log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); - buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); - log_assert(!design->module(ID($__abc9__))); - { - AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); - reader.parse_xaiger(); - } - ifs.close(); - Pass::call(design, stringf("write_verilog -noexpr -norename")); - design->remove(design->module(ID($__abc9__))); -#endif - - design->selection_stack.pop_back(); - - log_header(design, "Executing ABC9_MAP.\n"); - - if (!lut_costs.empty()) { - buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); - f = fopen(buffer.c_str(), "wt"); - if (f == NULL) - log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); - for (int i = 0; i < GetSize(lut_costs); i++) - fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i)); - fclose(f); - } - - buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str()); - log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str()); - -#ifndef YOSYS_LINK_ABC - abc9_output_filter filt(tempdir_name, show_tempdir); - int ret = run_command(buffer, std::bind(&abc9_output_filter::next_line, filt, std::placeholders::_1)); -#else - // These needs to be mutable, supposedly due to getopt - char *abc9_argv[5]; - string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str()); - abc9_argv[0] = strdup(exe_file.c_str()); - abc9_argv[1] = strdup("-s"); - abc9_argv[2] = strdup("-f"); - abc9_argv[3] = strdup(tmp_script_name.c_str()); - abc9_argv[4] = 0; - int ret = Abc_RealMain(4, abc9_argv); - free(abc9_argv[0]); - free(abc9_argv[1]); - free(abc9_argv[2]); - free(abc9_argv[3]); -#endif - if (ret != 0) - log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); - - buffer = stringf("%s/%s", tempdir_name.c_str(), "output.aig"); - ifs.open(buffer, std::ifstream::binary); - if (ifs.fail()) - log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); - - buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); - log_assert(!design->module(ID($__abc9__))); - - AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); - reader.parse_xaiger(box_lookup); - ifs.close(); - -#if 0 - Pass::call(design, stringf("write_verilog -noexpr -norename")); -#endif - - log_header(design, "Re-integrating ABC9 results.\n"); - RTLIL::Module *mapped_mod = design->module(ID($__abc9__)); - if (mapped_mod == NULL) - log_error("ABC output file does not contain a module `$__abc9__'.\n"); - - pool output_bits; - for (auto &it : mapped_mod->wires_) { - RTLIL::Wire *w = it.second; - RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w)); - if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx; - if (w->port_output) { - RTLIL::Wire *wire = module->wire(w->name); - log_assert(wire); - for (int i = 0; i < GetSize(w); i++) - output_bits.insert({wire, i}); - } - } - - for (auto &it : module->connections_) { - auto &signal = it.first; - auto bits = signal.bits(); - for (auto &b : bits) - if (output_bits.count(b)) - b = module->addWire(NEW_ID); - signal = std::move(bits); - } - - dict abc9_box; - vector boxes; - for (const auto &it : module->cells_) { - auto cell = it.second; - if (cell->type.in(ID($_AND_), ID($_NOT_))) { - module->remove(cell); - continue; - } - auto jt = abc9_box.find(cell->type); - if (jt == abc9_box.end()) { - RTLIL::Module* box_module = design->module(cell->type); - jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; - } - if (jt->second) - boxes.emplace_back(cell); - } - - dict> bit_drivers, bit_users; - TopoSort toposort; - dict not2drivers; - dict> bit2sinks; - - std::map cell_stats; - for (auto c : mapped_mod->cells()) - { - toposort.node(c->name); - - RTLIL::Cell *cell = nullptr; - if (c->type == ID($_NOT_)) { - RTLIL::SigBit a_bit = c->getPort(ID::A); - RTLIL::SigBit y_bit = c->getPort(ID::Y); - bit_users[a_bit].insert(c->name); - bit_drivers[y_bit].insert(c->name); - - if (!a_bit.wire) { - c->setPort(ID::Y, module->addWire(NEW_ID)); - RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); - log_assert(wire); - module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1); - } - else if (!lut_costs.empty() || !lut_file.empty()) { - RTLIL::Cell* driver_lut = nullptr; - // ABC can return NOT gates that drive POs - if (!a_bit.wire->port_input) { - // If it's not a NOT gate that that comes from a PI directly, - // find the driver LUT and clone that to guarantee that we won't - // increase the max logic depth - // (TODO: Optimise by not cloning unless will increase depth) - RTLIL::IdString driver_name; - if (GetSize(a_bit.wire) == 1) - driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); - else - driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); - driver_lut = mapped_mod->cell(driver_name); - } - - if (!driver_lut) { - // If a driver couldn't be found (could be from PI or box CI) - // then implement using a LUT - cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), - RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), - RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), - RTLIL::Const::from_string("01")); - bit2sinks[cell->getPort(ID::A)].push_back(cell); - cell_stats[ID($lut)]++; - } - else - not2drivers[c] = driver_lut; - continue; - } - else - log_abort(); - if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; - continue; - } - cell_stats[c->type]++; - - RTLIL::Cell *existing_cell = nullptr; - if (c->type == ID($lut)) { - if (GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) { - SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID::A).as_wire()->name)); - SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID::Y).as_wire()->name)); - module->connect(my_y, my_a); - if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx; - log_abort(); - continue; - } - cell = module->addCell(remap_name(c->name), c->type); - } - else { - existing_cell = module->cell(c->name); - log_assert(existing_cell); - cell = module->addCell(remap_name(c->name), c->type); - } - - if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; - if (existing_cell) { - cell->parameters = existing_cell->parameters; - cell->attributes = existing_cell->attributes; - } - else { - cell->parameters = c->parameters; - cell->attributes = c->attributes; - } - for (auto &conn : c->connections()) { - RTLIL::SigSpec newsig; - for (auto c : conn.second.chunks()) { - if (c.width == 0) - continue; - //log_assert(c.width == 1); - if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); - newsig.append(c); - } - cell->setPort(conn.first, newsig); - - if (cell->input(conn.first)) { - for (auto i : newsig) - bit2sinks[i].push_back(cell); - for (auto i : conn.second) - bit_users[i].insert(c->name); - } - if (cell->output(conn.first)) - for (auto i : conn.second) - bit_drivers[i].insert(c->name); - } - } - - for (auto existing_cell : boxes) { - Cell *cell = module->cell(remap_name(existing_cell->name)); - if (cell) { - for (auto &conn : existing_cell->connections()) { - if (!conn.second.is_wire()) - continue; - Wire *wire = conn.second.as_wire(); - if (!wire->get_bool_attribute(ID(abc9_padding))) - continue; - cell->unsetPort(conn.first); - log_debug("Dropping padded port connection for %s (%s) .%s (%s )\n", log_id(cell), cell->type.c_str(), log_id(conn.first), log_signal(conn.second)); - } - module->swap_names(cell, existing_cell); - } - module->remove(existing_cell); - } - - // Copy connections (and rename) from mapped_mod to module - for (auto conn : mapped_mod->connections()) { - if (!conn.first.is_fully_const()) { - auto chunks = conn.first.chunks(); - for (auto &c : chunks) - c.wire = module->wires_.at(remap_name(c.wire->name)); - conn.first = std::move(chunks); - } - if (!conn.second.is_fully_const()) { - auto chunks = conn.second.chunks(); - for (auto &c : chunks) - if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); - conn.second = std::move(chunks); - } - module->connect(conn); - } - - for (auto &it : cell_stats) - log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); - int in_wires = 0, out_wires = 0; - - // Stitch in mapped_mod's inputs/outputs into module - for (auto port : mapped_mod->ports) { - RTLIL::Wire *w = mapped_mod->wire(port); - RTLIL::Wire *wire = module->wire(port); - log_assert(wire); - RTLIL::Wire *remap_wire = module->wire(remap_name(port)); - RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); - log_assert(GetSize(signal) >= GetSize(remap_wire)); - - RTLIL::SigSig conn; - if (w->port_output) { - conn.first = signal; - conn.second = remap_wire; - out_wires++; - module->connect(conn); - } - else if (w->port_input) { - conn.first = remap_wire; - conn.second = signal; - in_wires++; - module->connect(conn); - } - } - - 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); - bool no_loops YS_ATTRIBUTE(unused) = toposort.sort(); - log_assert(no_loops); - - for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) { - RTLIL::Cell *not_cell = mapped_mod->cell(*ii); - log_assert(not_cell); - if (not_cell->type != ID($_NOT_)) - continue; - auto it = not2drivers.find(not_cell); - if (it == not2drivers.end()) - continue; - RTLIL::Cell *driver_lut = it->second; - RTLIL::SigBit a_bit = not_cell->getPort(ID::A); - RTLIL::SigBit y_bit = not_cell->getPort(ID::Y); - RTLIL::Const driver_mask; - - a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); - y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); - - auto jt = bit2sinks.find(a_bit); - if (jt == bit2sinks.end()) - goto clone_lut; - - for (auto sink_cell : jt->second) - if (sink_cell->type != ID($lut)) - goto clone_lut; - - // Push downstream LUTs past inverter - for (auto sink_cell : jt->second) { - SigSpec A = sink_cell->getPort(ID::A); - RTLIL::Const mask = sink_cell->getParam(ID(LUT)); - int index = 0; - for (; index < GetSize(A); index++) - if (A[index] == a_bit) - break; - log_assert(index < GetSize(A)); - int i = 0; - while (i < GetSize(mask)) { - for (int j = 0; j < (1 << index); j++) - std::swap(mask[i+j], mask[i+j+(1 << index)]); - i += 1 << (index+1); - } - A[index] = y_bit; - sink_cell->setPort(ID::A, A); - sink_cell->setParam(ID(LUT), mask); - } - - // Since we have rewritten all sinks (which we know - // to be only LUTs) to be after the inverter, we can - // go ahead and clone the LUT with the expectation - // that the original driving LUT will become dangling - // and get cleaned away -clone_lut: - driver_mask = driver_lut->getParam(ID(LUT)); - for (auto &b : driver_mask.bits) { - if (b == RTLIL::State::S0) b = RTLIL::State::S1; - else if (b == RTLIL::State::S1) b = RTLIL::State::S0; - } - auto cell = module->addLut(NEW_ID, - driver_lut->getPort(ID::A), - y_bit, - driver_mask); - for (auto &bit : cell->connections_.at(ID::A)) { - bit.wire = module->wires_.at(remap_name(bit.wire->name)); - bit2sinks[bit].push_back(cell); - } - } - - // Now 'unexpose' those wires by undoing - // the expose operation -- remove them from PO/PI - // and re-connecting them back together - for (auto wire : module->wires()) { - auto it = wire->attributes.find(ID(abc9_scc_break)); - if (it != wire->attributes.end()) { - wire->attributes.erase(it); - log_assert(wire->port_output); - wire->port_output = false; - std::string name = wire->name.str(); - RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5)); - log_assert(i_wire); - log_assert(i_wire->port_input); - i_wire->port_input = false; - module->connect(i_wire, wire); - } - } - module->fixup_ports(); - - //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); - log("ABC RESULTS: input signals: %8d\n", in_wires); - log("ABC RESULTS: output signals: %8d\n", out_wires); - - design->remove(mapped_mod); - } - else - { - log("Don't call ABC as there is nothing to map.\n"); - } - - if (cleanup) - { - log("Removing temp directory.\n"); - remove_directory(tempdir_name); - } - - log_pop(); -} - -struct Abc9TechmapPass : public Pass { - Abc9TechmapPass() : Pass("abc9_map", "use ABC9 for technology mapping") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" abc9_map [options] [selection]\n"); - log("\n"); - log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); - log("library to a target architecture.\n"); - log("\n"); - log(" -exe \n"); -#ifdef ABCEXTERNAL - log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); -#else - log(" use the specified command instead of \"/yosys-abc\" to execute ABC.\n"); -#endif - log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n"); - log("\n"); - log(" -script \n"); - log(" use the specified ABC script file instead of the default script.\n"); - log("\n"); - log(" if starts with a plus sign (+), then the rest of the filename\n"); - log(" string is interpreted as the command string to be passed to ABC. The\n"); - log(" leading plus sign is removed and all commas (,) in the string are\n"); - log(" replaced with blanks before the string is passed to ABC.\n"); - log("\n"); - log(" if no -script parameter is given, the following scripts are used:\n"); - log("\n"); - log(" for -lut/-luts (only one LUT size):\n"); - log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); - log("\n"); - log(" for -lut/-luts (different LUT sizes):\n"); - log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); - log("\n"); - log(" -fast\n"); - log(" use different default scripts that are slightly faster (at the cost\n"); - log(" of output quality):\n"); - log("\n"); - log(" for -lut/-luts:\n"); - log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str()); - log("\n"); - log(" -D \n"); - log(" set delay target. the string {D} in the default scripts above is\n"); - log(" replaced by this option when used, and an empty string otherwise\n"); - log(" (indicating best possible delay).\n"); -// log(" This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); -// log(" default scripts above.\n"); - log("\n"); -// log(" -S \n"); -// log(" maximum number of LUT inputs shared.\n"); -// log(" (replaces {S} in the default scripts above, default: -S 1)\n"); -// log("\n"); - log(" -lut \n"); - log(" generate netlist using luts of (max) the specified width.\n"); - log("\n"); - log(" -lut :\n"); - log(" generate netlist using luts of (max) the specified width . All\n"); - log(" luts with width <= have constant cost. for luts larger than \n"); - log(" the area cost doubles with each additional input bit. the delay cost\n"); - log(" is still constant for all lut widths.\n"); - log("\n"); - log(" -lut \n"); - log(" pass this file with lut library to ABC.\n"); - log("\n"); - log(" -luts ,,,:,..\n"); - log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); - log(" 2, 3, .. inputs.\n"); - log("\n"); -// log(" -dff\n"); -// log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n"); -// log(" clock domains are automatically partitioned in clock domains and each\n"); -// log(" domain is passed through ABC independently.\n"); -// log("\n"); -// log(" -clk [!][,[!]]\n"); -// log(" use only the specified clock domain. this is like -dff, but only FF\n"); -// log(" cells that belong to the specified clock domain are used.\n"); -// log("\n"); -// log(" -keepff\n"); -// log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n"); -// log(" them, for example for equivalence checking.)\n"); -// log("\n"); - log(" -nocleanup\n"); - log(" when this option is used, the temporary files created by this pass\n"); - log(" are not removed. this is useful for debugging.\n"); - log("\n"); - log(" -showtmp\n"); - log(" print the temp dir name in log. usually this is suppressed so that the\n"); - log(" command output is identical across runs.\n"); - log("\n"); - log(" -markgroups\n"); - log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n"); - log(" this attribute is a unique integer for each ABC process started. This\n"); - log(" is useful for debugging the partitioning of clock domains.\n"); - log("\n"); - log(" -box \n"); - log(" pass this file with box library to ABC. Use with -lut.\n"); - log("\n"); - log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); - log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); - log("ABC on logic snippets extracted from your design. You will not get any useful\n"); - log("output when passing an ABC script that writes a file. Instead write your full\n"); - log("design as BLIF file with write_blif and then load that into ABC externally if\n"); - log("you want to use ABC to convert your design into another format.\n"); - log("\n"); - log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing ABC9 pass (technology mapping using ABC9).\n"); - log_push(); - - assign_map.clear(); - -#ifdef ABCEXTERNAL - std::string exe_file = ABCEXTERNAL; -#else - std::string exe_file = proc_self_dirname() + "yosys-abc"; -#endif - std::string script_file, clk_str, box_file, lut_file; - std::string delay_target, lutin_shared = "-S 1", wire_delay; - bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; - bool show_tempdir = false; - bool nomfs = false; - vector lut_costs; - markgroups = false; - -#if 0 - cleanup = false; - show_tempdir = true; -#endif - -#ifdef _WIN32 -#ifndef ABCEXTERNAL - if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe")) - exe_file = proc_self_dirname() + "..\\yosys-abc"; -#endif -#endif - - size_t argidx; - char pwd [PATH_MAX]; - if (!getcwd(pwd, sizeof(pwd))) { - log_cmd_error("getcwd failed: %s\n", strerror(errno)); - log_abort(); - } - for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-exe" && argidx+1 < args.size()) { - exe_file = args[++argidx]; - continue; - } - if (arg == "-script" && argidx+1 < args.size()) { - script_file = args[++argidx]; - rewrite_filename(script_file); - if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+') - script_file = std::string(pwd) + "/" + script_file; - continue; - } - if (arg == "-D" && argidx+1 < args.size()) { - delay_target = "-D " + args[++argidx]; - continue; - } - //if (arg == "-S" && argidx+1 < args.size()) { - // lutin_shared = "-S " + args[++argidx]; - // continue; - //} - if (arg == "-lut" && argidx+1 < args.size()) { - string arg = args[++argidx]; - if (arg.find_first_not_of("0123456789:") == std::string::npos) { - size_t pos = arg.find_first_of(':'); - int lut_mode = 0, lut_mode2 = 0; - if (pos != string::npos) { - lut_mode = atoi(arg.substr(0, pos).c_str()); - lut_mode2 = atoi(arg.substr(pos+1).c_str()); - } else { - lut_mode = atoi(arg.c_str()); - lut_mode2 = lut_mode; - } - lut_costs.clear(); - for (int i = 0; i < lut_mode; i++) - lut_costs.push_back(1); - for (int i = lut_mode; i < lut_mode2; i++) - lut_costs.push_back(2 << (i - lut_mode)); - } - else { - lut_file = arg; - rewrite_filename(lut_file); - if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+') - lut_file = std::string(pwd) + "/" + lut_file; - } - continue; - } - if (arg == "-luts" && argidx+1 < args.size()) { - lut_costs.clear(); - for (auto &tok : split_tokens(args[++argidx], ",")) { - auto parts = split_tokens(tok, ":"); - if (GetSize(parts) == 0 && !lut_costs.empty()) - lut_costs.push_back(lut_costs.back()); - else if (GetSize(parts) == 1) - lut_costs.push_back(atoi(parts.at(0).c_str())); - else if (GetSize(parts) == 2) - while (GetSize(lut_costs) < atoi(parts.at(0).c_str())) - lut_costs.push_back(atoi(parts.at(1).c_str())); - else - log_cmd_error("Invalid -luts syntax.\n"); - } - continue; - } - if (arg == "-fast") { - fast_mode = true; - continue; - } - //if (arg == "-dff") { - // dff_mode = true; - // continue; - //} - //if (arg == "-clk" && argidx+1 < args.size()) { - // clk_str = args[++argidx]; - // dff_mode = true; - // continue; - //} - //if (arg == "-keepff") { - // keepff = true; - // continue; - //} - if (arg == "-nocleanup") { - cleanup = false; - continue; - } - if (arg == "-showtmp") { - show_tempdir = true; - continue; - } - if (arg == "-markgroups") { - markgroups = true; - continue; - } - if (arg == "-box" && argidx+1 < args.size()) { - box_file = args[++argidx]; - continue; - } - if (arg == "-W" && argidx+1 < args.size()) { - wire_delay = "-W " + args[++argidx]; - continue; - } - if (arg == "-nomfs") { - nomfs = true; - continue; - } - break; - } - extra_args(args, argidx, design); - - // ABC expects a box file for XAIG - if (box_file.empty()) - box_file = "+/dummy.box"; - - rewrite_filename(box_file); - if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+') - box_file = std::string(pwd) + "/" + box_file; - - dict box_lookup; - for (auto m : design->modules()) { - auto it = m->attributes.find(ID(abc9_box_id)); - if (it == m->attributes.end()) - continue; - if (m->name.begins_with("$paramod")) - continue; - auto id = it->second.as_int(); - auto r = box_lookup.insert(std::make_pair(id, m->name)); - if (!r.second) - log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - log_id(m), id, log_id(r.first->second)); - log_assert(r.second); - - RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; - for (auto p : m->ports) { - auto w = m->wire(p); - log_assert(w); - if (w->attributes.count(ID(abc9_carry))) { - if (w->port_input) { - if (carry_in) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); - carry_in = w; - } - else if (w->port_output) { - if (carry_out) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); - carry_out = w; - } - } - } - if (carry_in || carry_out) { - if (carry_in && !carry_out) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); - if (!carry_in && carry_out) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); - // Make carry_in the last PI, and carry_out the last PO - // since ABC requires it this way - auto &ports = m->ports; - for (auto it = ports.begin(); it != ports.end(); ) { - RTLIL::Wire* w = m->wire(*it); - log_assert(w); - if (w == carry_in || w == carry_out) { - it = ports.erase(it); - continue; - } - if (w->port_id > carry_in->port_id) - --w->port_id; - if (w->port_id > carry_out->port_id) - --w->port_id; - log_assert(w->port_input || w->port_output); - log_assert(ports[w->port_id-1] == w->name); - ++it; - } - ports.push_back(carry_in->name); - carry_in->port_id = ports.size(); - ports.push_back(carry_out->name); - carry_out->port_id = ports.size(); - } - } - - for (auto mod : design->selected_modules()) - { - if (mod->attributes.count(ID(abc9_box_id))) - continue; - - if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); - continue; - } - - assign_map.set(mod); - - if (!dff_mode || !clk_str.empty()) { - abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, - delay_target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay, box_lookup, nomfs); - continue; - } - - CellTypes ct(design); - - std::vector all_cells = mod->selected_cells(); - std::set unassigned_cells(all_cells.begin(), all_cells.end()); - - std::set expand_queue, next_expand_queue; - std::set expand_queue_up, next_expand_queue_up; - std::set expand_queue_down, next_expand_queue_down; - - typedef tuple clkdomain_t; - std::map> assigned_cells; - std::map assigned_cells_reverse; - - std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; - std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; - - for (auto cell : all_cells) - { - clkdomain_t key; - - for (auto &conn : cell->connections()) - for (auto bit : conn.second) { - bit = assign_map(bit); - if (bit.wire != nullptr) { - cell_to_bit[cell].insert(bit); - bit_to_cell[bit].insert(cell); - if (ct.cell_input(cell->type, conn.first)) { - cell_to_bit_up[cell].insert(bit); - bit_to_cell_down[bit].insert(cell); - } - if (ct.cell_output(cell->type, conn.first)) { - cell_to_bit_down[cell].insert(bit); - bit_to_cell_up[bit].insert(cell); - } - } - } - - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) - { - key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec()); - } - else - if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - { - bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); - bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E)))); - } - else - continue; - - unassigned_cells.erase(cell); - expand_queue.insert(cell); - expand_queue_up.insert(cell); - expand_queue_down.insert(cell); - - assigned_cells[key].push_back(cell); - assigned_cells_reverse[cell] = key; - } - - while (!expand_queue_up.empty() || !expand_queue_down.empty()) - { - if (!expand_queue_up.empty()) - { - RTLIL::Cell *cell = *expand_queue_up.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue_up.erase(cell); - - for (auto bit : cell_to_bit_up[cell]) - for (auto c : bit_to_cell_up[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (!expand_queue_down.empty()) - { - RTLIL::Cell *cell = *expand_queue_down.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue_down.erase(cell); - - for (auto bit : cell_to_bit_down[cell]) - for (auto c : bit_to_cell_down[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].push_back(c); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (expand_queue_up.empty() && expand_queue_down.empty()) { - expand_queue_up.swap(next_expand_queue_up); - expand_queue_down.swap(next_expand_queue_down); - } - } - - while (!expand_queue.empty()) - { - RTLIL::Cell *cell = *expand_queue.begin(); - clkdomain_t key = assigned_cells_reverse.at(cell); - expand_queue.erase(cell); - - for (auto bit : cell_to_bit.at(cell)) { - for (auto c : bit_to_cell[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue.insert(c); - assigned_cells[key].push_back(c); - assigned_cells_reverse[c] = key; - } - bit_to_cell[bit].clear(); - } - - if (expand_queue.empty()) - expand_queue.swap(next_expand_queue); - } - - clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); - for (auto cell : unassigned_cells) { - assigned_cells[key].push_back(cell); - assigned_cells_reverse[cell] = key; - } - - log_header(design, "Summary of detected clock domains:\n"); - for (auto &it : assigned_cells) - log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), - std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), - std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); - - for (auto &it : assigned_cells) { - clk_polarity = std::get<0>(it.first); - clk_sig = assign_map(std::get<1>(it.first)); - en_polarity = std::get<2>(it.first); - en_sig = assign_map(std::get<3>(it.first)); - abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$", - keepff, delay_target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay, box_lookup, nomfs); - assign_map.set(mod); - } - } - - assign_map.clear(); - - log_pop(); - } -} Abc9TechmapPass; - -PRIVATE_NAMESPACE_END -- cgit v1.2.3 From 509da7ed1a1e27066451f57868108b473cf516a0 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 28 Dec 2019 16:12:45 +0100 Subject: Revert "Fix xilinx tests, when iopads are default" This reverts commit 477e43d921d204c6bc6403109fea6506802c948c. --- tests/arch/xilinx/add_sub.ys | 2 +- tests/arch/xilinx/adffs.ys | 8 ++++---- tests/arch/xilinx/bug1460.ys | 2 +- tests/arch/xilinx/counter.ys | 2 +- tests/arch/xilinx/dffs.ys | 4 ++-- tests/arch/xilinx/dsp_fastfir.ys | 2 +- tests/arch/xilinx/fsm.ys | 2 +- tests/arch/xilinx/latches.ys | 6 +++--- tests/arch/xilinx/logic.ys | 2 +- tests/arch/xilinx/lutram.ys | 14 +++++++------- tests/arch/xilinx/macc.ys | 4 ++-- tests/arch/xilinx/mul.ys | 2 +- tests/arch/xilinx/mul_unsigned.ys | 2 +- tests/arch/xilinx/mux.ys | 8 ++++---- tests/arch/xilinx/shifter.ys | 2 +- tests/arch/xilinx/xilinx_dffopt.ys | 18 +++++++++--------- 16 files changed, 40 insertions(+), 40 deletions(-) diff --git a/tests/arch/xilinx/add_sub.ys b/tests/arch/xilinx/add_sub.ys index 920717a3d..9dbddce47 100644 --- a/tests/arch/xilinx/add_sub.ys +++ b/tests/arch/xilinx/add_sub.ys @@ -7,5 +7,5 @@ cd top # Constrain all select calls below inside the top module select -assert-count 14 t:LUT2 select -assert-count 6 t:MUXCY select -assert-count 8 t:XORCY -select -assert-none t:LUT2 t:MUXCY t:XORCY t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT2 t:MUXCY t:XORCY %% t:* %D diff --git a/tests/arch/xilinx/adffs.ys b/tests/arch/xilinx/adffs.ys index ba9ddf90f..c0ff6a2e2 100644 --- a/tests/arch/xilinx/adffs.ys +++ b/tests/arch/xilinx/adffs.ys @@ -9,7 +9,7 @@ cd adff # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:FDCE -select -assert-none t:BUFG t:FDCE t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDCE %% t:* %D design -load read @@ -22,7 +22,7 @@ select -assert-count 1 t:BUFG select -assert-count 1 t:FDCE select -assert-count 1 t:INV -select -assert-none t:BUFG t:FDCE t:INV t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDCE t:INV %% t:* %D design -load read @@ -34,7 +34,7 @@ cd dffs # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:FDSE -select -assert-none t:BUFG t:FDSE t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDSE %% t:* %D design -load read @@ -47,4 +47,4 @@ select -assert-count 1 t:BUFG select -assert-count 1 t:FDRE_1 select -assert-count 1 t:INV -select -assert-none t:BUFG t:FDRE_1 t:INV t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE_1 t:INV %% t:* %D diff --git a/tests/arch/xilinx/bug1460.ys b/tests/arch/xilinx/bug1460.ys index 73fb662dc..2018071cc 100644 --- a/tests/arch/xilinx/bug1460.ys +++ b/tests/arch/xilinx/bug1460.ys @@ -31,4 +31,4 @@ EOT synth_xilinx cd register_file select -assert-count 32 t:RAM32M -select -assert-none t:* t:BUFG %d t:IBUF %d t:OBUF %d t:RAM32M %d +select -assert-none t:* t:BUFG %d t:RAM32M %d diff --git a/tests/arch/xilinx/counter.ys b/tests/arch/xilinx/counter.ys index e4217bbaf..604acdbfc 100644 --- a/tests/arch/xilinx/counter.ys +++ b/tests/arch/xilinx/counter.ys @@ -11,4 +11,4 @@ select -assert-count 8 t:FDCE select -assert-count 1 t:INV select -assert-count 7 t:MUXCY select -assert-count 8 t:XORCY -select -assert-none t:BUFG t:FDCE t:INV t:MUXCY t:XORCY t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDCE t:INV t:MUXCY t:XORCY %% t:* %D diff --git a/tests/arch/xilinx/dffs.ys b/tests/arch/xilinx/dffs.ys index b2cb70323..0bba4858f 100644 --- a/tests/arch/xilinx/dffs.ys +++ b/tests/arch/xilinx/dffs.ys @@ -9,7 +9,7 @@ cd dff # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:FDRE -select -assert-none t:BUFG t:FDRE t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE %% t:* %D design -load read @@ -21,5 +21,5 @@ cd dffe # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:FDRE -select -assert-none t:BUFG t:FDRE t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE %% t:* %D diff --git a/tests/arch/xilinx/dsp_fastfir.ys b/tests/arch/xilinx/dsp_fastfir.ys index 05e1785d8..0067a822b 100644 --- a/tests/arch/xilinx/dsp_fastfir.ys +++ b/tests/arch/xilinx/dsp_fastfir.ys @@ -66,4 +66,4 @@ EOT synth_xilinx cd fastfir_dynamictaps select -assert-count 2 t:DSP48E1 -select -assert-none t:* t:DSP48E1 %d t:BUFG %d t:IBUF %d t:OBUF %d +select -assert-none t:* t:DSP48E1 %d t:BUFG %d diff --git a/tests/arch/xilinx/fsm.ys b/tests/arch/xilinx/fsm.ys index d60695e2c..f03400fe7 100644 --- a/tests/arch/xilinx/fsm.ys +++ b/tests/arch/xilinx/fsm.ys @@ -16,4 +16,4 @@ select -assert-count 1 t:FDSE select -assert-count 1 t:LUT2 select -assert-count 3 t:LUT5 select -assert-count 1 t:LUT6 -select -assert-none t:BUFG t:IBUF t:OBUF t:FDRE t:FDSE t:LUT2 t:LUT5 t:LUT6 %% t:* %D +select -assert-none t:BUFG t:FDRE t:FDSE t:LUT2 t:LUT5 t:LUT6 %% t:* %D diff --git a/tests/arch/xilinx/latches.ys b/tests/arch/xilinx/latches.ys index c1caea27a..c87a8e38b 100644 --- a/tests/arch/xilinx/latches.ys +++ b/tests/arch/xilinx/latches.ys @@ -8,7 +8,7 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd latchp # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE -select -assert-none t:LDCE t:IBUF t:OBUF %% t:* %D +select -assert-none t:LDCE %% t:* %D design -load read @@ -20,7 +20,7 @@ cd latchn # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE select -assert-count 1 t:INV -select -assert-none t:LDCE t:INV t:IBUF t:OBUF %% t:* %D +select -assert-none t:LDCE t:INV %% t:* %D design -load read @@ -32,4 +32,4 @@ cd latchsr # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE select -assert-count 2 t:LUT3 -select -assert-none t:LDCE t:LUT3 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LDCE t:LUT3 %% t:* %D diff --git a/tests/arch/xilinx/logic.ys b/tests/arch/xilinx/logic.ys index 2372cca61..d5b5c1a37 100644 --- a/tests/arch/xilinx/logic.ys +++ b/tests/arch/xilinx/logic.ys @@ -8,4 +8,4 @@ cd top # Constrain all select calls below inside the top module select -assert-count 1 t:INV select -assert-count 6 t:LUT2 select -assert-count 2 t:LUT4 -select -assert-none t:INV t:LUT2 t:LUT4 t:IBUF t:OBUF %% t:* %D +select -assert-none t:INV t:LUT2 t:LUT4 %% t:* %D diff --git a/tests/arch/xilinx/lutram.ys b/tests/arch/xilinx/lutram.ys index 951517fa9..6c9d1eae1 100644 --- a/tests/arch/xilinx/lutram.ys +++ b/tests/arch/xilinx/lutram.ys @@ -14,7 +14,7 @@ #select -assert-count 1 t:BUFG #select -assert-count 8 t:FDRE #select -assert-count 8 t:RAM16X1D -#select -assert-none t:BUFG t:FDRE t:RAM16X1D t:IBUF t:OBUF %% t:* %D +#select -assert-none t:BUFG t:FDRE t:RAM16X1D %% t:* %D design -reset @@ -34,7 +34,7 @@ cd lutram_1w1r select -assert-count 1 t:BUFG select -assert-count 8 t:FDRE select -assert-count 8 t:RAM32X1D -select -assert-none t:BUFG t:FDRE t:RAM32X1D t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM32X1D %% t:* %D design -reset @@ -54,7 +54,7 @@ cd lutram_1w1r select -assert-count 1 t:BUFG select -assert-count 8 t:FDRE select -assert-count 8 t:RAM64X1D -select -assert-none t:BUFG t:FDRE t:RAM64X1D t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM64X1D %% t:* %D design -reset @@ -74,7 +74,7 @@ cd lutram_1w3r select -assert-count 1 t:BUFG select -assert-count 24 t:FDRE select -assert-count 4 t:RAM32M -select -assert-none t:BUFG t:FDRE t:RAM32M t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM32M %% t:* %D design -reset @@ -94,7 +94,7 @@ cd lutram_1w3r select -assert-count 1 t:BUFG select -assert-count 24 t:FDRE select -assert-count 8 t:RAM64M -select -assert-none t:BUFG t:FDRE t:RAM64M t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM64M %% t:* %D design -reset @@ -114,7 +114,7 @@ cd lutram_1w1r select -assert-count 1 t:BUFG select -assert-count 6 t:FDRE select -assert-count 1 t:RAM32M -select -assert-none t:BUFG t:FDRE t:RAM32M t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM32M %% t:* %D design -reset @@ -134,4 +134,4 @@ cd lutram_1w1r select -assert-count 1 t:BUFG select -assert-count 6 t:FDRE select -assert-count 2 t:RAM64M -select -assert-none t:BUFG t:FDRE t:RAM64M t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE t:RAM64M %% t:* %D diff --git a/tests/arch/xilinx/macc.ys b/tests/arch/xilinx/macc.ys index 0869a8dae..11e959976 100644 --- a/tests/arch/xilinx/macc.ys +++ b/tests/arch/xilinx/macc.ys @@ -12,7 +12,7 @@ cd macc # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:FDRE select -assert-count 1 t:DSP48E1 -select -assert-none t:BUFG t:FDRE t:DSP48E1 t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE t:DSP48E1 %% t:* %D design -load read hierarchy -top macc2 @@ -29,4 +29,4 @@ select -assert-count 1 t:DSP48E1 select -assert-count 1 t:FDRE select -assert-count 1 t:LUT2 select -assert-count 40 t:LUT3 -select -assert-none t:BUFG t:DSP48E1 t:FDRE t:LUT2 t:LUT3 t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:DSP48E1 t:FDRE t:LUT2 t:LUT3 %% t:* %D diff --git a/tests/arch/xilinx/mul.ys b/tests/arch/xilinx/mul.ys index 100de6629..d76814966 100644 --- a/tests/arch/xilinx/mul.ys +++ b/tests/arch/xilinx/mul.ys @@ -6,4 +6,4 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd top # Constrain all select calls below inside the top module select -assert-count 1 t:DSP48E1 -select -assert-none t:DSP48E1 t:IBUF t:OBUF %% t:* %D +select -assert-none t:DSP48E1 %% t:* %D diff --git a/tests/arch/xilinx/mul_unsigned.ys b/tests/arch/xilinx/mul_unsigned.ys index 59ead5cda..62495b90c 100644 --- a/tests/arch/xilinx/mul_unsigned.ys +++ b/tests/arch/xilinx/mul_unsigned.ys @@ -8,4 +8,4 @@ cd mul_unsigned # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:DSP48E1 select -assert-count 30 t:FDRE -select -assert-none t:DSP48E1 t:FDRE t:BUFG t:IBUF t:OBUF %% t:* %D +select -assert-none t:DSP48E1 t:FDRE t:BUFG %% t:* %D diff --git a/tests/arch/xilinx/mux.ys b/tests/arch/xilinx/mux.ys index faad64cc5..388272449 100644 --- a/tests/arch/xilinx/mux.ys +++ b/tests/arch/xilinx/mux.ys @@ -8,7 +8,7 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd mux2 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT3 -select -assert-none t:LUT3 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT3 %% t:* %D design -load read @@ -19,7 +19,7 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd mux4 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT6 -select -assert-none t:LUT6 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT6 %% t:* %D design -load read @@ -31,7 +31,7 @@ cd mux8 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT3 select -assert-count 2 t:LUT6 -select -assert-none t:LUT3 t:LUT6 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT3 t:LUT6 %% t:* %D design -load read @@ -44,4 +44,4 @@ select -assert-min 5 t:LUT6 select -assert-max 7 t:LUT6 select -assert-max 2 t:MUXF7 -select -assert-none t:LUT6 t:MUXF7 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT6 t:MUXF7 %% t:* %D diff --git a/tests/arch/xilinx/shifter.ys b/tests/arch/xilinx/shifter.ys index 4d63ba9c2..455437f18 100644 --- a/tests/arch/xilinx/shifter.ys +++ b/tests/arch/xilinx/shifter.ys @@ -8,4 +8,4 @@ cd top # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 8 t:FDRE -select -assert-none t:BUFG t:FDRE t:IBUF t:OBUF %% t:* %D +select -assert-none t:BUFG t:FDRE %% t:* %D diff --git a/tests/arch/xilinx/xilinx_dffopt.ys b/tests/arch/xilinx/xilinx_dffopt.ys index 5dbe11b27..dc036acfd 100644 --- a/tests/arch/xilinx/xilinx_dffopt.ys +++ b/tests/arch/xilinx/xilinx_dffopt.ys @@ -28,7 +28,7 @@ clean select -assert-count 1 t:FDRE select -assert-count 1 t:LUT6 select -assert-count 3 t:LUT2 -select -assert-none t:FDRE t:LUT6 t:LUT2 t:IBUF t:OBUF %% t:* %D +select -assert-none t:FDRE t:LUT6 t:LUT2 %% t:* %D design -load t0 @@ -39,7 +39,7 @@ clean select -assert-count 1 t:FDRE select -assert-count 1 t:LUT4 select -assert-count 3 t:LUT2 -select -assert-none t:FDRE t:LUT4 t:LUT2 t:IBUF t:OBUF %% t:* %D +select -assert-none t:FDRE t:LUT4 t:LUT2 %% t:* %D design -reset @@ -74,7 +74,7 @@ clean select -assert-count 1 t:FDSE select -assert-count 1 t:LUT6 select -assert-count 3 t:LUT2 -select -assert-none t:FDSE t:LUT6 t:LUT2 t:IBUF t:OBUF %% t:* %D +select -assert-none t:FDSE t:LUT6 t:LUT2 %% t:* %D design -load t0 @@ -85,7 +85,7 @@ clean select -assert-count 1 t:FDSE select -assert-count 1 t:LUT4 select -assert-count 3 t:LUT2 -select -assert-none t:FDSE t:LUT4 t:LUT2 t:IBUF t:OBUF %% t:* %D +select -assert-none t:FDSE t:LUT4 t:LUT2 %% t:* %D design -reset @@ -120,7 +120,7 @@ clean select -assert-count 1 t:FDCE select -assert-count 1 t:LUT4 select -assert-count 3 t:LUT2 -select -assert-none t:FDCE t:LUT4 t:LUT2 t:IBUF t:OBUF %% t:* %D +select -assert-none t:FDCE t:LUT4 t:LUT2 %% t:* %D design -reset @@ -154,7 +154,7 @@ clean select -assert-count 1 t:FDSE select -assert-count 1 t:LUT5 select -assert-count 2 t:LUT2 -select -assert-none t:FDSE t:LUT5 t:LUT2 t:IBUF t:OBUF %% t:* %D +select -assert-none t:FDSE t:LUT5 t:LUT2 %% t:* %D design -load t0 @@ -164,7 +164,7 @@ clean select -assert-count 1 t:FDSE select -assert-count 2 t:LUT2 -select -assert-none t:FDSE t:LUT2 t:IBUF t:OBUF %% t:* %D +select -assert-none t:FDSE t:LUT2 %% t:* %D design -reset @@ -200,7 +200,7 @@ clean select -assert-count 1 t:FDRSE select -assert-count 1 t:LUT6 select -assert-count 4 t:LUT2 -select -assert-none t:FDRSE t:LUT6 t:LUT2 t:IBUF t:OBUF %% t:* %D +select -assert-none t:FDRSE t:LUT6 t:LUT2 %% t:* %D design -load t0 @@ -211,6 +211,6 @@ clean select -assert-count 1 t:FDRSE select -assert-count 1 t:LUT4 select -assert-count 4 t:LUT2 -select -assert-none t:FDRSE t:LUT4 t:LUT2 t:IBUF t:OBUF %% t:* %D +select -assert-none t:FDRSE t:LUT4 t:LUT2 %% t:* %D design -reset -- cgit v1.2.3 From a82c701668d8197c01e54cb68bc45f2278f3172f Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 28 Dec 2019 16:22:24 +0100 Subject: Make test without iopads --- tests/arch/xilinx/add_sub.ys | 2 +- tests/arch/xilinx/adffs.ys | 8 ++++---- tests/arch/xilinx/attributes_test.ys | 12 ++++++------ tests/arch/xilinx/blockram.ys | 24 ++++++++++++------------ tests/arch/xilinx/bug1460.ys | 2 +- tests/arch/xilinx/counter.ys | 2 +- tests/arch/xilinx/dffs.ys | 4 ++-- tests/arch/xilinx/dsp_fastfir.ys | 2 +- tests/arch/xilinx/fsm.ys | 2 +- tests/arch/xilinx/latches.ys | 6 +++--- tests/arch/xilinx/logic.ys | 2 +- tests/arch/xilinx/lutram.ys | 14 +++++++------- tests/arch/xilinx/macc.ys | 8 ++++---- tests/arch/xilinx/mul.ys | 2 +- tests/arch/xilinx/mul_unsigned.ys | 2 +- tests/arch/xilinx/mux.ys | 8 ++++---- tests/arch/xilinx/shifter.ys | 2 +- 17 files changed, 51 insertions(+), 51 deletions(-) diff --git a/tests/arch/xilinx/add_sub.ys b/tests/arch/xilinx/add_sub.ys index 9dbddce47..313948cc5 100644 --- a/tests/arch/xilinx/add_sub.ys +++ b/tests/arch/xilinx/add_sub.ys @@ -1,7 +1,7 @@ read_verilog ../common/add_sub.v hierarchy -top top proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 14 t:LUT2 diff --git a/tests/arch/xilinx/adffs.ys b/tests/arch/xilinx/adffs.ys index c0ff6a2e2..3328f9edc 100644 --- a/tests/arch/xilinx/adffs.ys +++ b/tests/arch/xilinx/adffs.ys @@ -3,7 +3,7 @@ design -save read hierarchy -top adff proc -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd adff # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG @@ -15,7 +15,7 @@ select -assert-none t:BUFG t:FDCE %% t:* %D design -load read hierarchy -top adffn proc -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd adffn # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG @@ -28,7 +28,7 @@ select -assert-none t:BUFG t:FDCE t:INV %% t:* %D design -load read hierarchy -top dffs proc -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd dffs # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG @@ -40,7 +40,7 @@ select -assert-none t:BUFG t:FDSE %% t:* %D design -load read hierarchy -top ndffnr proc -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd ndffnr # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG diff --git a/tests/arch/xilinx/attributes_test.ys b/tests/arch/xilinx/attributes_test.ys index 4c881b280..7bdd94a63 100644 --- a/tests/arch/xilinx/attributes_test.ys +++ b/tests/arch/xilinx/attributes_test.ys @@ -1,7 +1,7 @@ # Check that blockram memory without parameters is not modified read_verilog ../common/memory_attributes/attributes_test.v hierarchy -top block_ram -synth_xilinx -top block_ram +synth_xilinx -top block_ram -noiopad cd block_ram # Constrain all select calls below inside the top module select -assert-count 1 t:RAMB18E1 @@ -9,7 +9,7 @@ select -assert-count 1 t:RAMB18E1 design -reset read_verilog ../common/memory_attributes/attributes_test.v hierarchy -top distributed_ram -synth_xilinx -top distributed_ram +synth_xilinx -top distributed_ram -noiopad cd distributed_ram # Constrain all select calls below inside the top module select -assert-count 8 t:RAM32X1D @@ -18,7 +18,7 @@ design -reset read_verilog ../common/memory_attributes/attributes_test.v prep setattr -mod -set ram_style "distributed" block_ram -synth_xilinx -top block_ram +synth_xilinx -top block_ram -noiopad cd block_ram # Constrain all select calls below inside the top module select -assert-count 32 t:RAM128X1D @@ -27,7 +27,7 @@ design -reset read_verilog ../common/memory_attributes/attributes_test.v prep setattr -mod -set logic_block 1 block_ram -synth_xilinx -top block_ram +synth_xilinx -top block_ram -noiopad cd block_ram # Constrain all select calls below inside the top module select -assert-count 0 t:RAMB18E1 select -assert-count 32 t:RAM128X1D @@ -35,13 +35,13 @@ select -assert-count 32 t:RAM128X1D # Set ram_style block to a distributed memory; will be implemented as blockram design -reset read_verilog ../common/memory_attributes/attributes_test.v -synth_xilinx -top distributed_ram_manual +synth_xilinx -top distributed_ram_manual -noiopad cd distributed_ram_manual # Constrain all select calls below inside the top module select -assert-count 1 t:RAMB18E1 # Set synthesis, ram_block block to a distributed memory; will be implemented as blockram design -reset read_verilog ../common/memory_attributes/attributes_test.v -synth_xilinx -top distributed_ram_manual_syn +synth_xilinx -top distributed_ram_manual_syn -noiopad cd distributed_ram_manual_syn # Constrain all select calls below inside the top module select -assert-count 1 t:RAMB18E1 diff --git a/tests/arch/xilinx/blockram.ys b/tests/arch/xilinx/blockram.ys index bb908cbbf..ed743cf44 100644 --- a/tests/arch/xilinx/blockram.ys +++ b/tests/arch/xilinx/blockram.ys @@ -3,28 +3,28 @@ # Memory bits <= 18K; Data width <= 36; Address width <= 14: -> RAMB18E1 read_verilog ../common/blockram.v chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 1 sync_ram_sdp -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 1 t:RAMB18E1 design -reset read_verilog ../common/blockram.v chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 18 sync_ram_sdp -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 1 t:RAMB18E1 design -reset read_verilog ../common/blockram.v chparam -set ADDRESS_WIDTH 14 -set DATA_WIDTH 1 sync_ram_sdp -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 1 t:RAMB18E1 design -reset read_verilog ../common/blockram.v chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_ram_sdp -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 1 t:RAMB18E1 @@ -32,7 +32,7 @@ select -assert-count 1 t:RAMB18E1 design -reset read_verilog ../common/blockram.v chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 2 sync_ram_sdp -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 0 t:RAMB18E1 select -assert-count 4 t:RAM128X1D @@ -41,7 +41,7 @@ select -assert-count 4 t:RAM128X1D design -reset read_verilog ../common/blockram.v chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 36 sync_ram_sdp -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 1 t:RAMB36E1 @@ -52,7 +52,7 @@ design -reset read_verilog ../common/blockram.v hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 10 -chparam DATA_WIDTH 1 setattr -set ram_style "block" m:memory -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 1 t:RAMB18E1 @@ -60,7 +60,7 @@ design -reset read_verilog ../common/blockram.v hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 10 -chparam DATA_WIDTH 1 setattr -set ram_block 1 m:memory -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 1 t:RAMB18E1 @@ -68,7 +68,7 @@ design -reset read_verilog ../common/blockram.v hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 10 -chparam DATA_WIDTH 1 setattr -set ram_style "dont_infer_a_ram_pretty_please" m:memory -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 0 t:RAMB18E1 @@ -76,7 +76,7 @@ design -reset read_verilog ../common/blockram.v hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 10 -chparam DATA_WIDTH 1 setattr -set logic_block 1 m:memory -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 0 t:RAMB18E1 @@ -84,7 +84,7 @@ design -reset read_verilog ../common/blockram.v hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 8 -chparam DATA_WIDTH 1 setattr -set ram_style "block" m:memory -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 1 t:RAMB18E1 @@ -92,6 +92,6 @@ design -reset read_verilog ../common/blockram.v hierarchy -top sync_ram_sdp -chparam ADDRESS_WIDTH 8 -chparam DATA_WIDTH 1 setattr -set ram_block 1 m:memory -synth_xilinx -top sync_ram_sdp +synth_xilinx -top sync_ram_sdp -noiopad cd sync_ram_sdp select -assert-count 1 t:RAMB18E1 diff --git a/tests/arch/xilinx/bug1460.ys b/tests/arch/xilinx/bug1460.ys index 2018071cc..09935ccd8 100644 --- a/tests/arch/xilinx/bug1460.ys +++ b/tests/arch/xilinx/bug1460.ys @@ -28,7 +28,7 @@ module register_file( endmodule EOT -synth_xilinx +synth_xilinx -noiopad cd register_file select -assert-count 32 t:RAM32M select -assert-none t:* t:BUFG %d t:RAM32M %d diff --git a/tests/arch/xilinx/counter.ys b/tests/arch/xilinx/counter.ys index 604acdbfc..11c29922e 100644 --- a/tests/arch/xilinx/counter.ys +++ b/tests/arch/xilinx/counter.ys @@ -2,7 +2,7 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/xilinx/dffs.ys b/tests/arch/xilinx/dffs.ys index 0bba4858f..dc764b033 100644 --- a/tests/arch/xilinx/dffs.ys +++ b/tests/arch/xilinx/dffs.ys @@ -3,7 +3,7 @@ design -save read hierarchy -top dff proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd dff # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG @@ -15,7 +15,7 @@ select -assert-none t:BUFG t:FDRE %% t:* %D design -load read hierarchy -top dffe proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd dffe # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG diff --git a/tests/arch/xilinx/dsp_fastfir.ys b/tests/arch/xilinx/dsp_fastfir.ys index 0067a822b..57fe49bde 100644 --- a/tests/arch/xilinx/dsp_fastfir.ys +++ b/tests/arch/xilinx/dsp_fastfir.ys @@ -63,7 +63,7 @@ module fastfir_dynamictaps(i_clk, i_reset, i_tap_wr, i_tap, i_ce, i_sample, o_re endmodule EOT -synth_xilinx +synth_xilinx -noiopad cd fastfir_dynamictaps select -assert-count 2 t:DSP48E1 select -assert-none t:* t:DSP48E1 %d t:BUFG %d diff --git a/tests/arch/xilinx/fsm.ys b/tests/arch/xilinx/fsm.ys index f03400fe7..3235d5af3 100644 --- a/tests/arch/xilinx/fsm.ys +++ b/tests/arch/xilinx/fsm.ys @@ -3,7 +3,7 @@ hierarchy -top fsm proc flatten -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad miter -equiv -make_assert -flatten gold gate miter sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter diff --git a/tests/arch/xilinx/latches.ys b/tests/arch/xilinx/latches.ys index c87a8e38b..e226c2ec8 100644 --- a/tests/arch/xilinx/latches.ys +++ b/tests/arch/xilinx/latches.ys @@ -3,7 +3,7 @@ design -save read hierarchy -top latchp proc -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd latchp # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE @@ -14,7 +14,7 @@ select -assert-none t:LDCE %% t:* %D design -load read hierarchy -top latchn proc -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd latchn # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE @@ -26,7 +26,7 @@ select -assert-none t:LDCE t:INV %% t:* %D design -load read hierarchy -top latchsr proc -equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd latchsr # Constrain all select calls below inside the top module select -assert-count 1 t:LDCE diff --git a/tests/arch/xilinx/logic.ys b/tests/arch/xilinx/logic.ys index d5b5c1a37..61a9314cc 100644 --- a/tests/arch/xilinx/logic.ys +++ b/tests/arch/xilinx/logic.ys @@ -1,7 +1,7 @@ read_verilog ../common/logic.v hierarchy -top top proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/xilinx/lutram.ys b/tests/arch/xilinx/lutram.ys index 6c9d1eae1..3f127a77e 100644 --- a/tests/arch/xilinx/lutram.ys +++ b/tests/arch/xilinx/lutram.ys @@ -2,7 +2,7 @@ #hierarchy -top lutram_1w1r -chparam A_WIDTH 4 #proc #memory -nomap -#equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +#equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad #memory #opt -full # @@ -22,7 +22,7 @@ read_verilog ../common/lutram.v hierarchy -top lutram_1w1r -chparam A_WIDTH 5 proc memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad memory opt -full @@ -42,7 +42,7 @@ read_verilog ../common/lutram.v hierarchy -top lutram_1w1r proc memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad memory opt -full @@ -62,7 +62,7 @@ read_verilog ../common/lutram.v hierarchy -top lutram_1w3r proc memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad memory opt -full @@ -82,7 +82,7 @@ read_verilog ../common/lutram.v hierarchy -top lutram_1w3r -chparam A_WIDTH 6 proc memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad memory opt -full @@ -102,7 +102,7 @@ read_verilog ../common/lutram.v hierarchy -top lutram_1w1r -chparam A_WIDTH 5 -chparam D_WIDTH 6 proc memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad memory opt -full @@ -122,7 +122,7 @@ read_verilog ../common/lutram.v hierarchy -top lutram_1w1r -chparam A_WIDTH 6 -chparam D_WIDTH 6 proc memory -nomap -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad memory opt -full diff --git a/tests/arch/xilinx/macc.ys b/tests/arch/xilinx/macc.ys index 11e959976..bf2b36320 100644 --- a/tests/arch/xilinx/macc.ys +++ b/tests/arch/xilinx/macc.ys @@ -3,8 +3,8 @@ design -save read hierarchy -top macc proc -#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx ### TODO -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad ### TODO +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -seq 10 -show-inputs -show-outputs miter design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) @@ -17,8 +17,8 @@ select -assert-none t:BUFG t:FDRE t:DSP48E1 %% t:* %D design -load read hierarchy -top macc2 proc -#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx ### TODO -equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad ### TODO +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx -noiopad miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -seq 10 -show-inputs -show-outputs miter design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) diff --git a/tests/arch/xilinx/mul.ys b/tests/arch/xilinx/mul.ys index d76814966..b04833a43 100644 --- a/tests/arch/xilinx/mul.ys +++ b/tests/arch/xilinx/mul.ys @@ -1,7 +1,7 @@ read_verilog ../common/mul.v hierarchy -top top proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/xilinx/mul_unsigned.ys b/tests/arch/xilinx/mul_unsigned.ys index 62495b90c..0a7644b65 100644 --- a/tests/arch/xilinx/mul_unsigned.ys +++ b/tests/arch/xilinx/mul_unsigned.ys @@ -2,7 +2,7 @@ read_verilog mul_unsigned.v hierarchy -top mul_unsigned proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mul_unsigned # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG diff --git a/tests/arch/xilinx/mux.ys b/tests/arch/xilinx/mux.ys index 388272449..99817738d 100644 --- a/tests/arch/xilinx/mux.ys +++ b/tests/arch/xilinx/mux.ys @@ -3,7 +3,7 @@ design -save read hierarchy -top mux2 proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux2 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT3 @@ -14,7 +14,7 @@ select -assert-none t:LUT3 %% t:* %D design -load read hierarchy -top mux4 proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux4 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT6 @@ -25,7 +25,7 @@ select -assert-none t:LUT6 %% t:* %D design -load read hierarchy -top mux8 proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux8 # Constrain all select calls below inside the top module select -assert-count 1 t:LUT3 @@ -37,7 +37,7 @@ select -assert-none t:LUT3 t:LUT6 %% t:* %D design -load read hierarchy -top mux16 proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module select -assert-min 5 t:LUT6 diff --git a/tests/arch/xilinx/shifter.ys b/tests/arch/xilinx/shifter.ys index 455437f18..3652319a0 100644 --- a/tests/arch/xilinx/shifter.ys +++ b/tests/arch/xilinx/shifter.ys @@ -2,7 +2,7 @@ read_verilog ../common/shifter.v hierarchy -top top proc flatten -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module -- cgit v1.2.3 From f9749c202c93e1c9c6edb522999eacc323039b95 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 28 Dec 2019 16:43:19 +0100 Subject: Fix new tests --- tests/arch/xilinx/dsp_cascade.ys | 8 ++++---- tests/arch/xilinx/mul.ys | 2 +- tests/arch/xilinx/mul_unsigned.ys | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/arch/xilinx/dsp_cascade.ys b/tests/arch/xilinx/dsp_cascade.ys index f9185551b..ca6b619b9 100644 --- a/tests/arch/xilinx/dsp_cascade.ys +++ b/tests/arch/xilinx/dsp_cascade.ys @@ -19,7 +19,7 @@ EOT proc design -save read -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad design -load postopt cd cascade select -assert-count 3 t:DSP48E1 @@ -35,7 +35,7 @@ select -assert-none t:DSP48E1 t:BUFG %% t:* %D select -assert-count 2 t:DSP48E1 %co:+[PCOUT] t:DSP48E1 %d %co:+[PCIN] w:* %d t:DSP48E1 %i design -load read -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s -noiopad design -load postopt cd cascade select -assert-count 3 t:DSP48A1 @@ -65,7 +65,7 @@ EOT proc design -save read -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad design -load postopt cd cascade select -assert-count 2 t:DSP48E1 @@ -75,7 +75,7 @@ select -assert-none t:DSP48E1 t:BUFG %% t:* %D select -assert-count 1 t:DSP48E1 %co:+[PCOUT] t:DSP48E1 %d %co:+[PCIN] w:* %d t:DSP48E1 %i design -load read -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s -noiopad design -load postopt cd cascade select -assert-count 2 t:DSP48A1 diff --git a/tests/arch/xilinx/mul.ys b/tests/arch/xilinx/mul.ys index 049a3da7e..490846ff1 100644 --- a/tests/arch/xilinx/mul.ys +++ b/tests/arch/xilinx/mul.ys @@ -13,7 +13,7 @@ design -reset read_verilog ../common/mul.v hierarchy -top top proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/xilinx/mul_unsigned.ys b/tests/arch/xilinx/mul_unsigned.ys index 830dd639c..980263cbd 100644 --- a/tests/arch/xilinx/mul_unsigned.ys +++ b/tests/arch/xilinx/mul_unsigned.ys @@ -16,7 +16,7 @@ read_verilog mul_unsigned.v hierarchy -top mul_unsigned proc -equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s # equivalency check +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -family xc6s -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mul_unsigned # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG -- cgit v1.2.3 From 52a27700e2b985d56821ffefb3c61f88cfb96e1a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 12:26:39 -0800 Subject: Grammar --- passes/techmap/abc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index b29480e26..279b32223 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1767,7 +1767,7 @@ struct AbcPass : public Pass { extra_args(args, argidx, design); if (!lut_costs.empty() && !liberty_file.empty()) - log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n"); + log_cmd_error("Got -lut and -liberty! These two options are exclusive.\n"); if (!constr_file.empty() && liberty_file.empty()) log_cmd_error("Got -constr but no -liberty!\n"); -- cgit v1.2.3 From 566d9fb77f8688022ae7247fa9466a4327b2adb7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 11:57:18 -0800 Subject: Revert "ABC to call retime all the time" This reverts commit 9aa94370a54c016421740d2ce32ef0aa338d0dbd. --- passes/techmap/abc.cc | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index b29480e26..1852cacc0 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -29,17 +29,17 @@ // Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558-562, doi:10.1145/368996.369025 // http://en.wikipedia.org/wiki/Topological_sorting -#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put" -#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p" -#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; if; mfs2" -#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; cover {I} {P}" -#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put" - -#define ABC_FAST_COMMAND_LIB "strash; dretime; retime {D}; map {D}" -#define ABC_FAST_COMMAND_CTR "strash; dretime; retime {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" -#define ABC_FAST_COMMAND_LUT "strash; dretime; retime {D}; if" -#define ABC_FAST_COMMAND_SOP "strash; dretime; retime {D}; cover -I {I} -P {P}" -#define ABC_FAST_COMMAND_DFL "strash; dretime; retime {D}; map" +#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put" +#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p" +#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2" +#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}" +#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put" + +#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}" +#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" +#define ABC_FAST_COMMAND_LUT "strash; dretime; if" +#define ABC_FAST_COMMAND_SOP "strash; dretime; cover -I {I} -P {P}" +#define ABC_FAST_COMMAND_DFL "strash; dretime; map" #include "kernel/register.h" #include "kernel/sigtools.h" @@ -747,6 +747,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin else abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; + if (script_file.empty() && !delay_target.empty()) + for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1)) + abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8); + for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3); -- cgit v1.2.3 From aa6d06c1b5b0083096ad547b0ad2600fcdc854f4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 12:09:53 -0800 Subject: Revert "Revert "synth_* with -retime option now calls abc with -D 1 as well"" This reverts commit 6008bb7002f874e5c748eaa2050e7b6c17b32745. --- techlibs/achronix/synth_achronix.cc | 4 ++-- techlibs/anlogic/synth_anlogic.cc | 2 +- techlibs/coolrunner2/synth_coolrunner2.cc | 2 +- techlibs/easic/synth_easic.cc | 2 +- techlibs/ecp5/synth_ecp5.cc | 2 +- techlibs/gowin/synth_gowin.cc | 2 +- techlibs/greenpak4/synth_greenpak4.cc | 2 +- techlibs/ice40/synth_ice40.cc | 2 +- techlibs/intel/synth_intel.cc | 2 +- techlibs/sf2/synth_sf2.cc | 2 +- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/techlibs/achronix/synth_achronix.cc b/techlibs/achronix/synth_achronix.cc index 626860d9c..3dbf20911 100755 --- a/techlibs/achronix/synth_achronix.cc +++ b/techlibs/achronix/synth_achronix.cc @@ -152,12 +152,12 @@ struct SynthAchronixPass : public ScriptPass { run("clean -purge"); run("setundef -undriven -zero"); if (retime || help_mode) - run("abc -markgroups -dff", "(only if -retime)"); + run("abc -markgroups -dff -D 1", "(only if -retime)"); } if (check_label("map_luts")) { - run("abc -lut 4" + string(retime ? " -dff" : "")); + run("abc -lut 4" + string(retime ? " -dff -D 1" : "")); run("clean"); } diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc index b87fc8566..310c9c76c 100644 --- a/techlibs/anlogic/synth_anlogic.cc +++ b/techlibs/anlogic/synth_anlogic.cc @@ -164,7 +164,7 @@ struct SynthAnlogicPass : public ScriptPass run("opt -undriven -fine"); run("techmap -map +/techmap.v -map +/anlogic/arith_map.v"); if (retime || help_mode) - run("abc -dff", "(only if -retime)"); + run("abc -dff -D 1", "(only if -retime)"); } if (check_label("map_ffs")) diff --git a/techlibs/coolrunner2/synth_coolrunner2.cc b/techlibs/coolrunner2/synth_coolrunner2.cc index 014c68622..d73241fa8 100644 --- a/techlibs/coolrunner2/synth_coolrunner2.cc +++ b/techlibs/coolrunner2/synth_coolrunner2.cc @@ -161,7 +161,7 @@ struct SynthCoolrunner2Pass : public ScriptPass if (check_label("map_pla")) { - run("abc -sop -I 40 -P 56"); + run("abc -sop -I 40 -P 56" + string(retime ? " -dff -D 1" : "")); run("clean"); } diff --git a/techlibs/easic/synth_easic.cc b/techlibs/easic/synth_easic.cc index dd9e3dab7..7bacc7890 100644 --- a/techlibs/easic/synth_easic.cc +++ b/techlibs/easic/synth_easic.cc @@ -158,7 +158,7 @@ struct SynthEasicPass : public ScriptPass run("techmap"); run("opt -fast"); if (retime || help_mode) { - run("abc -dff", " (only if -retime)"); + run("abc -dff -D 1", " (only if -retime)"); run("opt_clean", "(only if -retime)"); } } diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index a0ea6d1f9..24e300fa8 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -290,7 +290,7 @@ struct SynthEcp5Pass : public ScriptPass else run("techmap -map +/techmap.v -map +/ecp5/arith_map.v"); if (retime || help_mode) - run("abc -dff", "(only if -retime)"); + run("abc -dff -D 1", "(only if -retime)"); } if (check_label("map_ffs")) diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc index 6cf058f29..5acc096a3 100644 --- a/techlibs/gowin/synth_gowin.cc +++ b/techlibs/gowin/synth_gowin.cc @@ -209,7 +209,7 @@ struct SynthGowinPass : public ScriptPass run("techmap -map +/techmap.v -map +/gowin/arith_map.v"); run("techmap -map +/techmap.v"); if (retime || help_mode) - run("abc -dff", "(only if -retime)"); + run("abc -dff -D 1", "(only if -retime)"); run("splitnets"); } diff --git a/techlibs/greenpak4/synth_greenpak4.cc b/techlibs/greenpak4/synth_greenpak4.cc index eeb001b46..3222be2e3 100644 --- a/techlibs/greenpak4/synth_greenpak4.cc +++ b/techlibs/greenpak4/synth_greenpak4.cc @@ -165,7 +165,7 @@ struct SynthGreenPAK4Pass : public ScriptPass run("dfflibmap -prepare -liberty +/greenpak4/gp_dff.lib"); run("opt -fast"); if (retime || help_mode) - run("abc -dff", "(only if -retime)"); + run("abc -dff -D 1", "(only if -retime)"); } if (check_label("map_luts")) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index ed7a16c08..fe1228165 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -316,7 +316,7 @@ struct SynthIce40Pass : public ScriptPass run("techmap -map +/techmap.v -map +/ice40/arith_map.v"); } if (retime || help_mode) - run(abc + " -dff", "(only if -retime)"); + run(abc + " -dff -D 1", "(only if -retime)"); run("ice40_opt"); } diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index c8c690e45..f033f3acc 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -210,7 +210,7 @@ struct SynthIntelPass : public ScriptPass { run("clean -purge"); run("setundef -undriven -zero"); if (retime || help_mode) - run("abc -markgroups -dff", "(only if -retime)"); + run("abc -markgroups -dff -D 1", "(only if -retime)"); } if (check_label("map_luts")) { diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc index 0924df7a6..3c5a58b4c 100644 --- a/techlibs/sf2/synth_sf2.cc +++ b/techlibs/sf2/synth_sf2.cc @@ -181,7 +181,7 @@ struct SynthSf2Pass : public ScriptPass run("opt -undriven -fine"); run("techmap -map +/techmap.v -map +/sf2/arith_map.v"); if (retime || help_mode) - run("abc -dff", "(only if -retime)"); + run("abc -dff -D 1", "(only if -retime)"); } if (check_label("map_ffs")) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a19046911..afe4d483b 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -555,9 +555,9 @@ struct SynthXilinxPass : public ScriptPass } else { if (nowidelut) - run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : "")); + run("abc -luts 2:2,3,6:5" + string(retime ? " -dff -D 1" : "")); else - run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff -D 1" : "")); } run("clean"); -- cgit v1.2.3 From c9e3b26412d6e5c5405f131b7526dec632fbb315 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 12:05:52 -0800 Subject: Disable synth_gowin -abc9 as it offers no advantages yet --- techlibs/gowin/synth_gowin.cc | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc index 5acc096a3..8431473f0 100644 --- a/techlibs/gowin/synth_gowin.cc +++ b/techlibs/gowin/synth_gowin.cc @@ -62,16 +62,16 @@ struct SynthGowinPass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log(" -nowidelut\n"); log(" do not use muxes to implement LUTs larger than LUT4s\n"); log("\n"); log(" -noiopads\n"); log(" do not emit IOB at top level ports\n"); - log("\n"); - log(" -abc9\n"); - log(" use new ABC9 flow (EXPERIMENTAL)\n"); + //log("\n"); + //log(" -abc9\n"); + //log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -144,10 +144,10 @@ struct SynthGowinPass : public ScriptPass nowidelut = true; continue; } - if (args[argidx] == "-abc9") { - abc9 = true; - continue; - } + //if (args[argidx] == "-abc9") { + // abc9 = true; + // continue; + //} if (args[argidx] == "-noiopads") { noiopads = true; continue; @@ -227,13 +227,13 @@ struct SynthGowinPass : public ScriptPass if (check_label("map_luts")) { - if (nowidelut && abc9) { + /*if (nowidelut && abc9) { run("abc9 -lut 4"); - } else if (nowidelut && !abc9) { + } else*/ if (nowidelut && !abc9) { run("abc -lut 4"); - } else if (!nowidelut && abc9) { + } else /*if (!nowidelut && abc9) { run("abc9 -lut 4:8"); - } else if (!nowidelut && !abc9) { + } else*/ if (!nowidelut && !abc9) { run("abc -lut 4:8"); } run("clean"); -- cgit v1.2.3 From 79448f9be035c88589b4e9c0de6b2bdc5acbd4df Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 12:11:45 -0800 Subject: Update doc that "-retime" calls abc with "-dff -D 1" --- techlibs/achronix/synth_achronix.cc | 2 +- techlibs/anlogic/synth_anlogic.cc | 2 +- techlibs/coolrunner2/synth_coolrunner2.cc | 2 +- techlibs/easic/synth_easic.cc | 2 +- techlibs/ecp5/synth_ecp5.cc | 2 +- techlibs/efinix/synth_efinix.cc | 4 ++-- techlibs/greenpak4/synth_greenpak4.cc | 2 +- techlibs/ice40/synth_ice40.cc | 2 +- techlibs/intel/synth_intel.cc | 2 +- techlibs/sf2/synth_sf2.cc | 2 +- techlibs/xilinx/synth_xilinx.cc | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/techlibs/achronix/synth_achronix.cc b/techlibs/achronix/synth_achronix.cc index 3dbf20911..1dc6bdb2f 100755 --- a/techlibs/achronix/synth_achronix.cc +++ b/techlibs/achronix/synth_achronix.cc @@ -52,7 +52,7 @@ struct SynthAchronixPass : public ScriptPass { log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc index 310c9c76c..57b8a2b26 100644 --- a/techlibs/anlogic/synth_anlogic.cc +++ b/techlibs/anlogic/synth_anlogic.cc @@ -58,7 +58,7 @@ struct SynthAnlogicPass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); diff --git a/techlibs/coolrunner2/synth_coolrunner2.cc b/techlibs/coolrunner2/synth_coolrunner2.cc index d73241fa8..388e2b792 100644 --- a/techlibs/coolrunner2/synth_coolrunner2.cc +++ b/techlibs/coolrunner2/synth_coolrunner2.cc @@ -55,7 +55,7 @@ struct SynthCoolrunner2Pass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); diff --git a/techlibs/easic/synth_easic.cc b/techlibs/easic/synth_easic.cc index 7bacc7890..b4a3a1ac9 100644 --- a/techlibs/easic/synth_easic.cc +++ b/techlibs/easic/synth_easic.cc @@ -56,7 +56,7 @@ struct SynthEasicPass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 24e300fa8..1ecb9cac3 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -62,7 +62,7 @@ struct SynthEcp5Pass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log(" -noccu2\n"); log(" do not use CCU2 cells in output netlist\n"); diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc index 26a8d4eda..6fe0182ac 100644 --- a/techlibs/efinix/synth_efinix.cc +++ b/techlibs/efinix/synth_efinix.cc @@ -58,7 +58,7 @@ struct SynthEfinixPass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -164,7 +164,7 @@ struct SynthEfinixPass : public ScriptPass run("opt -undriven -fine"); run("techmap -map +/techmap.v -map +/efinix/arith_map.v"); if (retime || help_mode) - run("abc -dff", "(only if -retime)"); + run("abc -dff -D 1", "(only if -retime)"); } if (check_label("map_ffs")) diff --git a/techlibs/greenpak4/synth_greenpak4.cc b/techlibs/greenpak4/synth_greenpak4.cc index 3222be2e3..e1fbe6b69 100644 --- a/techlibs/greenpak4/synth_greenpak4.cc +++ b/techlibs/greenpak4/synth_greenpak4.cc @@ -59,7 +59,7 @@ struct SynthGreenPAK4Pass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index fe1228165..463c2063a 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -65,7 +65,7 @@ struct SynthIce40Pass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log(" -nocarry\n"); log(" do not use SB_CARRY cells in output netlist\n"); diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index f033f3acc..a3d346407 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -71,7 +71,7 @@ struct SynthIntelPass : public ScriptPass { log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc index 3c5a58b4c..543dfdb9e 100644 --- a/techlibs/sf2/synth_sf2.cc +++ b/techlibs/sf2/synth_sf2.cc @@ -67,7 +67,7 @@ struct SynthSf2Pass : public ScriptPass log(" insert direct PAD->global_net buffers\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index afe4d483b..215a48f95 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -110,7 +110,7 @@ struct SynthXilinxPass : public ScriptPass log(" flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log(" -abc9\n"); log(" use new ABC9 flow (EXPERIMENTAL)\n"); -- 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 ++- passes/techmap/abc9.cc | 68 ++++++++++----------------------- techlibs/xilinx/abc9_map.v | 84 +++++++++++++++++++++++++++++++++++++++++ techlibs/xilinx/synth_xilinx.cc | 16 +++++++- 4 files changed, 120 insertions(+), 53 deletions(-) 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 */); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 857f1a0a6..19a1d2ccb 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -249,9 +249,8 @@ struct abc9_output_filter }; void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file, - bool cleanup, vector lut_costs, bool /*dff_mode*/, std::string /*clk_str*/, - bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, - bool show_tempdir, std::string box_file, std::string lut_file, + bool cleanup, vector lut_costs, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, + const std::vector &/*cells*/, bool show_tempdir, std::string box_file, std::string lut_file, std::string wire_delay, const dict &box_lookup, bool nomfs ) { @@ -294,20 +293,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip } else abc9_script += stringf("source %s", script_file.c_str()); } else if (!lut_costs.empty() || !lut_file.empty()) { - //bool all_luts_cost_same = true; - //for (int this_cost : lut_costs) - // if (this_cost != lut_costs.front()) - // all_luts_cost_same = false; abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; - //if (all_luts_cost_same && !fast_mode) - // abc9_script += "; lutpack {S}"; } else log_abort(); - //if (script_file.empty() && !delay_target.empty()) - // for (size_t pos = abc9_script.find("dretime;"); pos != std::string::npos; pos = abc9_script.find("dretime;", pos+1)) - // abc9_script = abc9_script.substr(0, pos) + "dretime; retime -o {D};" + abc9_script.substr(pos+8); - for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos)) abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3); @@ -439,8 +428,16 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip RTLIL::Module* box_module = design->module(cell->type); jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; } - if (jt->second) - boxes.emplace_back(cell); + if (jt->second) { + auto kt = cell->attributes.find("\\abc9_keep"); + bool abc9_keep = false; + if (kt != cell->attributes.end()) { + abc9_keep = kt->second.as_bool(); + cell->attributes.erase(kt); + } + if (!abc9_keep) + boxes.emplace_back(cell); + } } dict> bit_drivers, bit_users; @@ -766,7 +763,7 @@ struct Abc9Pass : public Pass { log(" if no -script parameter is given, the following scripts are used:\n"); log("\n"); log(" for -lut/-luts (only one LUT size):\n"); - log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); + log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); log("\n"); log(" for -lut/-luts (different LUT sizes):\n"); log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); @@ -782,8 +779,6 @@ struct Abc9Pass : public Pass { log(" set delay target. the string {D} in the default scripts above is\n"); log(" replaced by this option when used, and an empty string otherwise\n"); log(" (indicating best possible delay).\n"); -// log(" This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); -// log(" default scripts above.\n"); log("\n"); // log(" -S \n"); // log(" maximum number of LUT inputs shared.\n"); @@ -805,19 +800,6 @@ struct Abc9Pass : public Pass { log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); log(" 2, 3, .. inputs.\n"); log("\n"); -// log(" -dff\n"); -// log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n"); -// log(" clock domains are automatically partitioned in clock domains and each\n"); -// log(" domain is passed through ABC independently.\n"); -// log("\n"); -// log(" -clk [!][,[!]]\n"); -// log(" use only the specified clock domain. this is like -dff, but only FF\n"); -// log(" cells that belong to the specified clock domain are used.\n"); -// log("\n"); -// log(" -keepff\n"); -// log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n"); -// log(" them, for example for equivalence checking.)\n"); -// log("\n"); log(" -nocleanup\n"); log(" when this option is used, the temporary files created by this pass\n"); log(" are not removed. this is useful for debugging.\n"); @@ -865,7 +847,7 @@ struct Abc9Pass : public Pass { #endif std::string script_file, clk_str, box_file, lut_file; std::string delay_target, lutin_shared = "-S 1", wire_delay; - bool fast_mode = false, /*dff_mode = false,*/ keepff = false, cleanup = true; + bool fast_mode = false, cleanup = true; bool show_tempdir = false; bool nomfs = false; vector lut_costs; @@ -956,19 +938,6 @@ struct Abc9Pass : public Pass { fast_mode = true; continue; } - //if (arg == "-dff") { - // dff_mode = true; - // continue; - //} - //if (arg == "-clk" && argidx+1 < args.size()) { - // clk_str = args[++argidx]; - // dff_mode = true; - // continue; - //} - //if (arg == "-keepff") { - // keepff = true; - // continue; - //} if (arg == "-nocleanup") { cleanup = false; continue; @@ -1083,7 +1052,7 @@ struct Abc9Pass : public Pass { typedef SigSpec clkdomain_t; dict clk_to_mergeability; - std::vector all_cells = module->selected_cells(); + const std::vector all_cells = module->selected_cells(); #if 0 pool unassigned_cells(all_cells.begin(), all_cells.end()); @@ -1116,7 +1085,8 @@ struct Abc9Pass : public Pass { for (auto cell : all_cells) { auto inst_module = design->module(cell->type); - if (!inst_module || !inst_module->attributes.count("\\abc9_flop")) + if (!inst_module || !inst_module->attributes.count("\\abc9_flop") + || cell->get_bool_attribute("\\abc9_keep")) continue; Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); @@ -1268,8 +1238,8 @@ struct Abc9Pass : public Pass { RTLIL::Selection& sel = design->selection_stack.back(); sel.selected_members[module->name] = std::move(it.second); #endif - abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, false, "$", - keepff, delay_target, lutin_shared, fast_mode, show_tempdir, + abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, + delay_target, lutin_shared, fast_mode, all_cells, show_tempdir, box_file, lut_file, wire_delay, box_lookup, nomfs); #if 0 assign_map.set(module); diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index d2d7d9114..1e17d4766 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -83,6 +83,7 @@ module FDRE (output Q, input C, CE, D, R); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; +`ifdef DFF_MODE wire QQ, $nextQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -113,9 +114,21 @@ module FDRE (output Q, input C, CE, D, R); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; +`else + (* abc9_keep *) + FDRE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_R_INVERTED(IS_R_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .R(R) + ); +`endif endmodule module FDRE_1 (output Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; +`ifdef DFF_MODE wire QQ, $nextQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -140,6 +153,14 @@ module FDRE_1 (output Q, input C, CE, D, R); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; +`else + (* abc9_keep *) + FDRE_1 #( + .INIT(INIT) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .R(R) + ); +`endif endmodule module FDCE (output Q, input C, CE, D, CLR); @@ -147,6 +168,7 @@ module FDCE (output Q, input C, CE, D, CLR); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; +`ifdef DFF_MODE wire QQ, $nextQ, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -190,9 +212,21 @@ module FDCE (output Q, input C, CE, D, CLR); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; +`else + (* abc9_keep *) + FDCE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_CLR_INVERTED(IS_CLR_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR) + ); +`endif endmodule module FDCE_1 (output Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; +`ifdef DFF_MODE wire QQ, $nextQ, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -228,6 +262,14 @@ module FDCE_1 (output Q, input C, CE, D, CLR); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; +`else + (* abc9_keep *) + FDCE_1 #( + .INIT(INIT) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR) + ); +`endif endmodule module FDPE (output Q, input C, CE, D, PRE); @@ -235,6 +277,7 @@ module FDPE (output Q, input C, CE, D, PRE); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; +`ifdef DFF_MODE wire QQ, $nextQ, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -276,9 +319,21 @@ module FDPE (output Q, input C, CE, D, PRE); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; +`else + (* abc9_keep *) + FDPE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_PRE_INVERTED(IS_PRE_INVERTED), + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE) + ); +`endif endmodule module FDPE_1 (output Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; +`ifdef DFF_MODE wire QQ, $nextQ, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -314,6 +369,14 @@ module FDPE_1 (output Q, input C, CE, D, PRE); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; +`else + (* abc9_keep *) + FDPE_1 #( + .INIT(INIT) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE) + ); +`endif endmodule module FDSE (output Q, input C, CE, D, S); @@ -321,6 +384,7 @@ module FDSE (output Q, input C, CE, D, S); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; +`ifdef DFF_MODE wire QQ, $nextQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -350,9 +414,21 @@ module FDSE (output Q, input C, CE, D, S); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; +`else + (* abc9_keep *) + FDSE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_S_INVERTED(IS_S_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .S(S) + ); +`endif endmodule module FDSE_1 (output Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; +`ifdef DFF_MODE wire QQ, $nextQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -376,6 +452,14 @@ module FDSE_1 (output Q, input C, CE, D, S); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; +`else + (* abc9_keep *) + FDSE_1 #( + .INIT(INIT) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .S(S) + ); +`endif endmodule module RAM32X1D ( diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ac6fedc58..e7069f286 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -109,6 +109,9 @@ struct SynthXilinxPass : public ScriptPass log(" -flatten\n"); log(" flatten design before synthesis\n"); log("\n"); + log(" -dff\n"); + log(" run 'abc9' with -dff option\n"); + log("\n"); log(" -retime\n"); log(" run 'abc' with -dff option\n"); log("\n"); @@ -122,7 +125,8 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, family; - bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram, abc9; + bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram; + bool abc9, dff_mode; bool flatten_before_abc; int widemux; @@ -148,6 +152,7 @@ struct SynthXilinxPass : public ScriptPass nodsp = false; uram = false; abc9 = false; + dff_mode = false; flatten_before_abc = false; widemux = 0; } @@ -256,6 +261,10 @@ struct SynthXilinxPass : public ScriptPass uram = true; continue; } + if (args[argidx] == "-dff") { + dff_mode = true; + continue; + } break; } extra_args(args, argidx, design); @@ -540,7 +549,10 @@ struct SynthXilinxPass : public ScriptPass if (family != "xc7") log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, " "will use timing for 'xc7' instead.\n", family.c_str()); - run("techmap -map +/xilinx/abc9_map.v -max_iter 1"); + std::string techmap_args = "-map +/xilinx/abc9_map.v -max_iter 1"; + if (dff_mode) + techmap_args += " -D DFF_MODE"; + run("techmap " + techmap_args); run("read_verilog -icells -lib +/xilinx/abc9_model.v"); std::string abc9_opts = " -box +/xilinx/abc9_xc7.box"; abc9_opts += stringf(" -W %d", XC7_WIRE_DELAY); -- cgit v1.2.3 From a038294a87b44a8eadfb62453f1fd76eec5a04ef Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 14:19:29 -0800 Subject: Tidy up abc9_map.v --- techlibs/xilinx/abc9_map.v | 206 ++++++++++++++++++++++----------------------- 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 1e17d4766..2cabe57d7 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -49,10 +49,10 @@ // || Comb box || // || || // || /\/\/\/\ || -// D -->>-----< > || +------+ -// R -->>-----< Comb. > || |$__ABC| -// CE -->>-----< logic >--->>-- $nextQ --| _FF_ |--+-->> Q -// $abc9_currQ +-->>-----< > || +------+ | +// D -->>-----< > || +// R -->>-----< Comb. > || +----------+ +// CE -->>-----< logic >--->>-- $Q --|$__ABC_FF_|--+-->> Q +// $abc9_currQ +-->>-----< > || +----------+ | // | || \/\/\/\/ || | // | || || | // | ++==================++ | @@ -84,7 +84,7 @@ module FDRE (output Q, input C, CE, D, R); parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; `ifdef DFF_MODE - wire QQ, $nextQ; + wire QQ, $Q; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDSE #( @@ -93,7 +93,7 @@ module FDRE (output Q, input C, CE, D, R); .IS_D_INVERTED(IS_D_INVERTED), .IS_S_INVERTED(IS_R_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($nextQ), .C(C), .CE(CE), .S(R) + .D(~D), .Q($Q), .C(C), .CE(CE), .S(R) ); end else begin @@ -104,11 +104,11 @@ module FDRE (output Q, input C, CE, D, R); .IS_D_INVERTED(IS_D_INVERTED), .IS_R_INVERTED(IS_R_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) + .D(D), .Q($Q), .C(C), .CE(CE), .R(R) ); end endgenerate - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); + $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; @@ -129,13 +129,13 @@ endmodule module FDRE_1 (output Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; `ifdef DFF_MODE - wire QQ, $nextQ; + wire QQ, $Q; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDSE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($nextQ), .C(C), .CE(CE), .S(R) + .D(~D), .Q($Q), .C(C), .CE(CE), .S(R) ); end else begin @@ -143,11 +143,11 @@ module FDRE_1 (output Q, input C, CE, D, R); FDRE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R) + .D(D), .Q($Q), .C(C), .CE(CE), .R(R) ); end endgenerate - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); + $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; @@ -169,7 +169,7 @@ module FDCE (output Q, input C, CE, D, CLR); parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; `ifdef DFF_MODE - wire QQ, $nextQ, $abc9_currQ; + wire QQ, $Q, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDPE #( @@ -178,7 +178,7 @@ module FDCE (output Q, input C, CE, D, CLR); .IS_D_INVERTED(IS_D_INVERTED), .IS_PRE_INVERTED(IS_CLR_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($nextQ), .C(C), .CE(CE), .PRE(CLR) + .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) // ^^^ Note that async // control is not directly // supported by abc9 but its @@ -186,7 +186,7 @@ module FDCE (output Q, input C, CE, D, CLR); // $__ABC9_ASYNC1 below ); // Since this is an async flop, async behaviour is dealt with here - \$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); + $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); end else begin assign Q = QQ; @@ -196,7 +196,7 @@ module FDCE (output Q, input C, CE, D, CLR); .IS_D_INVERTED(IS_D_INVERTED), .IS_CLR_INVERTED(IS_CLR_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) + .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) // ^^^ Note that async // control is not directly // supported by abc9 but its @@ -204,9 +204,9 @@ module FDCE (output Q, input C, CE, D, CLR); // $__ABC9_ASYNC0 below ); // Since this is an async flop, async behaviour is dealt with here - \$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); + $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); end endgenerate - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); + $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; @@ -227,36 +227,36 @@ endmodule module FDCE_1 (output Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; `ifdef DFF_MODE - wire QQ, $nextQ, $abc9_currQ; + wire QQ, $Q, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDPE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($nextQ), .C(C), .CE(CE), .PRE(CLR) + .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC1 below ); - \$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); + $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); end else begin assign Q = QQ; FDCE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR) + .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC0 below ); - \$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); + $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); end endgenerate - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); + $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; @@ -278,7 +278,7 @@ module FDPE (output Q, input C, CE, D, PRE); parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; `ifdef DFF_MODE - wire QQ, $nextQ, $abc9_currQ; + wire QQ, $Q, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDCE #( @@ -287,14 +287,14 @@ module FDPE (output Q, input C, CE, D, PRE); .IS_D_INVERTED(IS_D_INVERTED), .IS_CLR_INVERTED(IS_PRE_INVERTED), ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($nextQ), .C(C), .CE(CE), .CLR(PRE) + .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC0 below ); - \$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); + $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); end else begin assign Q = QQ; @@ -304,16 +304,16 @@ module FDPE (output Q, input C, CE, D, PRE); .IS_D_INVERTED(IS_D_INVERTED), .IS_PRE_INVERTED(IS_PRE_INVERTED), ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) + .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC1 below ); - \$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); + $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); end endgenerate - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); + $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; @@ -334,36 +334,36 @@ endmodule module FDPE_1 (output Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; `ifdef DFF_MODE - wire QQ, $nextQ, $abc9_currQ; + wire QQ, $Q, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDCE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($nextQ), .C(C), .CE(CE), .CLR(PRE) + .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC0 below ); - \$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); + $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); end else begin assign Q = QQ; FDPE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE) + .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) // ^^^ Note that async // control is not directly // supported by abc9 but its // behaviour is captured by // $__ABC9_ASYNC1 below ); - \$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); + $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); end endgenerate - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ)); + $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; @@ -385,7 +385,7 @@ module FDSE (output Q, input C, CE, D, S); parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; `ifdef DFF_MODE - wire QQ, $nextQ; + wire QQ, $Q; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDRE #( @@ -394,7 +394,7 @@ module FDSE (output Q, input C, CE, D, S); .IS_D_INVERTED(IS_D_INVERTED), .IS_R_INVERTED(IS_S_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($nextQ), .C(C), .CE(CE), .R(S) + .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) ); end else begin @@ -405,10 +405,10 @@ module FDSE (output Q, input C, CE, D, S); .IS_D_INVERTED(IS_D_INVERTED), .IS_S_INVERTED(IS_S_INVERTED) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) + .D(D), .Q($Q), .C(C), .CE(CE), .S(S) ); end endgenerate - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); + $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; @@ -429,13 +429,13 @@ endmodule module FDSE_1 (output Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; `ifdef DFF_MODE - wire QQ, $nextQ; + wire QQ, $Q; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDRE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($nextQ), .C(C), .CE(CE), .R(S) + .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) ); end else begin @@ -443,10 +443,10 @@ module FDSE_1 (output Q, input C, CE, D, S); FDSE_1 #( .INIT(1'b0) ) _TECHMAP_REPLACE_ ( - .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S) + .D(D), .Q($Q), .C(C), .CE(CE), .S(S) ); end endgenerate - \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ)); + $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); // Special signals wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; @@ -472,17 +472,17 @@ module RAM32X1D ( ); parameter INIT = 32'h0; parameter IS_WCLK_INVERTED = 1'b0; - wire \$DPO , \$SPO ; + wire $DPO, $SPO; RAM32X1D #( .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) ) _TECHMAP_REPLACE_ ( - .DPO(\$DPO ), .SPO(\$SPO ), + .DPO($DPO), .SPO($SPO), .D(D), .WCLK(WCLK), .WE(WE), .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4) ); - \$__ABC9_LUT6 spo (.A(\$SPO ), .S({1'b1, A4, A3, A2, A1, A0}), .Y(SPO)); - \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({1'b1, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); + $__ABC9_LUT6 spo (.A($SPO), .S({1'b1, A4, A3, A2, A1, A0}), .Y(SPO)); + $__ABC9_LUT6 dpo (.A($DPO), .S({1'b1, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); endmodule module RAM64X1D ( @@ -495,17 +495,17 @@ module RAM64X1D ( ); parameter INIT = 64'h0; parameter IS_WCLK_INVERTED = 1'b0; - wire \$DPO , \$SPO ; + wire $DPO, $SPO; RAM64X1D #( .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) ) _TECHMAP_REPLACE_ ( - .DPO(\$DPO ), .SPO(\$SPO ), + .DPO($DPO), .SPO($SPO), .D(D), .WCLK(WCLK), .WE(WE), .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5), .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5) ); - \$__ABC9_LUT6 spo (.A(\$SPO ), .S({A5, A4, A3, A2, A1, A0}), .Y(SPO)); - \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); + $__ABC9_LUT6 spo (.A($SPO), .S({A5, A4, A3, A2, A1, A0}), .Y(SPO)); + $__ABC9_LUT6 dpo (.A($DPO), .S({DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); endmodule module RAM128X1D ( @@ -517,17 +517,17 @@ module RAM128X1D ( ); parameter INIT = 128'h0; parameter IS_WCLK_INVERTED = 1'b0; - wire \$DPO , \$SPO ; + wire $DPO, $SPO; RAM128X1D #( .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) ) _TECHMAP_REPLACE_ ( - .DPO(\$DPO ), .SPO(\$SPO ), + .DPO($DPO), .SPO($SPO), .D(D), .WCLK(WCLK), .WE(WE), .A(A), .DPRA(DPRA) ); - \$__ABC9_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO)); - \$__ABC9_LUT7 dpo (.A(\$DPO ), .S(DPRA), .Y(DPO)); + $__ABC9_LUT7 spo (.A($SPO), .S(A), .Y(SPO)); + $__ABC9_LUT7 dpo (.A($DPO), .S(DPRA), .Y(DPO)); endmodule module RAM32M ( @@ -551,24 +551,24 @@ module RAM32M ( parameter [63:0] INIT_C = 64'h0000000000000000; parameter [63:0] INIT_D = 64'h0000000000000000; parameter [0:0] IS_WCLK_INVERTED = 1'b0; - wire [1:0] \$DOA , \$DOB , \$DOC , \$DOD ; + wire [1:0] $DOA, $DOB, $DOC, $DOD; RAM32M #( .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) ) _TECHMAP_REPLACE_ ( - .DOA(\$DOA ), .DOB(\$DOB ), .DOC(\$DOC ), .DOD(\$DOD ), + .DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD), .WCLK(WCLK), .WE(WE), .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) ); - \$__ABC9_LUT6 doa0 (.A(\$DOA [0]), .S({1'b1, ADDRA}), .Y(DOA[0])); - \$__ABC9_LUT6 doa1 (.A(\$DOA [1]), .S({1'b1, ADDRA}), .Y(DOA[1])); - \$__ABC9_LUT6 dob0 (.A(\$DOB [0]), .S({1'b1, ADDRB}), .Y(DOB[0])); - \$__ABC9_LUT6 dob1 (.A(\$DOB [1]), .S({1'b1, ADDRB}), .Y(DOB[1])); - \$__ABC9_LUT6 doc0 (.A(\$DOC [0]), .S({1'b1, ADDRC}), .Y(DOC[0])); - \$__ABC9_LUT6 doc1 (.A(\$DOC [1]), .S({1'b1, ADDRC}), .Y(DOC[1])); - \$__ABC9_LUT6 dod0 (.A(\$DOD [0]), .S({1'b1, ADDRD}), .Y(DOD[0])); - \$__ABC9_LUT6 dod1 (.A(\$DOD [1]), .S({1'b1, ADDRD}), .Y(DOD[1])); + $__ABC9_LUT6 doa0 (.A($DOA[0]), .S({1'b1, ADDRA}), .Y(DOA[0])); + $__ABC9_LUT6 doa1 (.A($DOA[1]), .S({1'b1, ADDRA}), .Y(DOA[1])); + $__ABC9_LUT6 dob0 (.A($DOB[0]), .S({1'b1, ADDRB}), .Y(DOB[0])); + $__ABC9_LUT6 dob1 (.A($DOB[1]), .S({1'b1, ADDRB}), .Y(DOB[1])); + $__ABC9_LUT6 doc0 (.A($DOC[0]), .S({1'b1, ADDRC}), .Y(DOC[0])); + $__ABC9_LUT6 doc1 (.A($DOC[1]), .S({1'b1, ADDRC}), .Y(DOC[1])); + $__ABC9_LUT6 dod0 (.A($DOD[0]), .S({1'b1, ADDRD}), .Y(DOD[0])); + $__ABC9_LUT6 dod1 (.A($DOD[1]), .S({1'b1, ADDRD}), .Y(DOD[1])); endmodule module RAM64M ( @@ -592,20 +592,20 @@ module RAM64M ( parameter [63:0] INIT_C = 64'h0000000000000000; parameter [63:0] INIT_D = 64'h0000000000000000; parameter [0:0] IS_WCLK_INVERTED = 1'b0; - wire \$DOA , \$DOB , \$DOC , \$DOD ; + wire $DOA, $DOB, $DOC, $DOD; RAM64M #( .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) ) _TECHMAP_REPLACE_ ( - .DOA(\$DOA ), .DOB(\$DOB ), .DOC(\$DOC ), .DOD(\$DOD ), + .DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD), .WCLK(WCLK), .WE(WE), .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) ); - \$__ABC9_LUT6 doa (.A(\$DOA ), .S(ADDRA), .Y(DOA)); - \$__ABC9_LUT6 dob (.A(\$DOB ), .S(ADDRB), .Y(DOB)); - \$__ABC9_LUT6 doc (.A(\$DOC ), .S(ADDRC), .Y(DOC)); - \$__ABC9_LUT6 dod (.A(\$DOD ), .S(ADDRD), .Y(DOD)); + $__ABC9_LUT6 doa (.A($DOA), .S(ADDRA), .Y(DOA)); + $__ABC9_LUT6 dob (.A($DOB), .S(ADDRB), .Y(DOB)); + $__ABC9_LUT6 doc (.A($DOC), .S(ADDRC), .Y(DOC)); + $__ABC9_LUT6 dod (.A($DOD), .S(ADDRD), .Y(DOD)); endmodule module SRL16E ( @@ -614,14 +614,14 @@ module SRL16E ( ); parameter [15:0] INIT = 16'h0000; parameter [0:0] IS_CLK_INVERTED = 1'b0; - wire \$Q ; + wire $Q; SRL16E #( .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) ) _TECHMAP_REPLACE_ ( - .Q(\$Q ), + .Q($Q), .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D) ); - \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); + $__ABC9_LUT6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); endmodule module SRLC32E ( @@ -632,14 +632,14 @@ module SRLC32E ( ); parameter [31:0] INIT = 32'h00000000; parameter [0:0] IS_CLK_INVERTED = 1'b0; - wire \$Q ; + wire $Q; SRLC32E #( .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) ) _TECHMAP_REPLACE_ ( - .Q(\$Q ), .Q31(Q31), + .Q($Q), .Q31(Q31), .A(A), .CE(CE), .CLK(CLK), .D(D) ); - \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q)); + $__ABC9_LUT6 q (.A($Q), .S({1'b1, A}), .Y(Q)); endmodule module DSP48E1 ( @@ -828,15 +828,15 @@ __CELL__ #( if (AREG == 0 && MREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else - \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); + $__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && MREG == 0 && PREG == 0) assign iB = B, pB = 1'bx; else - \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); + $__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) assign iC = C, pC = 1'bx; else - \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); + $__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0) assign iD = D; else if (techmap_guard) @@ -847,27 +847,27 @@ __CELL__ #( assign pAD = 1'bx; if (PREG == 0) begin if (MREG == 1) - \$__ABC9_REG rM (.Q(pM)); + $__ABC9_REG rM (.Q(pM)); else assign pM = 1'bx; assign pP = 1'bx; end else begin assign pM = 1'bx; - \$__ABC9_REG rP (.Q(pP)); + $__ABC9_REG rP (.Q(pP)); end if (MREG == 0 && PREG == 0) assign mP = oP, mPCOUT = oPCOUT; else assign mP = 1'bx, mPCOUT = 1'bx; - \$__ABC9_DSP48E1_MULT_P_MUX muxP ( + $__ABC9_DSP48E1_MULT_P_MUX muxP ( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P) ); - \$__ABC9_DSP48E1_MULT_PCOUT_MUX muxPCOUT ( + $__ABC9_DSP48E1_MULT_PCOUT_MUX muxPCOUT ( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT) ); - `DSP48E1_INST(\$__ABC9_DSP48E1_MULT ) + `DSP48E1_INST($__ABC9_DSP48E1_MULT ) end else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin // Disconnect the A-input if MREG is enabled, since @@ -875,26 +875,26 @@ __CELL__ #( if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else - \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); + $__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && MREG == 0 && PREG == 0) assign iB = B, pB = 1'bx; else - \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); + $__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) assign iC = C, pC = 1'bx; else - \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); + $__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0 && ADREG == 0) assign iD = D, pD = 1'bx; else - \$__ABC9_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD)); + $__ABC9_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD)); if (PREG == 0) begin if (MREG == 1) begin assign pAD = 1'bx; - \$__ABC9_REG rM (.Q(pM)); + $__ABC9_REG rM (.Q(pM)); end else begin if (ADREG == 1) - \$__ABC9_REG rAD (.Q(pAD)); + $__ABC9_REG rAD (.Q(pAD)); else assign pAD = 1'bx; assign pM = 1'bx; @@ -902,21 +902,21 @@ __CELL__ #( assign pP = 1'bx; end else begin assign pAD = 1'bx, pM = 1'bx; - \$__ABC9_REG rP (.Q(pP)); + $__ABC9_REG rP (.Q(pP)); end if (MREG == 0 && PREG == 0) assign mP = oP, mPCOUT = oPCOUT; else assign mP = 1'bx, mPCOUT = 1'bx; - \$__ABC9_DSP48E1_MULT_DPORT_P_MUX muxP ( + $__ABC9_DSP48E1_MULT_DPORT_P_MUX muxP ( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P) ); - \$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT ( + $__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT ( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT) ); - `DSP48E1_INST(\$__ABC9_DSP48E1_MULT_DPORT ) + `DSP48E1_INST($__ABC9_DSP48E1_MULT_DPORT ) end else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin // Disconnect the A-input if MREG is enabled, since @@ -924,15 +924,15 @@ __CELL__ #( if (AREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else - \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); + $__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && PREG == 0) assign iB = B, pB = 1'bx; else - \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); + $__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) assign iC = C, pC = 1'bx; else - \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); + $__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); if (DREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); assign pD = 1'bx; @@ -943,7 +943,7 @@ __CELL__ #( $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\""); assign pM = 1'bx; if (PREG == 1) - \$__ABC9_REG rP (.Q(pP)); + $__ABC9_REG rP (.Q(pP)); else assign pP = 1'bx; @@ -951,14 +951,14 @@ __CELL__ #( assign mP = oP, mPCOUT = oPCOUT; else assign mP = 1'bx, mPCOUT = 1'bx; - \$__ABC9_DSP48E1_P_MUX muxP ( + $__ABC9_DSP48E1_P_MUX muxP ( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P) ); - \$__ABC9_DSP48E1_PCOUT_MUX muxPCOUT ( + $__ABC9_DSP48E1_PCOUT_MUX muxPCOUT ( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT) ); - `DSP48E1_INST(\$__ABC9_DSP48E1 ) + `DSP48E1_INST($__ABC9_DSP48E1 ) end else $error("Invalid DSP48E1 configuration"); -- cgit v1.2.3 From ece423415cbc17654c6ac81a0f4b15783c558660 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 14:24:58 -0800 Subject: Add CHANGELOG entry, add abc9_{flop,keep} attr to README.md --- CHANGELOG | 1 + README.md | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 01ae17c2b..fc0cdc92e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -57,6 +57,7 @@ Yosys 0.9 .. Yosys 0.9-dev always_latch and always_ff) - Added "xilinx_dffopt" pass - Added "scratchpad" pass + - Added "synth_xilinx -dff" Yosys 0.8 .. Yosys 0.9 ---------------------- diff --git a/README.md b/README.md index 0250c7846..c04e2b9ec 100644 --- a/README.md +++ b/README.md @@ -378,6 +378,12 @@ Verilog Attributes and non-standard features for example, to specify the clk-to-Q delay of a flip-flop for consideration during techmapping. +- The module attribute ``abc9_flop`` is a boolean marking the module as a + whitebox that describes the synchronous behaviour of a flip-flop. + +- The cell attribute ``abc9_keep`` is a boolean indicating that this black/ + white box should be preserved through `abc9` mapping. + - The frontend sets attributes ``always_comb``, ``always_latch`` and ``always_ff`` on processes derived from SystemVerilog style always blocks according to the type of the always. These are checked for correctness in -- 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(-) 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 eb4e767053f4731c9f4b82c4dd53504e5fe50802 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 12:03:19 -0800 Subject: Do not offset FD* box timings due to -46ps Tsu --- techlibs/xilinx/abc9_xc7.box | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index a2d119284..16606d14e 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -53,50 +53,59 @@ $__ABC9_ASYNC0 1000 1 2 1 $__ABC9_ASYNC1 1001 1 2 1 0 764 -# The following FD*.{CE,R,CLR,PRE) are offset by 46ps to -# reflect the -46ps Tsu -# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L237-L251 -# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L265-L277 +# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L237-L251 +# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L265-L277 + +# NB: Inputs/Outputs must be ordered alphabetically +# (with exception for \$currQ) # Inputs: C CE D R \$currQ # Outputs: Q FDRE 1100 1 5 1 -0 151 0 446 0 +#0 109 -46 404 0 +0 109 0 404 0 # Clamp -46ps Tsu # Inputs: C CE D R \$currQ # Outputs: Q FDRE_1 1101 1 5 1 -0 151 0 446 0 +#0 109 0 -46 404 +0 109 0 0 404 # Clamp -46ps Tsu # Inputs: C CE CLR D \$currQ # Outputs: Q FDCE 1102 1 5 1 -0 151 806 0 0 +#0 109 764 -46 0 +0 109 764 0 0 # Clamp -46ps Tsu # Inputs: C CE CLR D \$currQ # Outputs: Q FDCE_1 1103 1 5 1 -0 151 806 0 0 +#0 109 764 -46 0 +0 109 764 0 0 # Clamp -46ps Tsu # Inputs: C CE D PRE \$currQ # Outputs: Q FDPE 1104 1 5 1 -0 151 0 806 0 +#0 109 -46 764 0 +0 109 0 764 0 # Clamp -46ps Tsu # Inputs: C CE D PRE \$currQ # Outputs: Q FDPE_1 1105 1 5 1 -0 151 0 806 0 +#0 109 -46 764 0 +0 109 0 764 0 # Clamp -46ps Tsu # Inputs: C CE D S \$currQ # Outputs: Q FDSE 1106 1 5 1 -0 151 0 446 0 +#0 109 -46 446 0 +0 109 0 446 0 # Clamp -46ps Tsu # Inputs: C CE D S \$currQ # Outputs: Q FDSE_1 1107 1 5 1 -0 151 0 446 0 +#0 109 -46 446 0 +0 109 0 446 0 # Clamp -46ps Tsu # SLICEM/A6LUT # Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} -- 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(-) 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 543bd2de6c00f98577263439ebdada7bcda249ab Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 12:15:33 -0800 Subject: Update timings for Xilinx S7 cells --- techlibs/xilinx/cells_sim.v | 50 +++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 3bcbfc9aa..72e684af5 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -1112,8 +1112,8 @@ module RAM16X1D_1 ( endmodule module RAM32X1D ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 - (* abc9_arrival=1153 *) + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L857 + (* abc9_arrival=1188 *) output DPO, SPO, input D, (* clkbuf_sink *) @@ -1135,8 +1135,8 @@ module RAM32X1D ( endmodule module RAM32X1D_1 ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 - (* abc9_arrival=1153 *) + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L857 + (* abc9_arrival=1188 *) output DPO, SPO, input D, (* clkbuf_sink *) @@ -1158,7 +1158,7 @@ module RAM32X1D_1 ( endmodule module RAM64X1D ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L889 (* abc9_arrival=1153 *) output DPO, SPO, input D, @@ -1181,7 +1181,7 @@ module RAM64X1D ( endmodule module RAM64X1D_1 ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L889 (* abc9_arrival=1153 *) output DPO, SPO, input D, @@ -1204,8 +1204,9 @@ module RAM64X1D_1 ( endmodule module RAM128X1D ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 - (* abc9_arrival=1153 *) + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L889 + // plus 204ps to cross MUXF7 + (* abc9_arrival=1357 *) output DPO, SPO, input D, (* clkbuf_sink *) @@ -1244,9 +1245,18 @@ endmodule // Multi port. module RAM32M ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 - (* abc9_arrival=1153 *) - output [1:0] DOA, DOB, DOC, DOD, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L857 + (* abc9_arrival=1188 *) + output [1:0] DOA, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L925 + (* abc9_arrival=1187 *) + output [1:0] DOB, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L993 + (* abc9_arrival=1180 *) + output [1:0] DOC, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1061 + (* abc9_arrival=1190 *) + output [1:0] DOD, input [4:0] ADDRA, ADDRB, ADDRC, ADDRD, input [1:0] DIA, DIB, DIC, DID, (* clkbuf_sink *) @@ -1347,9 +1357,18 @@ module RAM32M16 ( endmodule module RAM64M ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L889 (* abc9_arrival=1153 *) - output DOA, DOB, DOC, DOD, + output DOA, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + (* abc9_arrival=1161 *) + output DOB, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1025 + (* abc9_arrival=1158 *) + output DOC, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1093 + (* abc9_arrival=1163 *) + output DOD, input [5:0] ADDRA, ADDRB, ADDRC, ADDRD, input DIA, DIB, DIC, DID, (* clkbuf_sink *) @@ -1508,7 +1527,7 @@ module SRL16 ( endmodule module SRL16E ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 (* abc9_arrival=1472 *) output Q, input A0, A1, A2, A3, CE, @@ -1572,9 +1591,10 @@ module SRLC16E ( endmodule module SRLC32E ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 (* abc9_arrival=1472 *) output Q, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 (* abc9_arrival=1114 *) output Q31, input [4:0] A, -- cgit v1.2.3 From fc4b8b89912c14f42b04a7c9f2ce350db3ce7c0b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 14:56:14 -0800 Subject: Remove submod changes --- passes/hierarchy/submod.cc | 136 ++++++++++++--------------------------------- tests/various/submod.ys | 102 ---------------------------------- 2 files changed, 37 insertions(+), 201 deletions(-) delete mode 100644 tests/various/submod.ys diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 3b4f33a60..ec242aa1f 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -20,7 +20,6 @@ #include "kernel/register.h" #include "kernel/celltypes.h" #include "kernel/log.h" -#include "kernel/sigtools.h" #include #include #include @@ -33,56 +32,49 @@ struct SubmodWorker CellTypes ct; RTLIL::Design *design; RTLIL::Module *module; - SigMap sigmap; bool copy_mode; - bool hidden_mode; std::string opt_name; struct SubModule { std::string name, full_name; - pool cells; + std::set cells; }; std::map submodules; struct wire_flags_t { RTLIL::Wire *new_wire; - RTLIL::Const is_int_driven; - bool is_int_used, is_ext_driven, is_ext_used; - wire_flags_t(RTLIL::Wire* wire) : new_wire(NULL), is_int_driven(State::S0, GetSize(wire)), is_int_used(false), is_ext_driven(false), is_ext_used(false) { } + bool is_int_driven, is_int_used, is_ext_driven, is_ext_used; + wire_flags_t() : new_wire(NULL), is_int_driven(false), is_int_used(false), is_ext_driven(false), is_ext_used(false) { } }; std::map wire_flags; bool flag_found_something; - void flag_wire(RTLIL::Wire *wire, bool create, bool set_int_used, bool set_ext_driven, bool set_ext_used) + void flag_wire(RTLIL::Wire *wire, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used) { if (wire_flags.count(wire) == 0) { if (!create) return; - wire_flags.emplace(wire, wire); + wire_flags[wire] = wire_flags_t(); } + if (set_int_driven) + wire_flags[wire].is_int_driven = true; if (set_int_used) - wire_flags.at(wire).is_int_used = true; + wire_flags[wire].is_int_used = true; if (set_ext_driven) - wire_flags.at(wire).is_ext_driven = true; + wire_flags[wire].is_ext_driven = true; if (set_ext_used) - wire_flags.at(wire).is_ext_used = true; + wire_flags[wire].is_ext_used = true; flag_found_something = true; } void flag_signal(const RTLIL::SigSpec &sig, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used) { for (auto &c : sig.chunks()) - if (c.wire != NULL) { - flag_wire(c.wire, create, set_int_used, set_ext_driven, set_ext_used); - if (set_int_driven) - for (int i = c.offset; i < c.offset+c.width; i++) { - wire_flags.at(c.wire).is_int_driven[i] = State::S1; - flag_found_something = true; - } - } + if (c.wire != NULL) + flag_wire(c.wire, create, set_int_driven, set_int_used, set_ext_driven, set_ext_used); } void handle_submodule(SubModule &submod) @@ -135,39 +127,27 @@ struct SubmodWorker flags.is_ext_driven = true; if (wire->port_output) flags.is_ext_used = true; - else { - auto sig = sigmap(wire); - for (auto c : sig.chunks()) - if (c.wire && c.wire->port_output) { - flags.is_ext_used = true; - break; - } - } bool new_wire_port_input = false; bool new_wire_port_output = false; - if (!flags.is_int_driven.is_fully_zero() && flags.is_ext_used) + if (flags.is_int_driven && flags.is_ext_used) new_wire_port_output = true; if (flags.is_ext_driven && flags.is_int_used) new_wire_port_input = true; - if (!flags.is_int_driven.is_fully_zero() && flags.is_ext_driven) + if (flags.is_int_driven && flags.is_ext_driven) new_wire_port_input = true, new_wire_port_output = true; std::string new_wire_name = wire->name.str(); if (new_wire_port_input || new_wire_port_output) { - if (new_wire_name[0] == '$') - while (1) { - std::string next_wire_name = stringf("%s\\n%d", hidden_mode ? "$submod" : "", auto_name_counter++); - if (all_wire_names.count(next_wire_name) == 0) { - all_wire_names.insert(next_wire_name); - new_wire_name = next_wire_name; - break; - } + while (new_wire_name[0] == '$') { + std::string next_wire_name = stringf("\\n%d", auto_name_counter++); + if (all_wire_names.count(next_wire_name) == 0) { + all_wire_names.insert(next_wire_name); + new_wire_name = next_wire_name; } - else if (hidden_mode) - new_wire_name = stringf("$submod%s", new_wire_name.c_str()); + } } RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name, wire->width); @@ -175,22 +155,6 @@ struct SubmodWorker new_wire->port_output = new_wire_port_output; new_wire->start_offset = wire->start_offset; new_wire->attributes = wire->attributes; - if (!flags.is_int_driven.is_fully_zero()) { - new_wire->attributes.erase(ID(init)); - auto sig = sigmap(wire); - for (int i = 0; i < GetSize(sig); i++) { - if (flags.is_int_driven[i] == State::S0) - continue; - if (!sig[i].wire) - continue; - auto it = sig[i].wire->attributes.find(ID(init)); - if (it != sig[i].wire->attributes.end()) { - auto jt = new_wire->attributes.insert(std::make_pair(ID(init), Const(State::Sx, GetSize(sig)))).first; - jt->second[i] = it->second[sig[i].offset]; - it->second[sig[i].offset] = State::Sx; - } - } - } if (new_wire->port_input && new_wire->port_output) log(" signal %s: inout %s\n", wire->name.c_str(), new_wire->name.c_str()); @@ -213,7 +177,7 @@ struct SubmodWorker for (auto &bit : conn.second) if (bit.wire != NULL) { log_assert(wire_flags.count(bit.wire) > 0); - bit.wire = wire_flags.at(bit.wire).new_wire; + bit.wire = wire_flags[bit.wire].new_wire; } log(" cell %s (%s)\n", new_cell->name.c_str(), new_cell->type.c_str()); if (!copy_mode) @@ -225,27 +189,16 @@ struct SubmodWorker RTLIL::Cell *new_cell = module->addCell(submod.full_name, submod.full_name); for (auto &it : wire_flags) { - RTLIL::SigSpec old_sig = sigmap(it.first); + RTLIL::Wire *old_wire = it.first; RTLIL::Wire *new_wire = it.second.new_wire; - if (new_wire->port_id > 0) { - if (new_wire->port_output) - for (int i = 0; i < GetSize(old_sig); i++) { - auto &b = old_sig[i]; - // Prevents "ERROR: Mismatch in directionality ..." when flattening - if (!b.wire) - b = module->addWire(NEW_ID); - // Prevents "Warning: multiple conflicting drivers ..." - else if (!it.second.is_int_driven[i]) - b = module->addWire(NEW_ID); - } - new_cell->setPort(new_wire->name, old_sig); - } + if (new_wire->port_id > 0) + new_cell->setPort(new_wire->name, RTLIL::SigSpec(old_wire)); } } } - SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, bool hidden_mode = false, std::string opt_name = std::string()) : - design(design), module(module), sigmap(module), copy_mode(copy_mode), hidden_mode(hidden_mode), opt_name(opt_name) + SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, std::string opt_name = std::string()) : + design(design), module(module), copy_mode(copy_mode), opt_name(opt_name) { if (!design->selected_whole_module(module->name) && opt_name.empty()) return; @@ -266,12 +219,6 @@ struct SubmodWorker ct.setup_stdcells_mem(); ct.setup_design(design); - for (auto port : module->ports) { - auto wire = module->wire(port); - if (wire->port_output) - sigmap.add(wire); - } - if (opt_name.empty()) { for (auto &it : module->wires_) @@ -326,7 +273,7 @@ struct SubmodPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" submod [options] [selection]\n"); + log(" submod [-copy] [selection]\n"); log("\n"); log("This pass identifies all cells with the 'submod' attribute and moves them to\n"); log("a newly created module. The value of the attribute is used as name for the\n"); @@ -338,20 +285,16 @@ struct SubmodPass : public Pass { log("This pass only operates on completely selected modules with no processes\n"); log("or memories.\n"); log("\n"); - log(" -copy\n"); - log(" by default the cells are 'moved' from the source module and the source\n"); - log(" module will use an instance of the new module after this command is\n"); - log(" finished. call with -copy to not modify the source module.\n"); log("\n"); - log(" -name \n"); - log(" don't use the 'submod' attribute but instead use the selection. only\n"); - log(" objects from one module might be selected. the value of the -name option\n"); - log(" is used as the value of the 'submod' attribute instead.\n"); + log(" submod -name [-copy] [selection]\n"); + log("\n"); + log("As above, but don't use the 'submod' attribute but instead use the selection.\n"); + log("Only objects from one module might be selected. The value of the -name option\n"); + log("is used as the value of the 'submod' attribute above.\n"); log("\n"); - log(" -hidden\n"); - log(" instead of creating submodule ports with public names, create ports with\n"); - log(" private names so that a subsequent 'flatten; clean' call will restore the\n"); - log(" original module with original public names.\n"); + log("By default the cells are 'moved' from the source module and the source module\n"); + log("will use an instance of the new module after this command is finished. Call\n"); + log("with -copy to not modify the source module.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -361,7 +304,6 @@ struct SubmodPass : public Pass { std::string opt_name; bool copy_mode = false; - bool hidden_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -373,10 +315,6 @@ struct SubmodPass : public Pass { copy_mode = true; continue; } - if (args[argidx] == "-hidden") { - hidden_mode = true; - continue; - } break; } extra_args(args, argidx, design); @@ -397,7 +335,7 @@ struct SubmodPass : public Pass { queued_modules.push_back(mod_it.first); for (auto &modname : queued_modules) if (design->modules_.count(modname) != 0) { - SubmodWorker worker(design, design->modules_[modname], copy_mode, hidden_mode); + SubmodWorker worker(design, design->modules_[modname], copy_mode); handled_modules.insert(modname); did_something = true; } @@ -420,7 +358,7 @@ struct SubmodPass : public Pass { else { Pass::call_on_module(design, module, "opt_clean"); log_header(design, "Continuing SUBMOD pass.\n"); - SubmodWorker worker(design, module, copy_mode, hidden_mode, opt_name); + SubmodWorker worker(design, module, copy_mode, opt_name); } } diff --git a/tests/various/submod.ys b/tests/various/submod.ys deleted file mode 100644 index 9d7dabdd7..000000000 --- a/tests/various/submod.ys +++ /dev/null @@ -1,102 +0,0 @@ -read_verilog < Date: Mon, 30 Dec 2019 12:26:39 -0800 Subject: Grammar --- passes/techmap/abc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index b29480e26..279b32223 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1767,7 +1767,7 @@ struct AbcPass : public Pass { extra_args(args, argidx, design); if (!lut_costs.empty() && !liberty_file.empty()) - log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n"); + log_cmd_error("Got -lut and -liberty! These two options are exclusive.\n"); if (!constr_file.empty() && liberty_file.empty()) log_cmd_error("Got -constr but no -liberty!\n"); -- 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 ++---- passes/techmap/abc9.cc | 188 ++++------------------------------------------- 2 files changed, 20 insertions(+), 190 deletions(-) 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) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 19a1d2ccb..a0403535b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -268,13 +268,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip if (!lut_costs.empty()) { abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); if (!box_file.empty()) - abc9_script += stringf("read_box -v %s; ", box_file.c_str()); + abc9_script += stringf("read_box %s; ", box_file.c_str()); } else if (!lut_file.empty()) { abc9_script += stringf("read_lut %s; ", lut_file.c_str()); if (!box_file.empty()) - abc9_script += stringf("read_box -v %s; ", box_file.c_str()); + abc9_script += stringf("read_box %s; ", box_file.c_str()); } else log_abort(); @@ -321,20 +321,22 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip fprintf(f, "%s\n", abc9_script.c_str()); fclose(f); - //bool count_output = false; log_push(); - //if (count_output) - { - handle_loops(design, module); + handle_loops(design, module); - Pass::call(design, "aigmap -select"); + Pass::call(design, "aigmap -select"); - //log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", - // count_gates, GetSize(signal_list), count_input, count_output); + Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); - Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); + int count_outputs = design->scratchpad_get_int("write_xaiger.num_outputs"); + log("Extracted %d AND gates and %d wires to a netlist network with %d inputs and %d outputs.\n", + design->scratchpad_get_int("write_xaiger.num_ands"), + design->scratchpad_get_int("write_xaiger.num_wires"), + design->scratchpad_get_int("write_xaiger.num_inputs"), + count_outputs); + if (count_outputs > 0) { std::string buffer; std::ifstream ifs; #if 0 @@ -1053,35 +1055,6 @@ struct Abc9Pass : public Pass { dict clk_to_mergeability; const std::vector all_cells = module->selected_cells(); -#if 0 - pool unassigned_cells(all_cells.begin(), all_cells.end()); - - pool expand_queue, next_expand_queue; - pool expand_queue_up, next_expand_queue_up; - pool expand_queue_down, next_expand_queue_down; - - std::map> assigned_cells; - std::map assigned_cells_reverse; - - std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; - std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; - - for (auto cell : all_cells) - for (auto &conn : cell->connections()) - for (auto bit : assign_map(conn.second)) - if (bit.wire != nullptr) { - cell_to_bit[cell].insert(bit); - bit_to_cell[bit].insert(cell); - if (ct.cell_input(cell->type, conn.first)) { - cell_to_bit_up[cell].insert(bit); - bit_to_cell_down[bit].insert(cell); - } - if (ct.cell_output(cell->type, conn.first)) { - cell_to_bit_down[cell].insert(bit); - bit_to_cell_up[bit].insert(cell); - } - } -#endif for (auto cell : all_cells) { auto inst_module = design->module(cell->type); @@ -1095,12 +1068,6 @@ struct Abc9Pass : public Pass { SigSpec abc9_clock = assign_map(abc9_clock_wire); clkdomain_t key(abc9_clock); -#if 0 - unassigned_cells.erase(cell); - expand_queue_up.insert(cell); - assigned_cells[key].insert(cell->name); - assigned_cells_reverse[cell] = key; -#endif auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1)); auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); @@ -1115,137 +1082,12 @@ struct Abc9Pass : public Pass { log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); log_assert(r2.second); - -#if 0 - // Also assign these special ABC9 cells to the - // same clock domain - for (auto b : cell_to_bit_down[cell]) - for (auto c : bit_to_cell_down[b]) - if (c->type == "$__ABC9_FF_") { - cell = c; - unassigned_cells.erase(cell); - assigned_cells[key].insert(cell->name); - assigned_cells_reverse[cell] = key; - break; - } - for (auto b : cell_to_bit_down[cell]) - for (auto c : bit_to_cell_down[b]) - if (c->type == "$__ABC9_ASYNC") { - cell = c; - unassigned_cells.erase(cell); - assigned_cells[key].insert(cell->name); - assigned_cells_reverse[cell] = key; - break; - } - - expand_queue.insert(cell); - expand_queue_down.insert(cell); -#endif } -#if 0 - while (!expand_queue_up.empty() || !expand_queue_down.empty()) - { - if (!expand_queue_up.empty()) - { - RTLIL::Cell *cell = *expand_queue_up.begin(); - auto key = assigned_cells_reverse.at(cell); - expand_queue_up.erase(cell); - - for (auto bit : cell_to_bit_up[cell]) - for (auto c : bit_to_cell_up[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].insert(c->name); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (!expand_queue_down.empty()) - { - RTLIL::Cell *cell = *expand_queue_down.begin(); - auto key = assigned_cells_reverse.at(cell); - expand_queue_down.erase(cell); - - for (auto bit : cell_to_bit_down[cell]) - for (auto c : bit_to_cell_down[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue_up.insert(c); - assigned_cells[key].insert(c->name); - assigned_cells_reverse[c] = key; - expand_queue.insert(c); - } - } - - if (expand_queue_up.empty() && expand_queue_down.empty()) { - expand_queue_up.swap(next_expand_queue_up); - expand_queue_down.swap(next_expand_queue_down); - } - } - - while (!expand_queue.empty()) - { - RTLIL::Cell *cell = *expand_queue.begin(); - auto key = assigned_cells_reverse.at(cell); - expand_queue.erase(cell); - - for (auto bit : cell_to_bit.at(cell)) { - for (auto c : bit_to_cell[bit]) - if (unassigned_cells.count(c)) { - unassigned_cells.erase(c); - next_expand_queue.insert(c); - assigned_cells[key].insert(c->name); - assigned_cells_reverse[c] = key; - } - bit_to_cell[bit].clear(); - } - - if (expand_queue.empty()) - expand_queue.swap(next_expand_queue); - } - - clkdomain_t key; - for (auto cell : unassigned_cells) { - assigned_cells[key].insert(cell->name); - assigned_cells_reverse[cell] = key; - } - - log_header(design, "Summary of detected clock domains:\n"); - for (auto &it : assigned_cells) { - log(" %d cells in clk=%s\n", GetSize(it.second), log_signal(it.first)); - } -#endif - design->selected_active_module = module->name.str(); -#if 0 - design->selection_stack.emplace_back(false); - for (auto &it : assigned_cells) { - std::string target = delay_target; - if (target.empty()) { - for (auto b : assign_map(it.first)) - if (b.wire) { - auto jt = b.wire->attributes.find("\\abc9_period"); - if (jt != b.wire->attributes.end()) { - target = stringf("-D %d", jt->second.as_int()); - log("Target period = %s ps for clock domain %s\n", target.c_str(), log_signal(it.first)); - break; - } - } - } - RTLIL::Selection& sel = design->selection_stack.back(); - sel.selected_members[module->name] = std::move(it.second); -#endif - abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, - delay_target, lutin_shared, fast_mode, all_cells, show_tempdir, - box_file, lut_file, wire_delay, box_lookup, nomfs); -#if 0 - assign_map.set(module); - } - design->selection_stack.pop_back(); -#endif + abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, + delay_target, lutin_shared, fast_mode, all_cells, show_tempdir, + box_file, lut_file, wire_delay, box_lookup, nomfs); design->selected_active_module.clear(); } -- cgit v1.2.3 From 4c3f517425d7aa7a4349696cd1c21d46aa9ad03f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 16:11:42 -0800 Subject: Remove delay targets doc --- passes/techmap/abc9.cc | 9 --------- 1 file changed, 9 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index a0403535b..b63a1aa6c 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -825,15 +825,6 @@ struct Abc9Pass : public Pass { log("design as an XAIGER file with write_xaiger and then load that into ABC externally\n"); log("if you want to use ABC to convert your design into another format.\n"); log("\n"); - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("Delay targets can also be specified on a per clock basis by attaching a\n"); - log("'(* abc9_period = *)' attribute onto clock wires (specifically, onto wires\n"); - log("that appear inside any special '$abc9_clock' wires inserted by abc9_map.v). This\n"); - log("can be achieved by modifying the source directly, or through a `setattr`\n"); - log("invocation. Since such attributes cannot yet be propagated through a\n"); - log("hierarchical design (whether or not it has been uniquified) it is recommended\n"); - log("that the design be flattened when using this feature.\n"); - log("\n"); log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); log("\n"); } -- cgit v1.2.3 From dbffbeef5c2df2345c786e195d2006d7bb23578a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 16:21:20 -0800 Subject: Fix struct name --- passes/techmap/abc9_map.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9_map.cc b/passes/techmap/abc9_map.cc index 6c431b185..7d53db5ea 100644 --- a/passes/techmap/abc9_map.cc +++ b/passes/techmap/abc9_map.cc @@ -650,8 +650,8 @@ clone_lut: log_pop(); } -struct Abc9TechmapPass : public Pass { - Abc9TechmapPass() : Pass("abc9_map", "use ABC9 for technology mapping") { } +struct Abc9MapPass : public Pass { + Abc9MapPass() : Pass("abc9_map", "use ABC9 for technology mapping") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -1017,6 +1017,6 @@ struct Abc9TechmapPass : public Pass { log_pop(); } -} Abc9TechmapPass; +} Abc9MapPass; PRIVATE_NAMESPACE_END -- cgit v1.2.3 From 88b9c8d46ddac513831dc79d370f8abb23ab68fc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 16:29:08 -0800 Subject: Restore count_outputs, move process check to abc --- passes/techmap/abc9.cc | 10 +++++++++- passes/techmap/abc9_map.cc | 14 ++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index d507a6973..ac64ae86d 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -164,7 +164,7 @@ struct Abc9Pass : public ScriptPass map_cmd << " " << arg << " " << args[++argidx]; continue; } - if (arg == "-fast" || /*arg == "-dff" ||*/ arg == "-keepff" + if (arg == "-fast" /*|| arg == "-nocleanup"*/ || arg == "-showtmp" || arg == "-markgroups" || arg == "-nomfs") { map_cmd << " " << arg; @@ -189,6 +189,14 @@ struct Abc9Pass : public ScriptPass active_design->selection_stack.emplace_back(false); for (auto mod : selected_modules) { + if (module->attributes.count(ID(abc9_box_id))) + continue; + + if (module->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(module)); + continue; + } + log_push(); active_design->selection().select(mod); diff --git a/passes/techmap/abc9_map.cc b/passes/techmap/abc9_map.cc index 7d53db5ea..83f90a762 100644 --- a/passes/techmap/abc9_map.cc +++ b/passes/techmap/abc9_map.cc @@ -268,15 +268,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip log_push(); - // FIXME: - /*int count_outputs = design->scratchpad_get_int("write_xaiger.num_outputs"); + int count_outputs = design->scratchpad_get_int("write_xaiger.num_outputs"); log("Extracted %d AND gates and %d wires to a netlist network with %d inputs and %d outputs.\n", design->scratchpad_get_int("write_xaiger.num_ands"), design->scratchpad_get_int("write_xaiger.num_wires"), design->scratchpad_get_int("write_xaiger.num_inputs"), count_outputs); - if (count_outputs > 0)*/ { + if (count_outputs > 0) { std::string buffer; std::ifstream ifs; #if 0 @@ -965,13 +964,8 @@ struct Abc9MapPass : public Pass { CellTypes ct(design); for (auto module : design->selected_modules()) { - if (module->attributes.count(ID(abc9_box_id))) - continue; - - if (module->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(module)); - continue; - } + if (module->processes.size() > 0) + log_error("Module '%s' has processes!\n", log_id(module)); assign_map.set(module); -- cgit v1.2.3 From 16c4ec7edaa3cb66ced2f856d3c48f30d7d2acf1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 16:36:33 -0800 Subject: Add abc9_ops -prep_dff --- passes/techmap/abc9.cc | 8 ++++---- passes/techmap/abc9_map.cc | 35 ----------------------------------- passes/techmap/abc9_ops.cc | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 39 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index ac64ae86d..cd798cfbe 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -189,11 +189,11 @@ struct Abc9Pass : public ScriptPass active_design->selection_stack.emplace_back(false); for (auto mod : selected_modules) { - if (module->attributes.count(ID(abc9_box_id))) + if (mod->attributes.count(ID(abc9_box_id))) continue; - if (module->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(module)); + if (mod->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(mod)); continue; } @@ -207,7 +207,7 @@ struct Abc9Pass : public ScriptPass tempdir_name = make_temp_dir(tempdir_name); run("scc -set_attr abc9_scc_id {}"); - run("abc9_ops -break_scc"); + run("abc9_ops -break_scc -prep_dff"); run("aigmap"); run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()), "write_xaiger -map /input.sym /input.xaig"); diff --git a/passes/techmap/abc9_map.cc b/passes/techmap/abc9_map.cc index 83f90a762..6b9d0afff 100644 --- a/passes/techmap/abc9_map.cc +++ b/passes/techmap/abc9_map.cc @@ -960,48 +960,13 @@ struct Abc9MapPass : public Pass { } } - SigMap assign_map; - CellTypes ct(design); for (auto module : design->selected_modules()) { if (module->processes.size() > 0) log_error("Module '%s' has processes!\n", log_id(module)); - assign_map.set(module); - - typedef SigSpec clkdomain_t; - dict clk_to_mergeability; - const std::vector all_cells = module->selected_cells(); - for (auto cell : all_cells) { - auto inst_module = design->module(cell->type); - if (!inst_module || !inst_module->attributes.count("\\abc9_flop") - || cell->get_bool_attribute("\\abc9_keep")) - continue; - - Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); - if (abc9_clock_wire == NULL) - log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - SigSpec abc9_clock = assign_map(abc9_clock_wire); - - clkdomain_t key(abc9_clock); - - auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1)); - auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); - log_assert(r2.second); - - Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str())); - if (abc9_init_wire == NULL) - log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - log_assert(GetSize(abc9_init_wire) == 1); - SigSpec abc9_init = assign_map(abc9_init_wire); - if (!abc9_init.is_fully_const()) - log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); - log_assert(r2.second); - } - design->selected_active_module = module->name.str(); abc9_module(design, module, script_file, exe_file, lut_costs, delay_target, lutin_shared, fast_mode, all_cells, show_tempdir, diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 4c30efd06..3e7e5ec7f 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -19,6 +19,7 @@ */ #include "kernel/register.h" +#include "kernel/sigtools.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -95,6 +96,44 @@ void unbreak_scc(RTLIL::Module *module) { module->fixup_ports(); } +void prep_dff(RTLIL::Module *module) { + auto design = module->design; + log_assert(design); + + SigMap assign_map(module); + + typedef SigSpec clkdomain_t; + dict clk_to_mergeability; + + for (auto cell : module->selected_cells()) { + auto inst_module = design->module(cell->type); + if (!inst_module || !inst_module->attributes.count("\\abc9_flop") + || cell->get_bool_attribute("\\abc9_keep")) + continue; + + Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); + if (abc9_clock_wire == NULL) + log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + SigSpec abc9_clock = assign_map(abc9_clock_wire); + + clkdomain_t key(abc9_clock); + + auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1)); + auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); + log_assert(r2.second); + + Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str())); + if (abc9_init_wire == NULL) + log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_assert(GetSize(abc9_init_wire) == 1); + SigSpec abc9_init = assign_map(abc9_init_wire); + if (!abc9_init.is_fully_const()) + log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); + log_assert(r2.second); + } +} + struct Abc9PrepPass : public Pass { Abc9PrepPass() : Pass("abc9_ops", "helper functions for ABC9") { } void help() YS_OVERRIDE @@ -111,6 +150,7 @@ struct Abc9PrepPass : public Pass { bool break_scc_mode = false; bool unbreak_scc_mode = false; + bool prep_dff_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -123,6 +163,10 @@ struct Abc9PrepPass : public Pass { unbreak_scc_mode = true; continue; } + if (arg == "-prep_dff") { + prep_dff_mode = true; + continue; + } break; } extra_args(args, argidx, design); @@ -132,6 +176,8 @@ struct Abc9PrepPass : public Pass { break_scc(mod); if (unbreak_scc_mode) unbreak_scc(mod); + if (prep_dff_mode) + prep_dff(mod); } } } Abc9PrepPass; -- 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 ++------------------ passes/techmap/abc9.cc | 2 +- passes/techmap/abc9_ops.cc | 314 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 321 insertions(+), 135 deletions(-) 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(); } } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index cd798cfbe..e11b15065 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -207,7 +207,7 @@ struct Abc9Pass : public ScriptPass tempdir_name = make_temp_dir(tempdir_name); run("scc -set_attr abc9_scc_id {}"); - run("abc9_ops -break_scc -prep_dff"); + run("abc9_ops -break_scc -prep_dff -prep_holes"); run("aigmap"); run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()), "write_xaiger -map /input.sym /input.xaig"); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 3e7e5ec7f..8eb935e1f 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -20,6 +20,7 @@ #include "kernel/register.h" #include "kernel/sigtools.h" +#include "kernel/utils.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -75,7 +76,8 @@ void break_scc(RTLIL::Module *module) module->fixup_ports(); } -void unbreak_scc(RTLIL::Module *module) { +void unbreak_scc(RTLIL::Module *module) +{ // Now 'unexpose' those wires by undoing // the expose operation -- remove them from PO/PI // and re-connecting them back together @@ -96,7 +98,8 @@ void unbreak_scc(RTLIL::Module *module) { module->fixup_ports(); } -void prep_dff(RTLIL::Module *module) { +void prep_dff(RTLIL::Module *module) +{ auto design = module->design; log_assert(design); @@ -134,6 +137,306 @@ void prep_dff(RTLIL::Module *module) { } } +void prep_holes(RTLIL::Module *module) +{ + auto design = module->design; + log_assert(design); + + SigMap sigmap(module); + + // 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_") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); + 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()); + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); + continue; + } + + if (cell->type == "$__ABC9_FF_") + continue; + + RTLIL::Module* inst_module = design->module(cell->type); + if (inst_module) { + if (!inst_module->attributes.count("\\abc9_box_id") || cell->get_bool_attribute("\\abc9_keep")) + continue; + + for (const auto &conn : cell->connections()) { + auto port_wire = inst_module->wire(conn.first); + // 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); + } + + abc9_box_seen = true; + + toposort.node(cell->name); + } + } + + if (!abc9_box_seen) + return; + + 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); + + vector box_list; + for (auto cell_name : toposort.sorted) { + RTLIL::Cell *cell = module->cell(cell_name); + log_assert(cell); + + RTLIL::Module* box_module = design->module(cell->type); + 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 */); + + // 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); + 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->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); + } + } + } + + box_list.emplace_back(cell); + } + log_assert(!box_list.empty()); + + RTLIL::Module *holes_module = design->addModule(stringf("%s$holes", module->name.c_str())); + log_assert(holes_module); + + dict cell_cache; + + int port_id = 1; + for (auto cell : box_list) { + RTLIL::Module* orig_box_module = design->module(cell->type); + log_assert(orig_box_module); + IdString derived_name = orig_box_module->derive(design, cell->parameters); + RTLIL::Module* box_module = design->module(derived_name); + if (box_module->has_processes()) + Pass::call_on_module(design, box_module, "proc"); + + int box_inputs = 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) + 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); + + 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); + } + } + + 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(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; + holes_design->add(holes_module); + Pass::call(holes_design, "opt -purge"); + holes_design->modules_.erase(holes_module->name); + holes_module->design = design; + + log_pop(); +} + struct Abc9PrepPass : public Pass { Abc9PrepPass() : Pass("abc9_ops", "helper functions for ABC9") { } void help() YS_OVERRIDE @@ -151,6 +454,7 @@ struct Abc9PrepPass : public Pass { bool break_scc_mode = false; bool unbreak_scc_mode = false; bool prep_dff_mode = false; + bool prep_holes_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -167,6 +471,10 @@ struct Abc9PrepPass : public Pass { prep_dff_mode = true; continue; } + if (arg == "-prep_holes") { + prep_holes_mode = true; + continue; + } break; } extra_args(args, argidx, design); @@ -178,6 +486,8 @@ struct Abc9PrepPass : public Pass { unbreak_scc(mod); if (prep_dff_mode) prep_dff(mod); + if (prep_holes_mode) + prep_holes(mod); } } } Abc9PrepPass; -- 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(-) 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(-) 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 0317a2b476f5ec78cab35b79a02d166c84c0f53e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 18:46:22 -0800 Subject: holes_module to be whitebox --- passes/techmap/abc9_ops.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 8eb935e1f..e65b16fc6 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -434,6 +434,8 @@ void prep_holes(RTLIL::Module *module) holes_design->modules_.erase(holes_module->name); holes_module->design = design; + holes_module->set_bool_attribute(ID::whitebox); + log_pop(); } @@ -480,6 +482,14 @@ struct Abc9PrepPass : public Pass { extra_args(args, argidx, design); for (auto mod : design->selected_modules()) { + if (mod->get_blackbox_attribute()) + continue; + + if (mod->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(mod)); + continue; + } + if (break_scc_mode) break_scc(mod); if (unbreak_scc_mode) -- cgit v1.2.3 From 52f649dcfd2bba3e4efc219b53e7937281a658c6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 18:47:06 -0800 Subject: Use function arg --- passes/techmap/abc9_map.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/passes/techmap/abc9_map.cc b/passes/techmap/abc9_map.cc index 6b9d0afff..9764d057c 100644 --- a/passes/techmap/abc9_map.cc +++ b/passes/techmap/abc9_map.cc @@ -198,7 +198,7 @@ struct abc9_output_filter void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file, vector lut_costs, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, - const std::vector &/*cells*/, bool show_tempdir, std::string box_file, std::string lut_file, + const std::vector &cells, bool show_tempdir, std::string box_file, std::string lut_file, std::string wire_delay, const dict &box_lookup, bool nomfs, std::string tempdir_name ) { @@ -359,7 +359,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip dict abc9_box; vector boxes; - for (auto cell : module->selected_cells()) { + for (auto cell : cells) { if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) { module->remove(cell); continue; @@ -960,18 +960,18 @@ struct Abc9MapPass : public Pass { } } - for (auto module : design->selected_modules()) + for (auto mod : design->selected_modules()) { - if (module->processes.size() > 0) - log_error("Module '%s' has processes!\n", log_id(module)); + if (mod->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(mod)); + continue; + } - const std::vector all_cells = module->selected_cells(); + const std::vector all_cells = mod->selected_cells(); - design->selected_active_module = module->name.str(); - abc9_module(design, module, script_file, exe_file, lut_costs, + abc9_module(design, mod, script_file, exe_file, lut_costs, delay_target, lutin_shared, fast_mode, all_cells, show_tempdir, box_file, lut_file, wire_delay, box_lookup, nomfs, tempdir_name); - design->selected_active_module.clear(); } log_pop(); -- 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(-) 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 ++ passes/techmap/abc9.cc | 14 +++++- passes/techmap/abc9_ops.cc | 113 +++++++++++++++++++-------------------------- 3 files changed, 63 insertions(+), 68 deletions(-) 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); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index e11b15065..7d922df56 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -185,11 +185,21 @@ struct Abc9Pass : public ScriptPass void script() YS_OVERRIDE { + run("abc9_ops -prep_holes"); + run("select -set abc9_holes A:abc9_holes"); + run("flatten -wb @abc9_holes"); + run("techmap @abc9_holes"); + run("aigmap @abc9_holes"); + run("select -list @abc9_holes"); + run("abc9_ops -prep_dff"); + run("opt -purge @abc9_holes"); + run("setattr -mod -set whitebox 1 @abc9_holes"); + auto selected_modules = active_design->selected_modules(); active_design->selection_stack.emplace_back(false); for (auto mod : selected_modules) { - if (mod->attributes.count(ID(abc9_box_id))) + if (mod->get_blackbox_attribute()) continue; if (mod->processes.size() > 0) { @@ -207,7 +217,7 @@ struct Abc9Pass : public ScriptPass tempdir_name = make_temp_dir(tempdir_name); run("scc -set_attr abc9_scc_id {}"); - run("abc9_ops -break_scc -prep_dff -prep_holes"); + run("abc9_ops -break_scc"); run("aigmap"); run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()), "write_xaiger -map /input.sym /input.xaig"); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index e65b16fc6..b52382972 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -135,6 +135,50 @@ void prep_dff(RTLIL::Module *module) r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); log_assert(r2.second); } + + RTLIL::Module *holes_module = design->module(stringf("%s$holes", module->name.c_str())); + log_assert(holes_module); + + 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); + } + else + ++it; + } + + for (auto &conn : holes_module->connections_) { + auto it = replace.find(conn); + if (it != replace.end()) + conn = it->second; + } } void prep_holes(RTLIL::Module *module) @@ -280,6 +324,7 @@ void prep_holes(RTLIL::Module *module) RTLIL::Module *holes_module = design->addModule(stringf("%s$holes", module->name.c_str())); log_assert(holes_module); + holes_module->set_bool_attribute("\\abc9_holes"); dict cell_cache; @@ -371,72 +416,6 @@ void prep_holes(RTLIL::Module *module) holes_module->connect(w, holes_wire); } } - - 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(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; - holes_design->add(holes_module); - Pass::call(holes_design, "opt -purge"); - holes_design->modules_.erase(holes_module->name); - holes_module->design = design; - - holes_module->set_bool_attribute(ID::whitebox); - - log_pop(); } struct Abc9PrepPass : public Pass { @@ -484,6 +463,8 @@ struct Abc9PrepPass : public Pass { for (auto mod : design->selected_modules()) { if (mod->get_blackbox_attribute()) continue; + if (mod->get_bool_attribute("\\abc9_holes")) + continue; if (mod->processes.size() > 0) { log("Skipping module %s as it contains processes.\n", log_id(mod)); -- cgit v1.2.3 From 0c4be94a02a70de495343258ecda19eb20b3616b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 20:13:25 -0800 Subject: Add -D DFF_MODE to abc9_map test --- tests/arch/xilinx/abc9_map.ys | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/arch/xilinx/abc9_map.ys b/tests/arch/xilinx/abc9_map.ys index 6823589f1..4a7b9384a 100644 --- a/tests/arch/xilinx/abc9_map.ys +++ b/tests/arch/xilinx/abc9_map.ys @@ -6,7 +6,7 @@ endmodule EOT design -save gold -techmap -map +/xilinx/abc9_map.v -max_iter 1 +techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE techmap -map +/xilinx/abc9_unmap.v select -assert-count 1 t:FDSE select -assert-count 1 t:FDSE_1 @@ -29,7 +29,7 @@ endmodule EOT design -save gold -techmap -map +/xilinx/abc9_map.v -max_iter 1 +techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE techmap -map +/xilinx/abc9_unmap.v select -assert-count 1 t:FDRE select -assert-count 1 t:FDRE_1 @@ -52,7 +52,7 @@ endmodule EOT design -save gold -techmap -map +/xilinx/abc9_map.v -max_iter 1 +techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE techmap -map +/xilinx/abc9_unmap.v select -assert-count 1 t:FDCE select -assert-count 1 t:FDCE_1 @@ -76,7 +76,7 @@ endmodule EOT design -save gold -techmap -map +/xilinx/abc9_map.v -max_iter 1 +techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE techmap -map +/xilinx/abc9_unmap.v select -assert-count 1 t:FDPE techmap -autoproc -map +/xilinx/cells_sim.v -- 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(-) 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 a367f703ea0633a4a6289415ae8a4545440ee705 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 22:56:19 -0800 Subject: Rename struct --- passes/techmap/abc9_ops.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index b52382972..271b76a39 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -418,8 +418,8 @@ void prep_holes(RTLIL::Module *module) } } -struct Abc9PrepPass : public Pass { - Abc9PrepPass() : Pass("abc9_ops", "helper functions for ABC9") { } +struct Abc9OpsPass : public Pass { + Abc9OpsPass() : Pass("abc9_ops", "helper functions for ABC9") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -481,6 +481,6 @@ struct Abc9PrepPass : public Pass { prep_holes(mod); } } -} Abc9PrepPass; +} Abc9OpsPass; PRIVATE_NAMESPACE_END -- cgit v1.2.3 From f1bf44ae8f66e81b7de6a2ec47c4a9dffe7e6587 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 22:58:39 -0800 Subject: abc9_ops -prep_dff cope with lack of holes module --- passes/techmap/abc9_ops.cc | 76 +++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 271b76a39..019868adb 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -137,47 +137,47 @@ void prep_dff(RTLIL::Module *module) } RTLIL::Module *holes_module = design->module(stringf("%s$holes", module->name.c_str())); - log_assert(holes_module); - - 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())); + if (holes_module) { + 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); + } 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); + ++it; } - else - ++it; - } - for (auto &conn : holes_module->connections_) { - auto it = replace.find(conn); - if (it != replace.end()) - conn = it->second; + for (auto &conn : holes_module->connections_) { + auto it = replace.find(conn); + if (it != replace.end()) + conn = it->second; + } } } -- cgit v1.2.3 From dacdc6cc941015aff45d1fde4d5365ab5e36e883 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Dec 2019 22:59:14 -0800 Subject: Remove abc9 -clk option --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 9e1318700..f44e3df06 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -150,7 +150,7 @@ struct Abc9Pass : public ScriptPass std::string arg = args[argidx]; if ((arg == "-exe" || arg == "-script" || arg == "-D" || /* arg == "-S" || */ arg == "-lut" || arg == "-luts" || - arg == "-clk" || arg == "-box" || arg == "-W") && + arg == "-box" || arg == "-W") && argidx+1 < args.size()) { map_cmd << " " << arg << " " << args[++argidx]; continue; -- 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(-) 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(-) 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(-) 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 789211d9b3a6892c72d22a09bf2299075337f9f9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 11:13:50 -0800 Subject: Fix incorrect $__ABC9_ASYNC[01] box --- techlibs/xilinx/abc9_map.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 2cabe57d7..a3f9e311e 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -186,7 +186,7 @@ module FDCE (output Q, input C, CE, D, CLR); // $__ABC9_ASYNC1 below ); // Since this is an async flop, async behaviour is dealt with here - $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); + $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); end else begin assign Q = QQ; @@ -204,7 +204,7 @@ module FDCE (output Q, input C, CE, D, CLR); // $__ABC9_ASYNC0 below ); // Since this is an async flop, async behaviour is dealt with here - $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); + $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); end endgenerate $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); -- cgit v1.2.3 From b4663a987bc1bac3aa4cccab99dc191825902205 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 11:14:11 -0800 Subject: Fix attributes on $__ABC9_ASYNC[01] whitebox --- techlibs/xilinx/abc9_model.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/abc9_model.v b/techlibs/xilinx/abc9_model.v index c793396a4..11250123d 100644 --- a/techlibs/xilinx/abc9_model.v +++ b/techlibs/xilinx/abc9_model.v @@ -34,13 +34,13 @@ module \$__ABC9_FF_ (input D, output Q); endmodule // Box to emulate async behaviour of FDC* -(* abc_box_id = 1000 *) +(* abc9_box_id = 1000, lib_whitebox *) module \$__ABC9_ASYNC0 (input A, S, output Y); assign Y = S ? 1'b0 : A; endmodule // Box to emulate async behaviour of FDP* -(* abc_box_id = 1001 *) +(* abc9_box_id = 1001, lib_whitebox *) module \$__ABC9_ASYNC1 (input A, S, output Y); assign Y = S ? 1'b0 : A; endmodule -- cgit v1.2.3 From 4cdba00e25d892b90c0ee48716c17dec60e472db Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 15:24:02 -0800 Subject: FDCE ports to be alphabetical --- techlibs/xilinx/cells_sim.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 4d20e1d2c..982ccad72 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -405,10 +405,10 @@ module FDCE ( (* invertible_pin = "IS_C_INVERTED" *) input C, input CE, - (* invertible_pin = "IS_D_INVERTED" *) - input D, (* invertible_pin = "IS_CLR_INVERTED" *) - input CLR + input CLR, + (* invertible_pin = "IS_D_INVERTED" *) + input D ); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; -- cgit v1.2.3 From 6b825c719b5bf6f63d3397cfadf8293b5d14dde6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 15:25:46 -0800 Subject: Update abc9_xc7.box comments --- techlibs/xilinx/abc9_xc7.box | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index 16606d14e..67523124a 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -1,8 +1,9 @@ # Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf -# NB: Inputs/Outputs must be ordered alphabetically -# (with exceptions for carry in/out) +# NB: Box inputs/outputs must each be in the same order +# as their corresponding module definition +# (with exceptions detailed below) # Average across F7[AB]MUX # Inputs: I0 I1 S0 @@ -15,7 +16,7 @@ MUXF7 1 1 3 1 MUXF8 2 1 3 1 104 94 273 -# Box containing MUXF7.[AB] + MUXF8, +# Box containing MUXF7.[AB] + MUXF8 # Necessary to make these an atomic unit so that # ABC cannot optimise just one of the MUXF7 away # and expect to save on its delay @@ -27,8 +28,8 @@ $__MUXF78 3 1 6 1 # CARRY4 + CARRY4_[ABCD]X # Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI # Outputs: O0 O1 O2 O3 CO0 CO1 CO2 CO3 -# (NB: carry chain input/output must be last -# input/output and the entire bus has been +# (Exception: carry chain input/output must be the +# last input and output and the entire bus has been # moved there overriding the otherwise # alphabetical ordering) CARRY4 4 1 10 8 @@ -53,55 +54,54 @@ $__ABC9_ASYNC0 1000 1 2 1 $__ABC9_ASYNC1 1001 1 2 1 0 764 -# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L237-L251 -# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L265-L277 +# Flop boxes: +# * Max delays from https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L237-L251 +# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L265-L277 +# * Exception: $abc9_currQ is a special input (located last) necessary for clock-enable functionality -# NB: Inputs/Outputs must be ordered alphabetically -# (with exception for \$currQ) - -# Inputs: C CE D R \$currQ +# Inputs: C CE D R $abc9_currQ # Outputs: Q FDRE 1100 1 5 1 #0 109 -46 404 0 0 109 0 404 0 # Clamp -46ps Tsu -# Inputs: C CE D R \$currQ +# Inputs: C CE D R $abc9_currQ # Outputs: Q FDRE_1 1101 1 5 1 #0 109 0 -46 404 0 109 0 0 404 # Clamp -46ps Tsu -# Inputs: C CE CLR D \$currQ +# Inputs: C CE CLR D $abc9_currQ # Outputs: Q FDCE 1102 1 5 1 #0 109 764 -46 0 0 109 764 0 0 # Clamp -46ps Tsu -# Inputs: C CE CLR D \$currQ +# Inputs: C CE CLR D $abc9_currQ # Outputs: Q FDCE_1 1103 1 5 1 #0 109 764 -46 0 0 109 764 0 0 # Clamp -46ps Tsu -# Inputs: C CE D PRE \$currQ +# Inputs: C CE D PRE $abc9_currQ # Outputs: Q FDPE 1104 1 5 1 #0 109 -46 764 0 0 109 0 764 0 # Clamp -46ps Tsu -# Inputs: C CE D PRE \$currQ +# Inputs: C CE D PRE $abc9_currQ # Outputs: Q FDPE_1 1105 1 5 1 #0 109 -46 764 0 0 109 0 764 0 # Clamp -46ps Tsu -# Inputs: C CE D S \$currQ +# Inputs: C CE D S $abc9_currQ # Outputs: Q FDSE 1106 1 5 1 #0 109 -46 446 0 0 109 0 446 0 # Clamp -46ps Tsu -# Inputs: C CE D S \$currQ +# Inputs: C CE D S $abc9_currQ # Outputs: Q FDSE_1 1107 1 5 1 #0 109 -46 446 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 ++++++++++++++++++++++++++++-------------------- passes/techmap/abc9.cc | 22 -------------------- 2 files changed, 32 insertions(+), 44 deletions(-) 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++; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index b63a1aa6c..1ae1637bd 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1003,28 +1003,6 @@ struct Abc9Pass : public Pass { log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); if (!carry_in && carry_out) log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); - // Make carry_in the last PI, and carry_out the last PO - // since ABC requires it this way - auto &ports = m->ports; - for (auto it = ports.begin(); it != ports.end(); ) { - RTLIL::Wire* w = m->wire(*it); - log_assert(w); - if (w == carry_in || w == carry_out) { - it = ports.erase(it); - continue; - } - if (w->port_id > carry_in->port_id) - --w->port_id; - if (w->port_id > carry_out->port_id) - --w->port_id; - log_assert(w->port_input || w->port_output); - log_assert(ports[w->port_id-1] == w->name); - ++it; - } - ports.push_back(carry_in->name); - carry_in->port_id = ports.size(); - ports.push_back(carry_out->name); - carry_out->port_id = ports.size(); } } -- cgit v1.2.3 From ccc0a740d254e6895b49037681bc484d6572342d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 16:16:05 -0800 Subject: Add some abc9 dff tests --- tests/arch/xilinx/abc9_dff.ys | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tests/arch/xilinx/abc9_dff.ys diff --git a/tests/arch/xilinx/abc9_dff.ys b/tests/arch/xilinx/abc9_dff.ys new file mode 100644 index 000000000..6611b4f18 --- /dev/null +++ b/tests/arch/xilinx/abc9_dff.ys @@ -0,0 +1,55 @@ +read_verilog < Date: Tue, 31 Dec 2019 16:50:22 -0800 Subject: parse_xaiger to reorder ports too --- frontends/aiger/aigerparse.cc | 67 +++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 9cb05dfb3..3d00aee10 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -722,6 +722,7 @@ void AigerReader::post_process() { pool seen_boxes; pool flops; + dict> box_ports; unsigned ci_count = 0, co_count = 0, flop_count = 0; for (auto cell : boxes) { RTLIL::Module* box_module = design->module(cell->type); @@ -734,51 +735,35 @@ void AigerReader::post_process() flops.insert(cell->type); is_flop = true; } - auto it = box_module->attributes.find("\\abc9_carry"); - if (it != box_module->attributes.end()) { - RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; - auto carry_in_out = it->second.decode_string(); - auto pos = carry_in_out.find(','); - if (pos == std::string::npos) - log_error("'abc9_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); - auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); - carry_in = box_module->wire(carry_in_name); - if (!carry_in || !carry_in->port_input) - log_error("'abc9_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); - - auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); - carry_out = box_module->wire(carry_out_name); - if (!carry_out || !carry_out->port_output) - log_error("'abc9_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); - - auto &ports = box_module->ports; - for (auto jt = ports.begin(); jt != ports.end(); ) { - RTLIL::Wire* w = box_module->wire(*jt); - log_assert(w); - if (w == carry_in || w == carry_out) { - jt = ports.erase(jt); - continue; - } - if (w->port_id > carry_in->port_id) - --w->port_id; - if (w->port_id > carry_out->port_id) - --w->port_id; - log_assert(w->port_input || w->port_output); - log_assert(ports[w->port_id-1] == w->name); - ++jt; - } - ports.push_back(carry_in->name); - carry_in->port_id = ports.size(); - ports.push_back(carry_out->name); - carry_out->port_id = ports.size(); - } } else is_flop = flops.count(cell->type); - // NB: Assume box_module->ports are sorted alphabetically - // (as RTLIL::Module::fixup_ports() would do) - for (auto port_name : box_module->ports) { + 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); + } + } + + for (auto port_name : box_ports.at(cell->type)) { RTLIL::Wire* port = box_module->wire(port_name); log_assert(port); RTLIL::SigSpec rhs; -- 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 ++++++++++++-- frontends/aiger/aigerparse.cc | 36 +++++++++++++++++---------------- frontends/aiger/aigerparse.h | 2 +- passes/techmap/abc9.cc | 47 ++++--------------------------------------- 4 files changed, 37 insertions(+), 63 deletions(-) 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); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 3d00aee10..f030933ec 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -340,7 +340,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera return wire; } -void AigerReader::parse_xaiger(const dict &box_lookup) +void AigerReader::parse_xaiger() { std::string header; f >> header; @@ -382,6 +382,21 @@ void AigerReader::parse_xaiger(const dict &box_lookup) if (f.peek() == '\n') f.get(); + dict box_lookup; + for (auto m : design->modules()) { + auto it = m->attributes.find(ID(abc9_box_id)); + if (it == m->attributes.end()) + continue; + if (m->name.begins_with("$paramod")) + continue; + auto id = it->second.as_int(); + auto r = box_lookup.insert(std::make_pair(id, m->name)); + if (!r.second) + log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", + log_id(m), id, log_id(r.first->second)); + log_assert(r.second); + } + // Parse footer (symbol table, comments, etc.) std::string s; for (int c = f.get(); c != EOF; c = f.get()) { @@ -456,7 +471,7 @@ void AigerReader::parse_xaiger(const dict &box_lookup) uint32_t boxUniqueId = parse_xaiger_literal(f); log_assert(boxUniqueId > 0); uint32_t oldBoxNum = parse_xaiger_literal(f); - RTLIL::Cell* cell = module->addCell(stringf("$__box%u", oldBoxNum), box_lookup.at(boxUniqueId)); + RTLIL::Cell* cell = module->addCell(stringf("$box%u", oldBoxNum), box_lookup.at(boxUniqueId)); boxes.emplace_back(cell); } } @@ -720,25 +735,12 @@ void AigerReader::parse_aiger_binary() void AigerReader::post_process() { - pool seen_boxes; - pool flops; dict> box_ports; unsigned ci_count = 0, co_count = 0, flop_count = 0; for (auto cell : boxes) { RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); - bool is_flop = false; - if (seen_boxes.insert(cell->type).second) { - if (box_module->attributes.count("\\abc9_flop")) { - log_assert(flop_count < flopNum); - flops.insert(cell->type); - is_flop = true; - } - } - else - is_flop = flops.count(cell->type); - auto r = box_ports.insert(cell->type); if (r.second) { // Make carry in the last PI, and carry out the last PO @@ -788,7 +790,7 @@ void AigerReader::post_process() cell->setPort(port_name, rhs); } - if (is_flop) { + if (box_module->attributes.count("\\abc9_flop")) { log_assert(co_count < outputs.size()); Wire *wire = outputs[co_count++]; log_assert(wire); @@ -900,7 +902,7 @@ void AigerReader::post_process() wire->attributes["\\init"] = init; } else if (type == "box") { - RTLIL::Cell* cell = module->cell(stringf("$__box%d", variable)); + RTLIL::Cell* cell = module->cell(stringf("$box%d", variable)); if (cell) { // ABC could have optimised this box away module->rename(cell, escaped_s); for (const auto &i : cell->connections()) { diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 583c9d0f9..de3c3efbc 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -47,7 +47,7 @@ struct AigerReader AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports); void parse_aiger(); - void parse_xaiger(const dict &box_lookup); + void parse_xaiger(); void parse_aiger_ascii(); void parse_aiger_binary(); void post_process(); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 1ae1637bd..3c53a5223 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -251,7 +251,7 @@ struct abc9_output_filter void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file, bool cleanup, vector lut_costs, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, const std::vector &/*cells*/, bool show_tempdir, std::string box_file, std::string lut_file, - std::string wire_delay, const dict &box_lookup, bool nomfs + std::string wire_delay, bool nomfs ) { map_autoidx = autoidx++; @@ -348,7 +348,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip log_assert(!design->module(ID($__abc9__))); { AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); - reader.parse_xaiger(box_lookup); + reader.parse_xaiger(); } ifs.close(); Pass::call_on_module(design, design->module(ID($__abc9__)), stringf("write_verilog -noexpr -norename -selected")); @@ -400,7 +400,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip log_assert(!design->module(ID($__abc9__))); AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); - reader.parse_xaiger(box_lookup); + reader.parse_xaiger(); ifs.close(); #if 0 @@ -967,45 +967,6 @@ struct Abc9Pass : public Pass { if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+') box_file = std::string(pwd) + "/" + box_file; - dict box_lookup; - for (auto m : design->modules()) { - auto it = m->attributes.find(ID(abc9_box_id)); - if (it == m->attributes.end()) - continue; - if (m->name.begins_with("$paramod")) - continue; - auto id = it->second.as_int(); - auto r = box_lookup.insert(std::make_pair(id, m->name)); - if (!r.second) - log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - log_id(m), id, log_id(r.first->second)); - log_assert(r.second); - - RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; - for (auto p : m->ports) { - auto w = m->wire(p); - log_assert(w); - if (w->attributes.count(ID(abc9_carry))) { - if (w->port_input) { - if (carry_in) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); - carry_in = w; - } - else if (w->port_output) { - if (carry_out) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); - carry_out = w; - } - } - } - if (carry_in || carry_out) { - if (carry_in && !carry_out) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); - if (!carry_in && carry_out) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); - } - } - SigMap assign_map; CellTypes ct(design); for (auto module : design->selected_modules()) @@ -1056,7 +1017,7 @@ struct Abc9Pass : public Pass { design->selected_active_module = module->name.str(); abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, delay_target, lutin_shared, fast_mode, all_cells, show_tempdir, - box_file, lut_file, wire_delay, box_lookup, nomfs); + box_file, lut_file, wire_delay, nomfs); design->selected_active_module.clear(); } -- cgit v1.2.3 From b2046a2114add3d24c0affd9d885b7ee320dba27 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 18:29:29 -0800 Subject: Cleanup ecp5 boxes --- techlibs/ecp5/abc9_5g.box | 41 +++++++++++++++++------------------------ techlibs/ecp5/abc9_map.v | 19 +++++++++++-------- techlibs/ecp5/abc9_model.v | 2 +- techlibs/ecp5/abc9_unmap.v | 4 ++-- 4 files changed, 31 insertions(+), 35 deletions(-) diff --git a/techlibs/ecp5/abc9_5g.box b/techlibs/ecp5/abc9_5g.box index 2bc945a54..5c7f52ab1 100644 --- a/techlibs/ecp5/abc9_5g.box +++ b/techlibs/ecp5/abc9_5g.box @@ -1,43 +1,36 @@ -# NB: Inputs/Outputs must be ordered alphabetically -# (with exceptions for carry in/out) +# NB: Box inputs/outputs must each be in the same order +# as their corresponding module definition +# (with exceptions detailed below) # Box 1 : CCU2C (2xCARRY + 2xLUT4) -# Outputs: S0, S1, COUT -# (NB: carry chain input/output must be last -# input/output and bus has been moved -# there overriding the otherwise +# (Exception: carry chain input/output must be the +# last input and output and the entire bus has been +# moved there overriding the otherwise # alphabetical ordering) # name ID w/b ins outs CCU2C 1 1 9 3 - -#A0 A1 B0 B1 C0 C1 D0 D1 CIN -379 - 379 - 275 - 141 - 257 -630 379 630 379 526 275 392 141 273 -516 516 516 516 412 412 278 278 43 +#A0 B0 C0 D0 A1 B1 C1 D1 CIN +379 379 275 141 - - - - 257 # S0 +630 630 526 392 379 379 275 141 273 # S1 +516 516 412 278 516 516 412 278 43 # COUT # Box 2 : TRELLIS_DPR16X4_COMB (16x4 dist ram) -# Outputs: DO0, DO1, DO2, DO3 # name ID w/b ins outs $__ABC9_DPR16X4_COMB 2 0 8 4 - -#A0 A1 A2 A3 RAD0 RAD1 RAD2 RAD3 -0 0 0 0 141 379 275 379 -0 0 0 0 141 379 275 379 -0 0 0 0 141 379 275 379 -0 0 0 0 141 379 275 379 +#$D0 $D1 $D2 $D3 RAD0 RAD1 RAD2 RAD3 +0 0 0 0 141 379 275 379 # DO0 +0 0 0 0 141 379 275 379 # DO1 +0 0 0 0 141 379 275 379 # DO2 +0 0 0 0 141 379 275 379 # DO3 # Box 3 : PFUMX (MUX2) -# Outputs: Z # name ID w/b ins outs PFUMX 3 1 3 1 - #ALUT BLUT C0 -98 98 151 +98 98 151 # Z # Box 4 : L6MUX21 (MUX2) -# Outputs: Z # name ID w/b ins outs L6MUX21 4 1 3 1 - #D0 D1 SD -140 141 148 +140 141 148 # Z diff --git a/techlibs/ecp5/abc9_map.v b/techlibs/ecp5/abc9_map.v index d8d70f9f6..113a35b91 100644 --- a/techlibs/ecp5/abc9_map.v +++ b/techlibs/ecp5/abc9_map.v @@ -1,24 +1,27 @@ // --------------------------------------- +// Attach a (combinatorial) black-box onto the output +// of this LUTRAM primitive to capture its +// asynchronous read behaviour module TRELLIS_DPR16X4 ( - input [3:0] DI, - input [3:0] WAD, - input WRE, - input WCK, - input [3:0] RAD, + (* techmap_autopurge *) input [3:0] DI, + (* techmap_autopurge *) input [3:0] WAD, + (* techmap_autopurge *) input WRE, + (* techmap_autopurge *) input WCK, + (* techmap_autopurge *) input [3:0] RAD, output [3:0] DO ); parameter WCKMUX = "WCK"; parameter WREMUX = "WRE"; parameter [63:0] INITVAL = 64'h0000000000000000; - wire [3:0] \$DO ; + wire [3:0] $DO; TRELLIS_DPR16X4 #( .WCKMUX(WCKMUX), .WREMUX(WREMUX), .INITVAL(INITVAL) ) _TECHMAP_REPLACE_ ( .DI(DI), .WAD(WAD), .WRE(WRE), .WCK(WCK), - .RAD(RAD), .DO(\$DO ) + .RAD(RAD), .DO($DO) ); - \$__ABC9_DPR16X4_COMB do (.A(\$DO ), .S(RAD), .Y(DO)); + $__ABC9_DPR16X4_COMB do (.$DO($DO), .RAD(RAD), .DO(DO)); endmodule diff --git a/techlibs/ecp5/abc9_model.v b/techlibs/ecp5/abc9_model.v index 1dc8b5617..81e5cd070 100644 --- a/techlibs/ecp5/abc9_model.v +++ b/techlibs/ecp5/abc9_model.v @@ -1,5 +1,5 @@ // --------------------------------------- (* abc9_box_id=2 *) -module \$__ABC9_DPR16X4_COMB (input [3:0] A, S, output [3:0] Y); +module \$__ABC9_DPR16X4_COMB (input [3:0] $DO, RAD, output [3:0] DO); endmodule diff --git a/techlibs/ecp5/abc9_unmap.v b/techlibs/ecp5/abc9_unmap.v index 9ae143c46..cbdffdaf1 100644 --- a/techlibs/ecp5/abc9_unmap.v +++ b/techlibs/ecp5/abc9_unmap.v @@ -1,5 +1,5 @@ // --------------------------------------- -module \$__ABC9_DPR16X4_COMB (input [3:0] A, S, output [3:0] Y); - assign Y = A; +module \$__ABC9_DPR16X4_COMB (input [3:0] $DO, RAD, output [3:0] DO); + assign DO = $DO; endmodule -- cgit v1.2.3 From 2358320f5168edd691882bba0f759d82308291d6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 18:29:37 -0800 Subject: Cleanup ice40 boxes --- techlibs/ice40/abc9_hx.box | 24 ++++++++++++++---------- techlibs/ice40/abc9_lp.box | 24 ++++++++++++++---------- techlibs/ice40/abc9_u.box | 25 +++++++++++++++---------- 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/techlibs/ice40/abc9_hx.box b/techlibs/ice40/abc9_hx.box index 3ea70bc91..31e743669 100644 --- a/techlibs/ice40/abc9_hx.box +++ b/techlibs/ice40/abc9_hx.box @@ -1,13 +1,17 @@ # From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt -# NB: Inputs/Outputs must be ordered alphabetically -# (with exceptions for carry in/out) +# NB: Box inputs/outputs must each be in the same order +# as their corresponding module definition +# (with exceptions detailed below) -# Inputs: A B I0 I3 CI -# Outputs: O CO -# (NB: carry chain input/output must be last -# input/output and have been moved there -# overriding the alphabetical ordering) -$__ICE40_CARRY_WRAPPER 1 1 5 2 -400 379 449 316 316 -259 231 - - 126 +# Box 1 : $__ICE40_CARRY_WRAPPER (private cell used to preserve +# SB_LUT4+SB_CARRY) +# (Exception: carry chain input/output must be the +# last input and output and the entire bus has been +# moved there overriding the otherwise +# alphabetical ordering) +# name ID w/b ins outs +$__ICE40_CARRY_WRAPPER 1 1 5 2 +#A B I0 I3 CI +400 379 449 316 316 # O +259 231 - - 126 # CO diff --git a/techlibs/ice40/abc9_lp.box b/techlibs/ice40/abc9_lp.box index 473e92fe9..71986a67b 100644 --- a/techlibs/ice40/abc9_lp.box +++ b/techlibs/ice40/abc9_lp.box @@ -1,13 +1,17 @@ # From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt -# NB: Inputs/Outputs must be ordered alphabetically -# (with exceptions for carry in/out) +# NB: Box inputs/outputs must each be in the same order +# as their corresponding module definition +# (with exceptions detailed below) -# Inputs: A B I0 I3 CI -# Outputs: O CO -# (NB: carry chain input/output must be last -# input/output and have been moved there -# overriding the alphabetical ordering) -$__ICE40_CARRY_WRAPPER 1 1 5 2 -589 558 661 465 465 -675 609 - - 186 +# Box 1 : $__ICE40_CARRY_WRAPPER (private cell used to preserve +# SB_LUT4+SB_CARRY) +# (Exception: carry chain input/output must be the +# last input and output and the entire bus has been +# moved there overriding the otherwise +# alphabetical ordering) +# name ID w/b ins outs +$__ICE40_CARRY_WRAPPER 1 1 5 2 +#A B I0 I3 CI +589 558 661 465 465 # O +675 609 - - 186 # CO diff --git a/techlibs/ice40/abc9_u.box b/techlibs/ice40/abc9_u.box index f00e247b8..48a51463e 100644 --- a/techlibs/ice40/abc9_u.box +++ b/techlibs/ice40/abc9_u.box @@ -1,13 +1,18 @@ # From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt -# NB: Inputs/Outputs must be ordered alphabetically -# (with exceptions for carry in/out) +# NB: Box inputs/outputs must each be in the same order +# as their corresponding module definition +# (with exceptions detailed below) -# Inputs: A B I0 I3 CI -# Outputs: O CO -# (NB: carry chain input/output must be last -# input/output and have been moved there -# overriding the alphabetical ordering) -$__ICE40_CARRY_WRAPPER 1 1 5 2 -1231 1205 1285 874 874 -675 609 - - 278 +# Box 1 : $__ICE40_CARRY_WRAPPER (private cell used to preserve +# SB_LUT4+SB_CARRY) +# Outputs: O, CO +# (Exception: carry chain input/output must be the +# last input and output and the entire bus has been +# moved there overriding the otherwise +# alphabetical ordering) +# name ID w/b ins outs +$__ICE40_CARRY_WRAPPER 1 1 5 2 +#A B I0 I3 CI +1231 1205 1285 874 874 # O +675 609 - - 278 # CO -- cgit v1.2.3 From 35c659be74396db7824bc98428137dc9a5ac1d16 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 18:29:44 -0800 Subject: Cleanup xilinx boxes --- techlibs/xilinx/abc9_map.v | 3 + techlibs/xilinx/abc9_xc7.box | 813 ++++++++++++++++++++++--------------------- 2 files changed, 425 insertions(+), 391 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index a3f9e311e..4ab8e1564 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -462,6 +462,9 @@ module FDSE_1 (output Q, input C, CE, D, S); `endif endmodule +// Attach a (combinatorial) black-box onto the output +// of thes LUTRAM primitives to capture their +// asynchronous read behaviour module RAM32X1D ( output DPO, SPO, (* techmap_autopurge *) input D, diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index 67523124a..302487041 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -5,126 +5,138 @@ # as their corresponding module definition # (with exceptions detailed below) -# Average across F7[AB]MUX -# Inputs: I0 I1 S0 -# Outputs: O -MUXF7 1 1 3 1 -204 208 286 +# Box 1 : MUXF7 +# Max delays from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L451-L453 +# name ID w/b ins outs +MUXF7 1 1 3 1 +#I0 I1 S0 +204 208 286 # O -# Inputs: I0 I1 S0 -# Outputs: O -MUXF8 2 1 3 1 -104 94 273 +# Box 2 : MUXF8 +# Max delays from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L462-L464 +# name ID w/b ins outs +MUXF8 2 1 3 1 +#I0 I1 S0 +104 94 273 # O -# Box containing MUXF7.[AB] + MUXF8 -# Necessary to make these an atomic unit so that -# ABC cannot optimise just one of the MUXF7 away -# and expect to save on its delay -# Inputs: I0 I1 I2 I3 S0 S1 -# Outputs: O -$__MUXF78 3 1 6 1 -294 297 311 317 390 273 +# Box 3 : $__MUXF78 +# (private cell used to preserve 2xMUXF7 + 1xMUXF8 +# an atomic unit so that ABC cannot optimise just +# one of the MUXF7 away and expect to save on its +# delay, since MUXF8 is only reachable through an +# MUXF7) +# name ID w/b ins outs +$__MUXF78 3 1 6 1 +#I0 I1 I2 I3 S0 S1 +294 297 311 317 390 273 # O -# CARRY4 + CARRY4_[ABCD]X -# Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI -# Outputs: O0 O1 O2 O3 CO0 CO1 CO2 CO3 +# Box 4 : CARRY4 + CARRY4_[ABCD]X # (Exception: carry chain input/output must be the # last input and output and the entire bus has been # moved there overriding the otherwise # alphabetical ordering) -CARRY4 4 1 10 8 -482 - - - - 223 - - - 222 -598 407 - - - 400 205 - - 334 -584 556 537 - - 523 558 226 - 239 -642 615 596 438 - 582 618 330 227 313 -536 379 - - - 340 - - - 271 -494 465 445 - - 433 469 - - 157 -592 540 520 356 - 512 548 292 - 228 -580 526 507 398 385 508 528 378 380 114 +# Max delays from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L11-L46 +# name ID w/b ins outs +CARRY4 4 1 10 8 +#CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI +482 - - - - 223 - - - 222 # O0 +598 407 - - - 400 205 - - 334 # O1 +584 556 537 - - 523 558 226 - 239 # O2 +642 615 596 438 - 582 618 330 227 313 # O3 +536 379 - - - 340 - - - 271 # CO0 +494 465 445 - - 433 469 - - 157 # CO1 +592 540 520 356 - 512 548 292 - 228 # CO2 +580 526 507 398 385 508 528 378 380 114 # CO3 -# Box to emulate async behaviour of FDC* -# Inputs: A S -# Outputs: Y -$__ABC9_ASYNC0 1000 1 2 1 -0 764 +# Box 1000 : $__ABC9_ASYNC0 +# (private cell to emulate async behaviour of FDC*) +# name ID w/b ins outs +$__ABC9_ASYNC0 1000 1 2 1 +#A S +0 764 # Y -# Box to emulate async behaviour of FDP* -# Inputs: A S -# Outputs: Y +# Box 1001 : $__ABC9_ASYNC1 +# (private cell to emulate async behaviour of FDP*) +# name ID w/b ins outs $__ABC9_ASYNC1 1001 1 2 1 -0 764 +#A S +0 764 # Y # Flop boxes: # * Max delays from https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L237-L251 # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L265-L277 # * Exception: $abc9_currQ is a special input (located last) necessary for clock-enable functionality -# Inputs: C CE D R $abc9_currQ -# Outputs: Q -FDRE 1100 1 5 1 +# Box 1100 : FDRE +# name ID w/b ins outs +FDRE 1100 1 5 1 +#C CE D R $abc9_currQ #0 109 -46 404 0 -0 109 0 404 0 # Clamp -46ps Tsu +0 109 0 404 0 # Q (-46ps Tsu clamped to 0) -# Inputs: C CE D R $abc9_currQ -# Outputs: Q -FDRE_1 1101 1 5 1 -#0 109 0 -46 404 -0 109 0 0 404 # Clamp -46ps Tsu +# Box 1101 : FDRE_1 +# name ID w/b ins outs +FDRE_1 1101 1 5 1 +#C CE D R $abc9_currQ +#0 109 -46 404 0 +0 109 0 404 0 # Q (-46ps Tsu clamped to 0) -# Inputs: C CE CLR D $abc9_currQ -# Outputs: Q -FDCE 1102 1 5 1 +# Box 1102 : FDCE +# name ID w/b ins outs +FDCE 1102 1 5 1 +#C CE CLR D $abc9_currQ #0 109 764 -46 0 -0 109 764 0 0 # Clamp -46ps Tsu +0 109 764 0 0 # Q (-46ps Tsu clamped to 0) -# Inputs: C CE CLR D $abc9_currQ -# Outputs: Q -FDCE_1 1103 1 5 1 +# Box 1103 : FDCE_1 +# name ID w/b ins outs +FDCE_1 1103 1 5 1 +#C CE CLR D $abc9_currQ #0 109 764 -46 0 -0 109 764 0 0 # Clamp -46ps Tsu +0 109 764 0 0 # Q (-46ps Tsu clamped to 0) -# Inputs: C CE D PRE $abc9_currQ -# Outputs: Q -FDPE 1104 1 5 1 +# Box 1104 : FDPE +# name ID w/b ins outs +FDPE 1104 1 5 1 +#C CE D PRE $abc9_currQ #0 109 -46 764 0 -0 109 0 764 0 # Clamp -46ps Tsu +0 109 -46 764 0 # Q (-46ps Tsu clamped to 0) -# Inputs: C CE D PRE $abc9_currQ -# Outputs: Q -FDPE_1 1105 1 5 1 +# Box 1105 : FDPE_1 +# name ID w/b ins outs +FDPE_1 1105 1 5 1 +#C CE D PRE $abc9_currQ #0 109 -46 764 0 -0 109 0 764 0 # Clamp -46ps Tsu +0 109 -46 764 0 # Q (-46ps Tsu clamped to 0) -# Inputs: C CE D S $abc9_currQ -# Outputs: Q -FDSE 1106 1 5 1 -#0 109 -46 446 0 -0 109 0 446 0 # Clamp -46ps Tsu +# Box 1106 : FDSE +# name ID w/b ins outs +FDSE 1106 1 5 1 +#C CE D R $abc9_currQ +#0 109 -46 404 0 +0 109 0 404 0 # Q (-46ps Tsu clamped to 0) -# Inputs: C CE D S $abc9_currQ -# Outputs: Q -FDSE_1 1107 1 5 1 -#0 109 -46 446 0 -0 109 0 446 0 # Clamp -46ps Tsu +# Box 1107 : FDSE_1 +# name ID w/b ins outs +FDSE_1 1107 1 5 1 +#C CE D R $abc9_currQ +#0 109 -46 404 0 +0 109 0 404 0 # Q (-46ps Tsu clamped to 0) +# Box 2000 : $__ABC9_LUT6 +# (private cell to emulate async behaviour of LUTRAMs) # SLICEM/A6LUT -# Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} -# Necessary since RAMD* and SRL* have both combinatorial (i.e. -# same-cycle read operation) and sequential (write operation -# is only committed on the next clock edge). -# To model the combinatorial path, such cells have to be split -# into comb and seq parts, with this box modelling only the former. -# Inputs: A S0 S1 S2 S3 S4 S5 -# Outputs: Y -$__ABC9_LUT6 2000 0 7 1 -0 642 631 472 407 238 127 +# name ID w/b ins outs +$__ABC9_LUT6 2000 0 7 1 +#A S0 S1 S2 S3 S4 S5 +0 642 631 472 407 238 127 # Y -# SLICEM/A6LUT + F7BMUX -# Box to emulate comb/seq behaviour of RAMD128 -# Inputs: A S0 S1 S2 S3 S4 S5 S6 -# Outputs: Y +# Box 2001 : $__ABC9_LUT6 +# (private cell to emulate async behaviour of LUITRAMs) +# name ID w/b ins outs $__ABC9_LUT7 2001 0 8 1 -0 1047 1036 877 812 643 532 478 +#A S0 S1 S2 S3 S4 S5 S6 +0 1047 1036 877 812 643 532 478 # Y # Boxes used to represent the comb/seq behaviour of DSP48E1 # With abc9_map.v responsible for disconnecting inputs to @@ -136,308 +148,323 @@ $__ABC9_LUT7 2001 0 8 1 # the mux at zero time, the combinatorial delay through # these muxes thus represents the clock-to-q delay at # P/PCOUT. -$__ABC9_DSP48E1_MULT_P_MUX 2100 0 103 48 -# A AD B C D I M P Pq -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -$__ABC9_DSP48E1_MULT_PCOUT_MUX 2101 0 103 48 -# A AD B C D I M P Pq -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -$__ABC9_DSP48E1_MULT_DPORT_P_MUX 2102 0 103 48 -# A AD B C D I M P Pq -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 103 48 -# A AD B C D I M P Pq -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -$__ABC9_DSP48E1_P_MUX 2104 0 103 48 -# A AD B C D I M P Pq -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -$__ABC9_DSP48E1_PCOUT_MUX 2105 0 103 48 -# A AD B C D I M P Pq -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -$__ABC9_DSP48E1_MULT 3000 0 263 154 +# Box 2100 : $__ABC9_DSP48E1_MULT_P_MUX +# name ID w/b ins outs +$__ABC9_DSP48E1_MULT_P_MUX 2100 0 103 48 +#A AD B C D I0 I47 M P0 P47 Pq +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 # O0 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 # O47 +# Box 2101 : $__ABC9_DSP48E1_MULT_PCOUT_MUX +# name ID w/b ins outs +$__ABC9_DSP48E1_MULT_PCOUT_MUX 2101 0 103 48 +#A AD B C D I0 I47 M P0 P47 Pq +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 # O0 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 # O47 +# Box 2102 : $__ABC9_DSP48E1_MULT_DPORT_P_MUX +# name ID w/b ins outs +$__ABC9_DSP48E1_MULT_DPORT_P_MUX 2102 0 103 48 +#A AD B C D I0 I47 M P0 P47 Pq +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 # O0 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 # O47 +# Box 2103 : $__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX +# name ID w/b ins outs +$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 103 48 +#A AD B C D I0 I47 M P0 P47 Pq +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 # O +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 # O47 +# Box 2104 : $__ABC9_DSP48E1_P_MUX +# name ID w/b ins outs +$__ABC9_DSP48E1_P_MUX 2104 0 103 48 +#A AD B C D I0 I47 M P0 P47 Pq +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 # O0 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 # O47 +# Box 2105 : $__ABC9_DSP48E1_PCOUT_MUX +# name ID w/b ins outs +$__ABC9_DSP48E1_PCOUT_MUX 2105 0 103 48 +#A AD B C D I0 I47 M P0 P47 Pq +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 # O0 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 # O47 + +# Box 3000 : $__ABC9_DSP48E1_MULT +# name ID w/b ins outs +$__ABC9_DSP48E1_MULT 3000 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - @@ -701,7 +728,9 @@ $__ABC9_DSP48E1_MULT 3000 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -$__ABC9_DSP48E1_MULT_DPORT 3001 0 263 154 +# Box 3001 : $__ABC9_DSP48E1_MULT_DPORT +# name ID w/b ins outs +$__ABC9_DSP48E1_MULT_DPORT 3001 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - @@ -965,7 +994,9 @@ $__ABC9_DSP48E1_MULT_DPORT 3001 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -$__ABC9_DSP48E1 3002 0 263 154 +# Box 3002 : $__ABC9_DSP48E1 +# name ID w/b ins outs +$__ABC9_DSP48E1 3002 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - -- cgit v1.2.3 From c082329af33cd428f53f5afbcb51fab8de545090 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 18:39:32 -0800 Subject: Call equiv_opt with -multiclock and -assert --- tests/arch/anlogic/counter.ys | 2 +- tests/arch/ecp5/counter.ys | 2 +- tests/arch/efinix/counter.ys | 2 +- tests/arch/gowin/counter.ys | 2 +- tests/arch/ice40/counter.ys | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/arch/anlogic/counter.ys b/tests/arch/anlogic/counter.ys index d363ec24e..a6eab248c 100644 --- a/tests/arch/anlogic/counter.ys +++ b/tests/arch/anlogic/counter.ys @@ -2,7 +2,7 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten -equiv_opt -map +/anlogic/cells_sim.v synth_anlogic # equivalency check +equiv_opt -assert -multiclock -map +/anlogic/cells_sim.v synth_anlogic # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/ecp5/counter.ys b/tests/arch/ecp5/counter.ys index f9f60fbff..e46001ffe 100644 --- a/tests/arch/ecp5/counter.ys +++ b/tests/arch/ecp5/counter.ys @@ -2,7 +2,7 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten -equiv_opt -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +equiv_opt -assert -multiclock -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 4 t:CCU2C diff --git a/tests/arch/efinix/counter.ys b/tests/arch/efinix/counter.ys index d20b8ae27..f8fb29a87 100644 --- a/tests/arch/efinix/counter.ys +++ b/tests/arch/efinix/counter.ys @@ -2,7 +2,7 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten -equiv_opt -map +/efinix/cells_sim.v synth_efinix # equivalency check +equiv_opt -assert -multiclock -map +/efinix/cells_sim.v synth_efinix # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/gowin/counter.ys b/tests/arch/gowin/counter.ys index 920479d44..bdbc7ee24 100644 --- a/tests/arch/gowin/counter.ys +++ b/tests/arch/gowin/counter.ys @@ -2,7 +2,7 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten -equiv_opt -map +/gowin/cells_sim.v synth_gowin # equivalency check +equiv_opt -assert -multiclock -map +/gowin/cells_sim.v synth_gowin # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/ice40/counter.ys b/tests/arch/ice40/counter.ys index f112eb97d..7bbc4f2c3 100644 --- a/tests/arch/ice40/counter.ys +++ b/tests/arch/ice40/counter.ys @@ -2,7 +2,7 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten -equiv_opt -map +/ice40/cells_sim.v synth_ice40 # equivalency check +equiv_opt -assert -multiclock -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 6 t:SB_CARRY -- cgit v1.2.3 From a59016b146e91311324bc87f9a9437d7ff31d9f2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 18:40:11 -0800 Subject: Fix warnings --- tests/arch/ice40/mul.ys | 2 +- tests/arch/ice40/rom.v | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/arch/ice40/mul.ys b/tests/arch/ice40/mul.ys index 9891b77d6..b8c3eb941 100644 --- a/tests/arch/ice40/mul.ys +++ b/tests/arch/ice40/mul.ys @@ -1,6 +1,6 @@ read_verilog ../common/mul.v hierarchy -top top -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check +equiv_opt -assert -multiclock -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:SB_MAC16 diff --git a/tests/arch/ice40/rom.v b/tests/arch/ice40/rom.v index 0a0f41f37..c4c677c1e 100644 --- a/tests/arch/ice40/rom.v +++ b/tests/arch/ice40/rom.v @@ -2,7 +2,7 @@ Example from: https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/iCEcube201701UserGuide.ashx?document_id=52071 [p. 74]. */ module top(data, addr); -output [3:0] data; +output reg [3:0] data; input [4:0] addr; always @(addr) begin case (addr) -- cgit v1.2.3 From 713484fa66da705d2a274cdea590bd4634f48d5d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 18:40:30 -0800 Subject: Do not do call equiv_opt when no sim model exists --- tests/arch/ecp5/macc.ys | 4 ++-- tests/arch/ecp5/mul.ys | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/arch/ecp5/macc.ys b/tests/arch/ecp5/macc.ys index 1863ea4d2..8da8d2f8e 100644 --- a/tests/arch/ecp5/macc.ys +++ b/tests/arch/ecp5/macc.ys @@ -3,8 +3,8 @@ hierarchy -top top proc # Blocked by issue #1358 (Missing ECP5 simulation models) #equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -equiv_opt -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +synth_ecp5 +#design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:MULT18X18D select -assert-count 4 t:CCU2C diff --git a/tests/arch/ecp5/mul.ys b/tests/arch/ecp5/mul.ys index 2105be52c..f887e9585 100644 --- a/tests/arch/ecp5/mul.ys +++ b/tests/arch/ecp5/mul.ys @@ -3,9 +3,9 @@ hierarchy -top top proc # Blocked by issue #1358 (Missing ECP5 simulation models) #equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -equiv_opt -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +synth_ecp5 -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +#design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:MULT18X18D select -assert-none t:MULT18X18D %% t:* %D -- cgit v1.2.3 From f7793a29564881245239e81326e0c7afeb15f6e9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 18:42:11 -0800 Subject: Missing character --- techlibs/ecp5/abc9_5g.box | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/abc9_5g.box b/techlibs/ecp5/abc9_5g.box index 5c7f52ab1..f153a665e 100644 --- a/techlibs/ecp5/abc9_5g.box +++ b/techlibs/ecp5/abc9_5g.box @@ -17,7 +17,7 @@ CCU2C 1 1 9 3 # Box 2 : TRELLIS_DPR16X4_COMB (16x4 dist ram) # name ID w/b ins outs $__ABC9_DPR16X4_COMB 2 0 8 4 -#$D0 $D1 $D2 $D3 RAD0 RAD1 RAD2 RAD3 +#$DO0 $DO1 $DO2 $DO3 RAD0 RAD1 RAD2 RAD3 0 0 0 0 141 379 275 379 # DO0 0 0 0 0 141 379 275 379 # DO1 0 0 0 0 141 379 275 379 # DO2 -- cgit v1.2.3 From 44d9fb0e7cee7d8986ed037429e3c9fdd1b29ba1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Dec 2019 18:47:38 -0800 Subject: Re-arrange FD order --- techlibs/xilinx/abc9_map.v | 166 +++++++++++++++++++++---------------------- techlibs/xilinx/abc9_xc7.box | 44 ++++++------ techlibs/xilinx/cells_sim.v | 154 +++++++++++++++++++-------------------- 3 files changed, 182 insertions(+), 182 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 4ab8e1564..6d93e508f 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -163,6 +163,89 @@ module FDRE_1 (output Q, input C, CE, D, R); `endif endmodule +module FDSE (output Q, input C, CE, D, S); + parameter [0:0] INIT = 1'b1; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_S_INVERTED = 1'b0; +`ifdef DFF_MODE + wire QQ, $Q; + generate if (INIT == 1'b1) begin + assign Q = ~QQ; + FDRE #( + .INIT(1'b0), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_R_INVERTED(IS_S_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) + ); + end + else begin + assign Q = QQ; + FDSE #( + .INIT(1'b0), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_S_INVERTED(IS_S_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q($Q), .C(C), .CE(CE), .S(S) + ); + end endgenerate + $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); + + // Special signals + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; +`else + (* abc9_keep *) + FDSE #( + .INIT(INIT), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_S_INVERTED(IS_S_INVERTED) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .S(S) + ); +`endif +endmodule +module FDSE_1 (output Q, input C, CE, D, S); + parameter [0:0] INIT = 1'b1; +`ifdef DFF_MODE + wire QQ, $Q; + generate if (INIT == 1'b1) begin + assign Q = ~QQ; + FDRE_1 #( + .INIT(1'b0) + ) _TECHMAP_REPLACE_ ( + .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) + ); + end + else begin + assign Q = QQ; + FDSE_1 #( + .INIT(1'b0) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q($Q), .C(C), .CE(CE), .S(S) + ); + end endgenerate + $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); + + // Special signals + wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; +`else + (* abc9_keep *) + FDSE_1 #( + .INIT(INIT) + ) _TECHMAP_REPLACE_ ( + .D(D), .Q(Q), .C(C), .CE(CE), .S(S) + ); +`endif +endmodule + module FDCE (output Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; @@ -379,89 +462,6 @@ module FDPE_1 (output Q, input C, CE, D, PRE); `endif endmodule -module FDSE (output Q, input C, CE, D, S); - parameter [0:0] INIT = 1'b1; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_S_INVERTED = 1'b0; -`ifdef DFF_MODE - wire QQ, $Q; - generate if (INIT == 1'b1) begin - assign Q = ~QQ; - FDRE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_R_INVERTED(IS_S_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) - ); - end - else begin - assign Q = QQ; - FDSE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_S_INVERTED(IS_S_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q($Q), .C(C), .CE(CE), .S(S) - ); - end endgenerate - $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); - - // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; - wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; -`else - (* abc9_keep *) - FDSE #( - .INIT(INIT), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_S_INVERTED(IS_S_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .S(S) - ); -`endif -endmodule -module FDSE_1 (output Q, input C, CE, D, S); - parameter [0:0] INIT = 1'b1; -`ifdef DFF_MODE - wire QQ, $Q; - generate if (INIT == 1'b1) begin - assign Q = ~QQ; - FDRE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) - ); - end - else begin - assign Q = QQ; - FDSE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q($Q), .C(C), .CE(CE), .S(S) - ); - end endgenerate - $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); - - // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; - wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; -`else - (* abc9_keep *) - FDSE_1 #( - .INIT(INIT) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .S(S) - ); -`endif -endmodule - // Attach a (combinatorial) black-box onto the output // of thes LUTRAM primitives to capture their // asynchronous read behaviour diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index 302487041..43c39544e 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -81,48 +81,48 @@ FDRE_1 1101 1 5 1 #0 109 -46 404 0 0 109 0 404 0 # Q (-46ps Tsu clamped to 0) -# Box 1102 : FDCE +# Box 1102 : FDSE # name ID w/b ins outs -FDCE 1102 1 5 1 +FDSE 1102 1 5 1 +#C CE D R $abc9_currQ +#0 109 -46 404 0 +0 109 0 404 0 # Q (-46ps Tsu clamped to 0) + +# Box 1103 : FDSE_1 +# name ID w/b ins outs +FDSE_1 1103 1 5 1 +#C CE D R $abc9_currQ +#0 109 -46 404 0 +0 109 0 404 0 # Q (-46ps Tsu clamped to 0) + +# Box 1104 : FDCE +# name ID w/b ins outs +FDCE 1104 1 5 1 #C CE CLR D $abc9_currQ #0 109 764 -46 0 0 109 764 0 0 # Q (-46ps Tsu clamped to 0) -# Box 1103 : FDCE_1 +# Box 1105 : FDCE_1 # name ID w/b ins outs -FDCE_1 1103 1 5 1 +FDCE_1 1105 1 5 1 #C CE CLR D $abc9_currQ #0 109 764 -46 0 0 109 764 0 0 # Q (-46ps Tsu clamped to 0) -# Box 1104 : FDPE +# Box 1106 : FDPE # name ID w/b ins outs -FDPE 1104 1 5 1 +FDPE 1106 1 5 1 #C CE D PRE $abc9_currQ #0 109 -46 764 0 0 109 -46 764 0 # Q (-46ps Tsu clamped to 0) -# Box 1105 : FDPE_1 +# Box 1107 : FDPE_1 # name ID w/b ins outs -FDPE_1 1105 1 5 1 +FDPE_1 1107 1 5 1 #C CE D PRE $abc9_currQ #0 109 -46 764 0 0 109 -46 764 0 # Q (-46ps Tsu clamped to 0) -# Box 1106 : FDSE -# name ID w/b ins outs -FDSE 1106 1 5 1 -#C CE D R $abc9_currQ -#0 109 -46 404 0 -0 109 0 404 0 # Q (-46ps Tsu clamped to 0) - -# Box 1107 : FDSE_1 -# name ID w/b ins outs -FDSE_1 1107 1 5 1 -#C CE D R $abc9_currQ -#0 109 -46 404 0 -0 109 0 404 0 # Q (-46ps Tsu clamped to 0) - # Box 2000 : $__ABC9_LUT6 # (private cell to emulate async behaviour of LUTRAMs) # SLICEM/A6LUT diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 982ccad72..c22bcdc27 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -362,6 +362,43 @@ module FDRE_1 ( always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; endmodule +(* abc9_box_id=1102, lib_whitebox, abc9_flop *) +module FDSE ( + (* abc9_arrival=303 *) + output reg Q, + (* clkbuf_sink *) + (* invertible_pin = "IS_C_INVERTED" *) + input C, + input CE, + (* invertible_pin = "IS_D_INVERTED" *) + input D, + (* invertible_pin = "IS_S_INVERTED" *) + input S +); + parameter [0:0] INIT = 1'b1; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_S_INVERTED = 1'b0; + initial Q <= INIT; + generate case (|IS_C_INVERTED) + 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate +endmodule + +(* abc9_box_id=1103, lib_whitebox, abc9_flop *) +module FDSE_1 ( + (* abc9_arrival=303 *) + output reg Q, + (* clkbuf_sink *) + input C, + input CE, D, S +); + parameter [0:0] INIT = 1'b1; + initial Q <= INIT; + always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; +endmodule + module FDRSE ( output reg Q, (* clkbuf_sink *) @@ -397,7 +434,7 @@ module FDRSE ( Q <= d; endmodule -(* abc9_box_id=1102, lib_whitebox, abc9_flop *) +(* abc9_box_id=1104, lib_whitebox, abc9_flop *) module FDCE ( (* abc9_arrival=303 *) output reg Q, @@ -423,7 +460,7 @@ module FDCE ( endcase endgenerate endmodule -(* abc9_box_id=1103, lib_whitebox, abc9_flop *) +(* abc9_box_id=1105, lib_whitebox, abc9_flop *) module FDCE_1 ( (* abc9_arrival=303 *) output reg Q, @@ -436,52 +473,7 @@ module FDCE_1 ( always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; endmodule -module FDCPE ( - output wire Q, - (* clkbuf_sink *) - (* invertible_pin = "IS_C_INVERTED" *) - input C, - input CE, - (* invertible_pin = "IS_CLR_INVERTED" *) - input CLR, - input D, - (* invertible_pin = "IS_PRE_INVERTED" *) - input PRE -); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_CLR_INVERTED = 1'b0; - parameter [0:0] IS_PRE_INVERTED = 1'b0; - wire c = C ^ IS_C_INVERTED; - wire clr = CLR ^ IS_CLR_INVERTED; - wire pre = PRE ^ IS_PRE_INVERTED; - // Hacky model to avoid simulation-synthesis mismatches. - reg qc, qp, qs; - initial qc = INIT; - initial qp = INIT; - initial qs = 0; - always @(posedge c, posedge clr) begin - if (clr) - qc <= 0; - else if (CE) - qc <= D; - end - always @(posedge c, posedge pre) begin - if (pre) - qp <= 1; - else if (CE) - qp <= D; - end - always @* begin - if (clr) - qs <= 0; - else if (pre) - qs <= 1; - end - assign Q = qs ? qp : qc; -endmodule - -(* abc9_box_id=1104, lib_whitebox, abc9_flop *) +(* abc9_box_id=1106, lib_whitebox, abc9_flop *) module FDPE ( (* abc9_arrival=303 *) output reg Q, @@ -507,7 +499,7 @@ module FDPE ( endcase endgenerate endmodule -(* abc9_box_id=1105, lib_whitebox, abc9_flop *) +(* abc9_box_id=1107, lib_whitebox, abc9_flop *) module FDPE_1 ( (* abc9_arrival=303 *) output reg Q, @@ -520,41 +512,49 @@ module FDPE_1 ( always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule -(* abc9_box_id=1106, lib_whitebox, abc9_flop *) -module FDSE ( - (* abc9_arrival=303 *) - output reg Q, +module FDCPE ( + output wire Q, (* clkbuf_sink *) (* invertible_pin = "IS_C_INVERTED" *) input C, input CE, - (* invertible_pin = "IS_D_INVERTED" *) + (* invertible_pin = "IS_CLR_INVERTED" *) + input CLR, input D, - (* invertible_pin = "IS_S_INVERTED" *) - input S + (* invertible_pin = "IS_PRE_INVERTED" *) + input PRE ); - parameter [0:0] INIT = 1'b1; + parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_S_INVERTED = 1'b0; - initial Q <= INIT; - generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase endgenerate -endmodule - -(* abc9_box_id=1107, lib_whitebox, abc9_flop *) -module FDSE_1 ( - (* abc9_arrival=303 *) - output reg Q, - (* clkbuf_sink *) - input C, - input CE, D, S -); - parameter [0:0] INIT = 1'b1; - initial Q <= INIT; - always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; + parameter [0:0] IS_CLR_INVERTED = 1'b0; + parameter [0:0] IS_PRE_INVERTED = 1'b0; + wire c = C ^ IS_C_INVERTED; + wire clr = CLR ^ IS_CLR_INVERTED; + wire pre = PRE ^ IS_PRE_INVERTED; + // Hacky model to avoid simulation-synthesis mismatches. + reg qc, qp, qs; + initial qc = INIT; + initial qp = INIT; + initial qs = 0; + always @(posedge c, posedge clr) begin + if (clr) + qc <= 0; + else if (CE) + qc <= D; + end + always @(posedge c, posedge pre) begin + if (pre) + qp <= 1; + else if (CE) + qp <= D; + end + always @* begin + if (clr) + qs <= 0; + else if (pre) + qs <= 1; + end + assign Q = qs ? qp : qc; endmodule module LDCE ( -- cgit v1.2.3 From 550310e2647c7aac1e49b79d9ff912436103062f Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 1 Jan 2020 12:30:00 +0000 Subject: Harmonize BRAM/LUTRAM descriptions across all of Yosys. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit: * renames all remaining instances of "DRAM" (which is ambiguous) to "LUTRAM" (which is not), finishing the work started in the commit 698ab9be; * renames memory rule files to brams.txt/lutrams.txt; * adds/renames script labels map_bram/map_lutram; * extracts where necessary script labels map_ffram and map_gates; * adds where necessary options -nobram/-nolutram. The end result is that BRAM/LUTRAM/FFRAM aspects of every target are now consistent with each other. Per architecture: * anlogic: rename drams.txt→lutrams.txt, add -nolutram, add :map_lutram, :map_ffram, :map_gates * ecp5: rename bram.txt→brams.txt, lutram.txt→lutrams.txt * efinix: rename bram.txt→brams.txt, add -nobram, add :map_ffram, :map_gates * gowin: rename bram.txt→brams.txt, dram.txt→lutrams.txt, rename -nodram→-nolutram (-nodram still recognized), rename :bram→:map_bram, :dram→:map_lutram, add :map_ffram, :map_gates --- techlibs/anlogic/Makefile.inc | 6 ++--- techlibs/anlogic/dram_init_16x4.vh | 16 ----------- techlibs/anlogic/drams.txt | 16 ----------- techlibs/anlogic/drams_map.v | 22 --------------- techlibs/anlogic/lutram_init_16x4.vh | 16 +++++++++++ techlibs/anlogic/lutrams.txt | 16 +++++++++++ techlibs/anlogic/lutrams_map.v | 22 +++++++++++++++ techlibs/anlogic/synth_anlogic.cc | 24 ++++++++++++----- techlibs/ecp5/Makefile.inc | 4 +-- techlibs/ecp5/bram.txt | 52 ------------------------------------ techlibs/ecp5/brams.txt | 52 ++++++++++++++++++++++++++++++++++++ techlibs/ecp5/lutram.txt | 17 ------------ techlibs/ecp5/lutrams.txt | 17 ++++++++++++ techlibs/ecp5/synth_ecp5.cc | 4 +-- techlibs/efinix/Makefile.inc | 2 +- techlibs/efinix/bram.txt | 32 ---------------------- techlibs/efinix/brams.txt | 32 ++++++++++++++++++++++ techlibs/efinix/synth_efinix.cc | 22 +++++++++++---- techlibs/gowin/Makefile.inc | 6 ++--- techlibs/gowin/bram.txt | 31 --------------------- techlibs/gowin/brams.txt | 31 +++++++++++++++++++++ techlibs/gowin/dram.txt | 17 ------------ techlibs/gowin/drams_map.v | 31 --------------------- techlibs/gowin/lutrams.txt | 17 ++++++++++++ techlibs/gowin/lutrams_map.v | 31 +++++++++++++++++++++ techlibs/gowin/synth_gowin.cc | 27 ++++++++++--------- techlibs/intel/synth_intel.cc | 10 +++---- 27 files changed, 300 insertions(+), 273 deletions(-) delete mode 100644 techlibs/anlogic/dram_init_16x4.vh delete mode 100644 techlibs/anlogic/drams.txt delete mode 100644 techlibs/anlogic/drams_map.v create mode 100644 techlibs/anlogic/lutram_init_16x4.vh create mode 100644 techlibs/anlogic/lutrams.txt create mode 100644 techlibs/anlogic/lutrams_map.v delete mode 100644 techlibs/ecp5/bram.txt create mode 100644 techlibs/ecp5/brams.txt delete mode 100644 techlibs/ecp5/lutram.txt create mode 100644 techlibs/ecp5/lutrams.txt delete mode 100644 techlibs/efinix/bram.txt create mode 100644 techlibs/efinix/brams.txt delete mode 100644 techlibs/gowin/bram.txt create mode 100644 techlibs/gowin/brams.txt delete mode 100644 techlibs/gowin/dram.txt delete mode 100644 techlibs/gowin/drams_map.v create mode 100644 techlibs/gowin/lutrams.txt create mode 100644 techlibs/gowin/lutrams_map.v diff --git a/techlibs/anlogic/Makefile.inc b/techlibs/anlogic/Makefile.inc index 9426b5ca5..2d8d65e2e 100644 --- a/techlibs/anlogic/Makefile.inc +++ b/techlibs/anlogic/Makefile.inc @@ -7,6 +7,6 @@ $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_sim.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/eagle_bb.v)) -$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/drams.txt)) -$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/drams_map.v)) -$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/dram_init_16x4.vh)) +$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutrams.txt)) +$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutrams_map.v)) +$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutram_init_16x4.vh)) diff --git a/techlibs/anlogic/dram_init_16x4.vh b/techlibs/anlogic/dram_init_16x4.vh deleted file mode 100644 index 32fb1578c..000000000 --- a/techlibs/anlogic/dram_init_16x4.vh +++ /dev/null @@ -1,16 +0,0 @@ -.INIT_D0({INIT[15*4+0], INIT[14*4+0], INIT[13*4+0], INIT[12*4+0], - INIT[11*4+0], INIT[10*4+0], INIT[9*4+0], INIT[8*4+0], - INIT[7*4+0], INIT[6*4+0], INIT[5*4+0], INIT[4*4+0], - INIT[3*4+0], INIT[2*4+0], INIT[1*4+0], INIT[0*4+0]}), -.INIT_D1({INIT[15*4+1], INIT[14*4+1], INIT[13*4+1], INIT[12*4+1], - INIT[11*4+1], INIT[10*4+1], INIT[9*4+1], INIT[8*4+1], - INIT[7*4+1], INIT[6*4+1], INIT[5*4+1], INIT[4*4+1], - INIT[3*4+1], INIT[2*4+1], INIT[1*4+1], INIT[0*4+1]}), -.INIT_D2({INIT[15*4+2], INIT[14*4+2], INIT[13*4+2], INIT[12*4+2], - INIT[11*4+2], INIT[10*4+2], INIT[9*4+2], INIT[8*4+2], - INIT[7*4+2], INIT[6*4+2], INIT[5*4+2], INIT[4*4+2], - INIT[3*4+2], INIT[2*4+2], INIT[1*4+2], INIT[0*4+2]}), -.INIT_D3({INIT[15*4+3], INIT[14*4+3], INIT[13*4+3], INIT[12*4+3], - INIT[11*4+3], INIT[10*4+3], INIT[9*4+3], INIT[8*4+3], - INIT[7*4+3], INIT[6*4+3], INIT[5*4+3], INIT[4*4+3], - INIT[3*4+3], INIT[2*4+3], INIT[1*4+3], INIT[0*4+3]}) diff --git a/techlibs/anlogic/drams.txt b/techlibs/anlogic/drams.txt deleted file mode 100644 index 4e903c0a2..000000000 --- a/techlibs/anlogic/drams.txt +++ /dev/null @@ -1,16 +0,0 @@ -bram $__ANLOGIC_DRAM16X4 - init 1 - abits 4 - dbits 4 - groups 2 - ports 1 1 - wrmode 0 1 - enable 0 1 - transp 0 0 - clocks 0 1 - clkpol 0 1 -endbram - -match $__ANLOGIC_DRAM16X4 - make_outreg -endmatch diff --git a/techlibs/anlogic/drams_map.v b/techlibs/anlogic/drams_map.v deleted file mode 100644 index 084e2a25f..000000000 --- a/techlibs/anlogic/drams_map.v +++ /dev/null @@ -1,22 +0,0 @@ -module \$__ANLOGIC_DRAM16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); - parameter [63:0]INIT = 64'bx; - input CLK1; - - input [3:0] A1ADDR; - output [3:0] A1DATA; - - input [3:0] B1ADDR; - input [3:0] B1DATA; - input B1EN; - - EG_LOGIC_DRAM16X4 #( - `include "dram_init_16x4.vh" - ) _TECHMAP_REPLACE_ ( - .di(B1DATA), - .waddr(B1ADDR), - .wclk(CLK1), - .we(B1EN), - .raddr(A1ADDR), - .do(A1DATA) - ); -endmodule diff --git a/techlibs/anlogic/lutram_init_16x4.vh b/techlibs/anlogic/lutram_init_16x4.vh new file mode 100644 index 000000000..32fb1578c --- /dev/null +++ b/techlibs/anlogic/lutram_init_16x4.vh @@ -0,0 +1,16 @@ +.INIT_D0({INIT[15*4+0], INIT[14*4+0], INIT[13*4+0], INIT[12*4+0], + INIT[11*4+0], INIT[10*4+0], INIT[9*4+0], INIT[8*4+0], + INIT[7*4+0], INIT[6*4+0], INIT[5*4+0], INIT[4*4+0], + INIT[3*4+0], INIT[2*4+0], INIT[1*4+0], INIT[0*4+0]}), +.INIT_D1({INIT[15*4+1], INIT[14*4+1], INIT[13*4+1], INIT[12*4+1], + INIT[11*4+1], INIT[10*4+1], INIT[9*4+1], INIT[8*4+1], + INIT[7*4+1], INIT[6*4+1], INIT[5*4+1], INIT[4*4+1], + INIT[3*4+1], INIT[2*4+1], INIT[1*4+1], INIT[0*4+1]}), +.INIT_D2({INIT[15*4+2], INIT[14*4+2], INIT[13*4+2], INIT[12*4+2], + INIT[11*4+2], INIT[10*4+2], INIT[9*4+2], INIT[8*4+2], + INIT[7*4+2], INIT[6*4+2], INIT[5*4+2], INIT[4*4+2], + INIT[3*4+2], INIT[2*4+2], INIT[1*4+2], INIT[0*4+2]}), +.INIT_D3({INIT[15*4+3], INIT[14*4+3], INIT[13*4+3], INIT[12*4+3], + INIT[11*4+3], INIT[10*4+3], INIT[9*4+3], INIT[8*4+3], + INIT[7*4+3], INIT[6*4+3], INIT[5*4+3], INIT[4*4+3], + INIT[3*4+3], INIT[2*4+3], INIT[1*4+3], INIT[0*4+3]}) diff --git a/techlibs/anlogic/lutrams.txt b/techlibs/anlogic/lutrams.txt new file mode 100644 index 000000000..4e903c0a2 --- /dev/null +++ b/techlibs/anlogic/lutrams.txt @@ -0,0 +1,16 @@ +bram $__ANLOGIC_DRAM16X4 + init 1 + abits 4 + dbits 4 + groups 2 + ports 1 1 + wrmode 0 1 + enable 0 1 + transp 0 0 + clocks 0 1 + clkpol 0 1 +endbram + +match $__ANLOGIC_DRAM16X4 + make_outreg +endmatch diff --git a/techlibs/anlogic/lutrams_map.v b/techlibs/anlogic/lutrams_map.v new file mode 100644 index 000000000..5a464cafc --- /dev/null +++ b/techlibs/anlogic/lutrams_map.v @@ -0,0 +1,22 @@ +module \$__ANLOGIC_DRAM16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); + parameter [63:0]INIT = 64'bx; + input CLK1; + + input [3:0] A1ADDR; + output [3:0] A1DATA; + + input [3:0] B1ADDR; + input [3:0] B1DATA; + input B1EN; + + EG_LOGIC_DRAM16X4 #( + `include "lutram_init_16x4.vh" + ) _TECHMAP_REPLACE_ ( + .di(B1DATA), + .waddr(B1ADDR), + .wclk(CLK1), + .we(B1EN), + .raddr(A1ADDR), + .do(A1DATA) + ); +endmodule diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc index b87fc8566..3a1992588 100644 --- a/techlibs/anlogic/synth_anlogic.cc +++ b/techlibs/anlogic/synth_anlogic.cc @@ -60,6 +60,9 @@ struct SynthAnlogicPass : public ScriptPass log(" -retime\n"); log(" run 'abc' with -dff option\n"); log("\n"); + log(" -nolutram\n"); + log(" do not use EG_LOGIC_DRAM16X4 cells in output netlist\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -67,7 +70,7 @@ struct SynthAnlogicPass : public ScriptPass } string top_opt, edif_file, json_file; - bool flatten, retime; + bool flatten, retime, nolutram; void clear_flags() YS_OVERRIDE { @@ -76,6 +79,7 @@ struct SynthAnlogicPass : public ScriptPass json_file = ""; flatten = true; retime = false; + nolutram = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -110,6 +114,10 @@ struct SynthAnlogicPass : public ScriptPass flatten = false; continue; } + if (args[argidx] == "-nolutram") { + nolutram = true; + continue; + } if (args[argidx] == "-retime") { retime = true; continue; @@ -150,18 +158,22 @@ struct SynthAnlogicPass : public ScriptPass run("synth -run coarse"); } - if (check_label("dram")) + if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { - run("memory_bram -rules +/anlogic/drams.txt"); - run("techmap -map +/anlogic/drams_map.v"); + run("memory_bram -rules +/anlogic/lutrams.txt"); + run("techmap -map +/anlogic/lutrams_map.v"); run("setundef -zero -params t:EG_LOGIC_DRAM16X4"); } - if (check_label("fine")) + if (check_label("map_ffram")) { run("opt -fast -mux_undef -undriven -fine"); run("memory_map"); run("opt -undriven -fine"); + } + + if (check_label("map_gates")) + { run("techmap -map +/techmap.v -map +/anlogic/arith_map.v"); if (retime || help_mode) run("abc -dff", "(only if -retime)"); @@ -187,7 +199,7 @@ struct SynthAnlogicPass : public ScriptPass run("techmap -map +/anlogic/cells_map.v"); run("clean"); } - + if (check_label("map_anlogic")) { run("anlogic_fixcarry"); diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index 46463f510..2c33f23b9 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -8,9 +8,9 @@ $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_bb.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutrams_map.v)) -$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutram.txt)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutrams.txt)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams_map.v)) -$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams.txt)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dsp_map.v)) diff --git a/techlibs/ecp5/bram.txt b/techlibs/ecp5/bram.txt deleted file mode 100644 index 777ccaa2e..000000000 --- a/techlibs/ecp5/bram.txt +++ /dev/null @@ -1,52 +0,0 @@ -bram $__ECP5_PDPW16KD - init 1 - - abits 9 - dbits 36 - - groups 2 - ports 1 1 - wrmode 1 0 - enable 4 1 - transp 0 0 - clocks 2 3 - clkpol 2 3 -endbram - -bram $__ECP5_DP16KD - init 1 - - abits 10 @a10d18 - dbits 18 @a10d18 - abits 11 @a11d9 - dbits 9 @a11d9 - abits 12 @a12d4 - dbits 4 @a12d4 - abits 13 @a13d2 - dbits 2 @a13d2 - abits 14 @a14d1 - dbits 1 @a14d1 - - groups 2 - ports 1 1 - wrmode 1 0 - enable 2 1 @a10d18 - enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 - transp 0 2 - clocks 2 3 - clkpol 2 3 -endbram - -match $__ECP5_PDPW16KD - min bits 2048 - min efficiency 5 - shuffle_enable A - make_transp - or_next_if_better -endmatch - -match $__ECP5_DP16KD - min bits 2048 - min efficiency 5 - shuffle_enable A -endmatch diff --git a/techlibs/ecp5/brams.txt b/techlibs/ecp5/brams.txt new file mode 100644 index 000000000..777ccaa2e --- /dev/null +++ b/techlibs/ecp5/brams.txt @@ -0,0 +1,52 @@ +bram $__ECP5_PDPW16KD + init 1 + + abits 9 + dbits 36 + + groups 2 + ports 1 1 + wrmode 1 0 + enable 4 1 + transp 0 0 + clocks 2 3 + clkpol 2 3 +endbram + +bram $__ECP5_DP16KD + init 1 + + abits 10 @a10d18 + dbits 18 @a10d18 + abits 11 @a11d9 + dbits 9 @a11d9 + abits 12 @a12d4 + dbits 4 @a12d4 + abits 13 @a13d2 + dbits 2 @a13d2 + abits 14 @a14d1 + dbits 1 @a14d1 + + groups 2 + ports 1 1 + wrmode 1 0 + enable 2 1 @a10d18 + enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 + transp 0 2 + clocks 2 3 + clkpol 2 3 +endbram + +match $__ECP5_PDPW16KD + min bits 2048 + min efficiency 5 + shuffle_enable A + make_transp + or_next_if_better +endmatch + +match $__ECP5_DP16KD + min bits 2048 + min efficiency 5 + shuffle_enable A +endmatch diff --git a/techlibs/ecp5/lutram.txt b/techlibs/ecp5/lutram.txt deleted file mode 100644 index b94357429..000000000 --- a/techlibs/ecp5/lutram.txt +++ /dev/null @@ -1,17 +0,0 @@ -bram $__TRELLIS_DPR16X4 - init 1 - abits 4 - dbits 4 - groups 2 - ports 1 1 - wrmode 0 1 - enable 0 1 - transp 0 0 - clocks 0 1 - clkpol 0 2 -endbram - -match $__TRELLIS_DPR16X4 - make_outreg - min wports 1 -endmatch diff --git a/techlibs/ecp5/lutrams.txt b/techlibs/ecp5/lutrams.txt new file mode 100644 index 000000000..b94357429 --- /dev/null +++ b/techlibs/ecp5/lutrams.txt @@ -0,0 +1,17 @@ +bram $__TRELLIS_DPR16X4 + init 1 + abits 4 + dbits 4 + groups 2 + ports 1 1 + wrmode 0 1 + enable 0 1 + transp 0 0 + clocks 0 1 + clkpol 0 2 +endbram + +match $__TRELLIS_DPR16X4 + make_outreg + min wports 1 +endmatch diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index a0ea6d1f9..3985da57a 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -266,13 +266,13 @@ struct SynthEcp5Pass : public ScriptPass if (!nobram && check_label("map_bram", "(skip if -nobram)")) { - run("memory_bram -rules +/ecp5/bram.txt"); + run("memory_bram -rules +/ecp5/brams.txt"); run("techmap -map +/ecp5/brams_map.v"); } if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { - run("memory_bram -rules +/ecp5/lutram.txt"); + run("memory_bram -rules +/ecp5/lutrams.txt"); run("techmap -map +/ecp5/lutrams_map.v"); } diff --git a/techlibs/efinix/Makefile.inc b/techlibs/efinix/Makefile.inc index 5013f7fc1..69665982c 100644 --- a/techlibs/efinix/Makefile.inc +++ b/techlibs/efinix/Makefile.inc @@ -7,4 +7,4 @@ $(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v)) $(eval $(call add_share_file,share/efinix,techlibs/efinix/arith_map.v)) $(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_sim.v)) $(eval $(call add_share_file,share/efinix,techlibs/efinix/brams_map.v)) -$(eval $(call add_share_file,share/efinix,techlibs/efinix/bram.txt)) +$(eval $(call add_share_file,share/efinix,techlibs/efinix/brams.txt)) diff --git a/techlibs/efinix/bram.txt b/techlibs/efinix/bram.txt deleted file mode 100644 index 0b3fd9308..000000000 --- a/techlibs/efinix/bram.txt +++ /dev/null @@ -1,32 +0,0 @@ -bram $__EFINIX_5K - init 1 - - abits 8 @a8d16 - dbits 16 @a8d16 - abits 9 @a9d8 - dbits 8 @a9d8 - abits 10 @a10d4 - dbits 4 @a10d4 - abits 11 @a11d2 - dbits 2 @a11d2 - abits 12 @a12d1 - dbits 1 @a12d1 - abits 8 @a8d20 - dbits 20 @a8d20 - abits 9 @a9d10 - dbits 10 @a9d10 - - groups 2 - ports 1 1 - wrmode 1 0 - enable 1 1 - transp 0 2 - clocks 2 3 - clkpol 2 3 -endbram - -match $__EFINIX_5K - min bits 256 - min efficiency 5 - shuffle_enable B -endmatch diff --git a/techlibs/efinix/brams.txt b/techlibs/efinix/brams.txt new file mode 100644 index 000000000..0b3fd9308 --- /dev/null +++ b/techlibs/efinix/brams.txt @@ -0,0 +1,32 @@ +bram $__EFINIX_5K + init 1 + + abits 8 @a8d16 + dbits 16 @a8d16 + abits 9 @a9d8 + dbits 8 @a9d8 + abits 10 @a10d4 + dbits 4 @a10d4 + abits 11 @a11d2 + dbits 2 @a11d2 + abits 12 @a12d1 + dbits 1 @a12d1 + abits 8 @a8d20 + dbits 20 @a8d20 + abits 9 @a9d10 + dbits 10 @a9d10 + + groups 2 + ports 1 1 + wrmode 1 0 + enable 1 1 + transp 0 2 + clocks 2 3 + clkpol 2 3 +endbram + +match $__EFINIX_5K + min bits 256 + min efficiency 5 + shuffle_enable B +endmatch diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc index 26a8d4eda..3e5274385 100644 --- a/techlibs/efinix/synth_efinix.cc +++ b/techlibs/efinix/synth_efinix.cc @@ -60,6 +60,9 @@ struct SynthEfinixPass : public ScriptPass log(" -retime\n"); log(" run 'abc' with -dff option\n"); log("\n"); + log(" -nobram\n"); + log(" do not use EFX_RAM_5K cells in output netlist\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -67,7 +70,7 @@ struct SynthEfinixPass : public ScriptPass } string top_opt, edif_file, json_file; - bool flatten, retime; + bool flatten, retime, nobram; void clear_flags() YS_OVERRIDE { @@ -76,6 +79,7 @@ struct SynthEfinixPass : public ScriptPass json_file = ""; flatten = true; retime = false; + nobram = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -114,6 +118,10 @@ struct SynthEfinixPass : public ScriptPass retime = true; continue; } + if (args[argidx] == "-nobram") { + nobram = true; + continue; + } break; } extra_args(args, argidx, design); @@ -150,18 +158,22 @@ struct SynthEfinixPass : public ScriptPass run("synth -run coarse"); } - if (check_label("map_bram", "(skip if -nobram)")) + if (!nobram || check_label("map_bram", "(skip if -nobram)")) { - run("memory_bram -rules +/efinix/bram.txt"); + run("memory_bram -rules +/efinix/brams.txt"); run("techmap -map +/efinix/brams_map.v"); run("setundef -zero -params t:EFX_RAM_5K"); } - if (check_label("fine")) + if (check_label("map_ffram")) { run("opt -fast -mux_undef -undriven -fine"); run("memory_map"); run("opt -undriven -fine"); + } + + if (check_label("map_gates")) + { run("techmap -map +/techmap.v -map +/efinix/arith_map.v"); if (retime || help_mode) run("abc -dff", "(only if -retime)"); @@ -194,7 +206,7 @@ struct SynthEfinixPass : public ScriptPass run("efinix_fixcarry"); run("clean"); } - + if (check_label("check")) { run("hierarchy -check"); diff --git a/techlibs/gowin/Makefile.inc b/techlibs/gowin/Makefile.inc index d2853704b..fe5d9d6e6 100644 --- a/techlibs/gowin/Makefile.inc +++ b/techlibs/gowin/Makefile.inc @@ -7,9 +7,9 @@ $(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_map.v)) $(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_sim.v)) $(eval $(call add_share_file,share/gowin,techlibs/gowin/arith_map.v)) $(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_map.v)) -$(eval $(call add_share_file,share/gowin,techlibs/gowin/bram.txt)) -$(eval $(call add_share_file,share/gowin,techlibs/gowin/drams_map.v)) -$(eval $(call add_share_file,share/gowin,techlibs/gowin/dram.txt)) +$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams.txt)) +$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams_map.v)) +$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams.txt)) diff --git a/techlibs/gowin/bram.txt b/techlibs/gowin/bram.txt deleted file mode 100644 index e406f9c51..000000000 --- a/techlibs/gowin/bram.txt +++ /dev/null @@ -1,31 +0,0 @@ -bram $__GW1NR_SDP - init 1 - abits 9 @a9d36 - dbits 32 @a9d36 - abits 10 @a10d18 - dbits 16 @a10d18 - abits 11 @a11d9 - dbits 8 @a11d9 - abits 12 @a12d4 - dbits 4 @a12d4 - abits 13 @a13d2 - dbits 2 @a13d2 - abits 14 @a14d1 - dbits 1 @a14d1 - groups 2 - ports 1 1 - wrmode 1 0 - enable 4 1 @a9d36 - enable 2 1 @a10d18 - enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 - transp 0 0 - clocks 2 3 - clkpol 2 3 -endbram - -match $__GW1NR_SDP - min bits 2048 - min efficiency 5 - shuffle_enable A - make_transp -endmatch diff --git a/techlibs/gowin/brams.txt b/techlibs/gowin/brams.txt new file mode 100644 index 000000000..e406f9c51 --- /dev/null +++ b/techlibs/gowin/brams.txt @@ -0,0 +1,31 @@ +bram $__GW1NR_SDP + init 1 + abits 9 @a9d36 + dbits 32 @a9d36 + abits 10 @a10d18 + dbits 16 @a10d18 + abits 11 @a11d9 + dbits 8 @a11d9 + abits 12 @a12d4 + dbits 4 @a12d4 + abits 13 @a13d2 + dbits 2 @a13d2 + abits 14 @a14d1 + dbits 1 @a14d1 + groups 2 + ports 1 1 + wrmode 1 0 + enable 4 1 @a9d36 + enable 2 1 @a10d18 + enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 + transp 0 0 + clocks 2 3 + clkpol 2 3 +endbram + +match $__GW1NR_SDP + min bits 2048 + min efficiency 5 + shuffle_enable A + make_transp +endmatch diff --git a/techlibs/gowin/dram.txt b/techlibs/gowin/dram.txt deleted file mode 100644 index 9db530251..000000000 --- a/techlibs/gowin/dram.txt +++ /dev/null @@ -1,17 +0,0 @@ -bram $__GW1NR_RAM16S4 - init 1 - abits 4 - dbits 4 - groups 2 - ports 1 1 - wrmode 0 1 - enable 0 1 - transp 0 1 - clocks 0 1 - clkpol 0 1 -endbram - -match $__GW1NR_RAM16S4 - make_outreg - min wports 1 -endmatch diff --git a/techlibs/gowin/drams_map.v b/techlibs/gowin/drams_map.v deleted file mode 100644 index a50ab365a..000000000 --- a/techlibs/gowin/drams_map.v +++ /dev/null @@ -1,31 +0,0 @@ -module \$__GW1NR_RAM16S4 (CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); - parameter CFG_ABITS = 4; - parameter CFG_DBITS = 4; - - parameter [63:0] INIT = 64'bx; - input CLK1; - - input [CFG_ABITS-1:0] A1ADDR; - output [CFG_DBITS-1:0] A1DATA; - input A1EN; - - input [CFG_ABITS-1:0] B1ADDR; - input [CFG_DBITS-1:0] B1DATA; - input B1EN; - - `include "brams_init3.vh" - - RAM16S4 - #(.INIT_0(INIT_0), - .INIT_1(INIT_1), - .INIT_2(INIT_2), - .INIT_3(INIT_3)) - _TECHMAP_REPLACE_ - (.AD(B1ADDR), - .DI(B1DATA), - .DO(A1DATA), - .CLK(CLK1), - .WRE(B1EN)); - - -endmodule diff --git a/techlibs/gowin/lutrams.txt b/techlibs/gowin/lutrams.txt new file mode 100644 index 000000000..9db530251 --- /dev/null +++ b/techlibs/gowin/lutrams.txt @@ -0,0 +1,17 @@ +bram $__GW1NR_RAM16S4 + init 1 + abits 4 + dbits 4 + groups 2 + ports 1 1 + wrmode 0 1 + enable 0 1 + transp 0 1 + clocks 0 1 + clkpol 0 1 +endbram + +match $__GW1NR_RAM16S4 + make_outreg + min wports 1 +endmatch diff --git a/techlibs/gowin/lutrams_map.v b/techlibs/gowin/lutrams_map.v new file mode 100644 index 000000000..a50ab365a --- /dev/null +++ b/techlibs/gowin/lutrams_map.v @@ -0,0 +1,31 @@ +module \$__GW1NR_RAM16S4 (CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); + parameter CFG_ABITS = 4; + parameter CFG_DBITS = 4; + + parameter [63:0] INIT = 64'bx; + input CLK1; + + input [CFG_ABITS-1:0] A1ADDR; + output [CFG_DBITS-1:0] A1DATA; + input A1EN; + + input [CFG_ABITS-1:0] B1ADDR; + input [CFG_DBITS-1:0] B1DATA; + input B1EN; + + `include "brams_init3.vh" + + RAM16S4 + #(.INIT_0(INIT_0), + .INIT_1(INIT_1), + .INIT_2(INIT_2), + .INIT_3(INIT_3)) + _TECHMAP_REPLACE_ + (.AD(B1ADDR), + .DI(B1DATA), + .DO(A1DATA), + .CLK(CLK1), + .WRE(B1EN)); + + +endmodule diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc index 6cf058f29..785f2802b 100644 --- a/techlibs/gowin/synth_gowin.cc +++ b/techlibs/gowin/synth_gowin.cc @@ -55,7 +55,7 @@ struct SynthGowinPass : public ScriptPass log(" -nobram\n"); log(" do not use BRAM cells in output netlist\n"); log("\n"); - log(" -nodram\n"); + log(" -nolutram\n"); log(" do not use distributed RAM cells in output netlist\n"); log("\n"); log(" -noflatten\n"); @@ -80,7 +80,7 @@ struct SynthGowinPass : public ScriptPass } string top_opt, vout_file; - bool retime, nobram, nodram, flatten, nodffe, nowidelut, abc9, noiopads; + bool retime, nobram, nolutram, flatten, nodffe, nowidelut, abc9, noiopads; void clear_flags() YS_OVERRIDE { @@ -90,7 +90,7 @@ struct SynthGowinPass : public ScriptPass flatten = true; nobram = false; nodffe = false; - nodram = false; + nolutram = false; nowidelut = false; abc9 = false; noiopads = false; @@ -128,8 +128,8 @@ struct SynthGowinPass : public ScriptPass nobram = true; continue; } - if (args[argidx] == "-nodram") { - nodram = true; + if (args[argidx] == "-nolutram" || /*deprecated*/args[argidx] == "-nodram") { + nolutram = true; continue; } if (args[argidx] == "-nodffe") { @@ -188,24 +188,28 @@ struct SynthGowinPass : public ScriptPass run("synth -run coarse"); } - if (!nobram && check_label("bram", "(skip if -nobram)")) + if (!nobram && check_label("map_bram", "(skip if -nobram)")) { - run("memory_bram -rules +/gowin/bram.txt"); + run("memory_bram -rules +/gowin/brams.txt"); run("techmap -map +/gowin/brams_map.v -map +/gowin/cells_sim.v"); } - if (!nodram && check_label("dram", "(skip if -nodram)")) + if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { - run("memory_bram -rules +/gowin/dram.txt"); - run("techmap -map +/gowin/drams_map.v"); + run("memory_bram -rules +/gowin/lutrams.txt"); + run("techmap -map +/gowin/lutrams_map.v"); run("determine_init"); } - if (check_label("fine")) + if (check_label("map_ffram")) { run("opt -fast -mux_undef -undriven -fine"); run("memory_map"); run("opt -undriven -fine"); + } + + if (check_label("map_gates")) + { run("techmap -map +/techmap.v -map +/gowin/arith_map.v"); run("techmap -map +/techmap.v"); if (retime || help_mode) @@ -248,7 +252,6 @@ struct SynthGowinPass : public ScriptPass run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O " "-toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO", "(unless -noiopads)"); run("clean"); - } if (check_label("check")) diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index c8c690e45..5aa1a12d4 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -187,10 +187,10 @@ struct SynthIntelPass : public ScriptPass { } if (!nobram && check_label("map_bram", "(skip if -nobram)")) { - if (family_opt == "cycloneiv" || - family_opt == "cycloneive" || - family_opt == "max10" || - help_mode) { + if (family_opt == "cycloneiv" || + family_opt == "cycloneive" || + family_opt == "max10" || + help_mode) { run("memory_bram -rules +/intel/common/brams_m9k.txt", "(if applicable for family)"); run("techmap -map +/intel/common/brams_map_m9k.v", "(if applicable for family)"); } else { @@ -224,7 +224,7 @@ struct SynthIntelPass : public ScriptPass { if (check_label("map_cells")) { if (iopads || help_mode) run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(if -iopads)"); - run(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str())); + run(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str())); run("dffinit -highlow -ff dffeas q power_up"); run("clean -purge"); } -- cgit v1.2.3 From e0c879684f510ae6fd1169c90d137e660c88e6be Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 1 Jan 2020 16:13:14 +0100 Subject: take skip wire bits into account --- passes/techmap/iopadmap.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index 47da98b06..531ac2b99 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -234,6 +234,9 @@ struct IopadmapPass : public Pass { SigBit wire_bit(wire, i); Cell *tbuf_cell = nullptr; + if (skip_wire_bits.count(wire_bit)) + continue; + if (tbuf_bits.count(wire_bit)) tbuf_cell = tbuf_bits.at(wire_bit); -- cgit v1.2.3 From a1344ec06ead35a3b7933ee93b5757eeff2e5d4a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 1 Jan 2020 16:24:30 +0100 Subject: Added a test case --- tests/arch/xilinx/bug1605.ys | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/arch/xilinx/bug1605.ys diff --git a/tests/arch/xilinx/bug1605.ys b/tests/arch/xilinx/bug1605.ys new file mode 100644 index 000000000..4be659860 --- /dev/null +++ b/tests/arch/xilinx/bug1605.ys @@ -0,0 +1,19 @@ +read_verilog < Date: Tue, 31 Dec 2019 22:54:56 -0800 Subject: attributes.count() -> get_bool_attribute() --- backends/aiger/xaiger.cc | 2 +- passes/techmap/abc9.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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; } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 3c53a5223..d6c8260b2 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -533,7 +533,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip } RTLIL::Module* box_module = design->module(mapped_cell->type); - auto abc9_flop = box_module && box_module->attributes.count("\\abc9_flop"); + auto abc9_flop = box_module && box_module->get_bool_attribute("\\abc9_flop"); for (auto &conn : mapped_cell->connections()) { RTLIL::SigSpec newsig; for (auto c : conn.second.chunks()) { @@ -988,7 +988,7 @@ struct Abc9Pass : public Pass { for (auto cell : all_cells) { auto inst_module = design->module(cell->type); - if (!inst_module || !inst_module->attributes.count("\\abc9_flop") + if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop") || cell->get_bool_attribute("\\abc9_keep")) continue; -- cgit v1.2.3 From c40b1aae42c91f200194f7f5f2caa512787ed5a3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 1 Jan 2020 08:34:43 -0800 Subject: Restore abc9 -keepff --- README.md | 3 -- passes/techmap/abc9.cc | 79 ++++++++++++++++++------------------ techlibs/xilinx/abc9_map.v | 88 ++--------------------------------------- techlibs/xilinx/synth_xilinx.cc | 4 +- 4 files changed, 46 insertions(+), 128 deletions(-) diff --git a/README.md b/README.md index c04e2b9ec..aab1c7d6b 100644 --- a/README.md +++ b/README.md @@ -381,9 +381,6 @@ Verilog Attributes and non-standard features - The module attribute ``abc9_flop`` is a boolean marking the module as a whitebox that describes the synchronous behaviour of a flip-flop. -- The cell attribute ``abc9_keep`` is a boolean indicating that this black/ - white box should be preserved through `abc9` mapping. - - The frontend sets attributes ``always_comb``, ``always_latch`` and ``always_ff`` on processes derived from SystemVerilog style always blocks according to the type of the always. These are checked for correctness in diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index d6c8260b2..a02b8d73b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -249,7 +249,7 @@ struct abc9_output_filter }; void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file, - bool cleanup, vector lut_costs, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, + bool cleanup, vector lut_costs, bool keepff, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, const std::vector &/*cells*/, bool show_tempdir, std::string box_file, std::string lut_file, std::string wire_delay, bool nomfs ) @@ -425,19 +425,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip module->remove(cell); continue; } + RTLIL::Module* box_module = design->module(cell->type); auto jt = abc9_box.find(cell->type); - if (jt == abc9_box.end()) { - RTLIL::Module* box_module = design->module(cell->type); + if (jt == abc9_box.end()) jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; - } if (jt->second) { - auto kt = cell->attributes.find("\\abc9_keep"); - bool abc9_keep = false; - if (kt != cell->attributes.end()) { - abc9_keep = kt->second.as_bool(); - cell->attributes.erase(kt); - } - if (!abc9_keep) + if (!keepff || !box_module->get_bool_attribute("\\abc9_flop")) boxes.emplace_back(cell); } } @@ -802,6 +795,10 @@ struct Abc9Pass : public Pass { log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); log(" 2, 3, .. inputs.\n"); log("\n"); + log(" -keepff\n"); + log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n"); + log(" them, for example for equivalence checking.)\n"); + log("\n"); log(" -nocleanup\n"); log(" when this option is used, the temporary files created by this pass\n"); log(" are not removed. this is useful for debugging.\n"); @@ -840,7 +837,7 @@ struct Abc9Pass : public Pass { #endif std::string script_file, clk_str, box_file, lut_file; std::string delay_target, lutin_shared = "-S 1", wire_delay; - bool fast_mode = false, cleanup = true; + bool fast_mode = false, keepff = false, cleanup = true; bool show_tempdir = false; bool nomfs = false; vector lut_costs; @@ -931,6 +928,10 @@ struct Abc9Pass : public Pass { fast_mode = true; continue; } + if (arg == "-keepff") { + keepff = true; + continue; + } if (arg == "-nocleanup") { cleanup = false; continue; @@ -986,36 +987,36 @@ struct Abc9Pass : public Pass { const std::vector all_cells = module->selected_cells(); - for (auto cell : all_cells) { - auto inst_module = design->module(cell->type); - if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop") - || cell->get_bool_attribute("\\abc9_keep")) - continue; + if (!keepff) + for (auto cell : all_cells) { + auto inst_module = design->module(cell->type); + if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop")) + continue; - Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); - if (abc9_clock_wire == NULL) - log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - SigSpec abc9_clock = assign_map(abc9_clock_wire); - - clkdomain_t key(abc9_clock); - - auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1)); - auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); - log_assert(r2.second); - - Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str())); - if (abc9_init_wire == NULL) - log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - log_assert(GetSize(abc9_init_wire) == 1); - SigSpec abc9_init = assign_map(abc9_init_wire); - if (!abc9_init.is_fully_const()) - log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); - log_assert(r2.second); - } + Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); + if (abc9_clock_wire == NULL) + log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + SigSpec abc9_clock = assign_map(abc9_clock_wire); + + clkdomain_t key(abc9_clock); + + auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1)); + auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); + log_assert(r2.second); + + Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str())); + if (abc9_init_wire == NULL) + log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_assert(GetSize(abc9_init_wire) == 1); + SigSpec abc9_init = assign_map(abc9_init_wire); + if (!abc9_init.is_fully_const()) + log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); + log_assert(r2.second); + } design->selected_active_module = module->name.str(); - abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, + abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, keepff, delay_target, lutin_shared, fast_mode, all_cells, show_tempdir, box_file, lut_file, wire_delay, nomfs); design->selected_active_module.clear(); diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 6d93e508f..1b58c34c0 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -21,7 +21,8 @@ // The following techmapping rules are intended to be run (with -max_iter 1) // before invoking the `abc9` pass in order to transform the design into // a format that it understands. -// + +`ifdef DFF_MODE // For example, (complex) flip-flops are expected to be described as an // combinatorial box (containing all control logic such as clock enable // or synchronous resets) followed by a basic D-Q flop. @@ -83,7 +84,6 @@ module FDRE (output Q, input C, CE, D, R); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; -`ifdef DFF_MODE wire QQ, $Q; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -114,21 +114,9 @@ module FDRE (output Q, input C, CE, D, R); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; -`else - (* abc9_keep *) - FDRE #( - .INIT(INIT), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_R_INVERTED(IS_R_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .R(R) - ); -`endif endmodule module FDRE_1 (output Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; -`ifdef DFF_MODE wire QQ, $Q; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -153,14 +141,6 @@ module FDRE_1 (output Q, input C, CE, D, R); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; -`else - (* abc9_keep *) - FDRE_1 #( - .INIT(INIT) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .R(R) - ); -`endif endmodule module FDSE (output Q, input C, CE, D, S); @@ -168,7 +148,6 @@ module FDSE (output Q, input C, CE, D, S); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; -`ifdef DFF_MODE wire QQ, $Q; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -198,21 +177,9 @@ module FDSE (output Q, input C, CE, D, S); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; -`else - (* abc9_keep *) - FDSE #( - .INIT(INIT), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_S_INVERTED(IS_S_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .S(S) - ); -`endif endmodule module FDSE_1 (output Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; -`ifdef DFF_MODE wire QQ, $Q; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -236,14 +203,6 @@ module FDSE_1 (output Q, input C, CE, D, S); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; -`else - (* abc9_keep *) - FDSE_1 #( - .INIT(INIT) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .S(S) - ); -`endif endmodule module FDCE (output Q, input C, CE, D, CLR); @@ -251,7 +210,6 @@ module FDCE (output Q, input C, CE, D, CLR); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; -`ifdef DFF_MODE wire QQ, $Q, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -295,21 +253,9 @@ module FDCE (output Q, input C, CE, D, CLR); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; -`else - (* abc9_keep *) - FDCE #( - .INIT(INIT), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_CLR_INVERTED(IS_CLR_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR) - ); -`endif endmodule module FDCE_1 (output Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; -`ifdef DFF_MODE wire QQ, $Q, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -345,14 +291,6 @@ module FDCE_1 (output Q, input C, CE, D, CLR); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; -`else - (* abc9_keep *) - FDCE_1 #( - .INIT(INIT) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR) - ); -`endif endmodule module FDPE (output Q, input C, CE, D, PRE); @@ -360,7 +298,6 @@ module FDPE (output Q, input C, CE, D, PRE); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; -`ifdef DFF_MODE wire QQ, $Q, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -402,21 +339,9 @@ module FDPE (output Q, input C, CE, D, PRE); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; -`else - (* abc9_keep *) - FDPE #( - .INIT(INIT), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_PRE_INVERTED(IS_PRE_INVERTED), - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE) - ); -`endif endmodule module FDPE_1 (output Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; -`ifdef DFF_MODE wire QQ, $Q, $abc9_currQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; @@ -452,15 +377,8 @@ module FDPE_1 (output Q, input C, CE, D, PRE); wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; -`else - (* abc9_keep *) - FDPE_1 #( - .INIT(INIT) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE) - ); -`endif endmodule +`endif // Attach a (combinatorial) black-box onto the output // of thes LUTRAM primitives to capture their diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f2a9ae982..10aa7be5f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -108,7 +108,7 @@ struct SynthXilinxPass : public ScriptPass log(" flatten design before synthesis\n"); log("\n"); log(" -dff\n"); - log(" run 'abc9' with -dff option\n"); + log(" enable sequential synthesis with 'abc9'\n"); log("\n"); log(" -retime\n"); log(" run 'abc' with -dff option\n"); @@ -559,6 +559,8 @@ struct SynthXilinxPass : public ScriptPass abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut"; else abc9_opts += " -lut +/xilinx/abc9_xc7.lut"; + if (!dff_mode) + abc9_opts += " -keepff"; run("abc9" + abc9_opts); run("techmap -map +/xilinx/abc9_unmap.v"); } -- cgit v1.2.3 From 6dc63e84ef680465d500bf35da64fade626498b6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 1 Jan 2020 08:34:57 -0800 Subject: Cleanup abc9, update doc for -keepff option --- passes/techmap/abc9.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index a02b8d73b..c3c8e0dbc 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -250,7 +250,7 @@ struct abc9_output_filter void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file, bool cleanup, vector lut_costs, bool keepff, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, - const std::vector &/*cells*/, bool show_tempdir, std::string box_file, std::string lut_file, + bool show_tempdir, std::string box_file, std::string lut_file, std::string wire_delay, bool nomfs ) { @@ -796,8 +796,8 @@ struct Abc9Pass : public Pass { log(" 2, 3, .. inputs.\n"); log("\n"); log(" -keepff\n"); - log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n"); - log(" them, for example for equivalence checking.)\n"); + log(" do not represent (* abc9_flop *) modules as boxes (and thus do not perform\n"); + log(" any form of sequential synthesis).\n"); log("\n"); log(" -nocleanup\n"); log(" when this option is used, the temporary files created by this pass\n"); @@ -985,10 +985,9 @@ struct Abc9Pass : public Pass { typedef SigSpec clkdomain_t; dict clk_to_mergeability; - const std::vector all_cells = module->selected_cells(); if (!keepff) - for (auto cell : all_cells) { + for (auto cell : module->selected_cells()) { auto inst_module = design->module(cell->type); if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop")) continue; @@ -1017,7 +1016,7 @@ struct Abc9Pass : public Pass { design->selected_active_module = module->name.str(); abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, keepff, - delay_target, lutin_shared, fast_mode, all_cells, show_tempdir, + delay_target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, wire_delay, nomfs); design->selected_active_module.clear(); } -- 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(-) 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 0e95756e960f809aaa4596ba44330e7bd6fd0309 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 1 Jan 2020 08:39:00 -0800 Subject: Clamp -46ps for FDPE* too --- techlibs/xilinx/abc9_xc7.box | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index 43c39544e..1dff88509 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -114,14 +114,14 @@ FDCE_1 1105 1 5 1 FDPE 1106 1 5 1 #C CE D PRE $abc9_currQ #0 109 -46 764 0 -0 109 -46 764 0 # Q (-46ps Tsu clamped to 0) +0 109 0 764 0 # Q (-46ps Tsu clamped to 0) # Box 1107 : FDPE_1 # name ID w/b ins outs FDPE_1 1107 1 5 1 #C CE D PRE $abc9_currQ #0 109 -46 764 0 -0 109 -46 764 0 # Q (-46ps Tsu clamped to 0) +0 109 0 764 0 # Q (-46ps Tsu clamped to 0) # Box 2000 : $__ABC9_LUT6 # (private cell to emulate async behaviour of LUTRAMs) -- cgit v1.2.3 From 3deec51ddcb8690901f7d99958ad71bccd19084f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 1 Jan 2020 08:43:16 -0800 Subject: Fix anlogic async flop mapping --- techlibs/anlogic/cells_map.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/anlogic/cells_map.v b/techlibs/anlogic/cells_map.v index cfc743a4b..8ac087d9d 100644 --- a/techlibs/anlogic/cells_map.v +++ b/techlibs/anlogic/cells_map.v @@ -6,14 +6,14 @@ module \$_DFFE_NP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REG module \$_DFFE_PN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule module \$_DFFE_PP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule -module \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule -module \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), . SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule +module \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), . SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule module \$_DLATCH_N_ (E, D, Q); wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; -- cgit v1.2.3 From 52fe1e0c44d572b8e1f8881dc0a1e91f7fa93c9c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 1 Jan 2020 09:05:46 -0800 Subject: Revert insertion of 'reg', leave note behind --- tests/arch/ice40/rom.v | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/arch/ice40/rom.v b/tests/arch/ice40/rom.v index c4c677c1e..71459fe38 100644 --- a/tests/arch/ice40/rom.v +++ b/tests/arch/ice40/rom.v @@ -2,7 +2,8 @@ Example from: https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/iCEcube201701UserGuide.ashx?document_id=52071 [p. 74]. */ module top(data, addr); -output reg [3:0] data; +output [3:0] data; // Note: this prompts a Yosys warning, but + // vendor doc does not contain 'reg' input [4:0] addr; always @(addr) begin case (addr) -- cgit v1.2.3 From 3d98a9627312c283715a691995466568a33ce7a2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 1 Jan 2020 17:33:10 -0800 Subject: ifdef __ICARUS__ -> ifndef YOSYS --- techlibs/xilinx/cells_sim.v | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 72e684af5..c27b0f02b 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -2236,7 +2236,7 @@ module DSP48E1 ( parameter [6:0] IS_OPMODE_INVERTED = 7'b0; initial begin -`ifdef __ICARUS__ +`ifndef YOSYS if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value"); if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value"); if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value"); @@ -2399,12 +2399,12 @@ module DSP48E1 ( case (OPMODEr[1:0]) 2'b00: X = 48'b0; 2'b01: begin X = $signed(Mrx); -`ifdef __ICARUS__ +`ifndef YOSYS if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01"); `endif end 2'b10: begin X = P; -`ifdef __ICARUS__ +`ifndef YOSYS if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10"); `endif end @@ -2416,7 +2416,7 @@ module DSP48E1 ( case (OPMODEr[3:2]) 2'b00: Y = 48'b0; 2'b01: begin Y = 48'b0; // FIXME: more accurate partial product modelling? -`ifdef __ICARUS__ +`ifndef YOSYS if (OPMODEr[1:0] != 2'b01) $fatal(1, "OPMODEr[1:0] must be 2'b01 when OPMODEr[3:2] is 2'b01"); `endif end @@ -2430,13 +2430,13 @@ module DSP48E1 ( 3'b000: Z = 48'b0; 3'b001: Z = PCIN; 3'b010: begin Z = P; -`ifdef __ICARUS__ +`ifndef YOSYS if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010"); `endif end 3'b011: Z = Cr; 3'b100: begin Z = P; -`ifdef __ICARUS__ +`ifndef YOSYS if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100"); if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100"); `endif -- cgit v1.2.3 From 3edb2e708b09c7c9ead2aeb11e2be3cae88f8ee5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 2 Jan 2020 18:58:45 +0100 Subject: Always create $shl, $shr, $sshl, $sshr cells with unsigned B inputs Signed-off-by: Clifford Wolf --- kernel/rtlil.cc | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 7c73f94c8..ab4f4f377 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1893,10 +1893,6 @@ DEF_METHOD(And, max(sig_a.size(), sig_b.size()), ID($and)) DEF_METHOD(Or, max(sig_a.size(), sig_b.size()), ID($or)) DEF_METHOD(Xor, max(sig_a.size(), sig_b.size()), ID($xor)) DEF_METHOD(Xnor, max(sig_a.size(), sig_b.size()), ID($xnor)) -DEF_METHOD(Shl, sig_a.size(), ID($shl)) -DEF_METHOD(Shr, sig_a.size(), ID($shr)) -DEF_METHOD(Sshl, sig_a.size(), ID($sshl)) -DEF_METHOD(Sshr, sig_a.size(), ID($sshr)) DEF_METHOD(Shift, sig_a.size(), ID($shift)) DEF_METHOD(Shiftx, sig_a.size(), ID($shiftx)) DEF_METHOD(Lt, 1, ID($lt)) @@ -1916,6 +1912,31 @@ DEF_METHOD(LogicAnd, 1, ID($logic_and)) DEF_METHOD(LogicOr, 1, ID($logic_or)) #undef DEF_METHOD +#define DEF_METHOD(_func, _y_size, _type) \ + RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed, const std::string &src) { \ + RTLIL::Cell *cell = addCell(name, _type); \ + cell->parameters[ID(A_SIGNED)] = is_signed; \ + cell->parameters[ID(B_SIGNED)] = false; \ + cell->parameters[ID(A_WIDTH)] = sig_a.size(); \ + cell->parameters[ID(B_WIDTH)] = sig_b.size(); \ + cell->parameters[ID(Y_WIDTH)] = sig_y.size(); \ + cell->setPort(ID::A, sig_a); \ + cell->setPort(ID::B, sig_b); \ + cell->setPort(ID::Y, sig_y); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed, const std::string &src) { \ + RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \ + add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \ + return sig_y; \ + } +DEF_METHOD(Shl, sig_a.size(), ID($shl)) +DEF_METHOD(Shr, sig_a.size(), ID($shr)) +DEF_METHOD(Sshl, sig_a.size(), ID($sshl)) +DEF_METHOD(Sshr, sig_a.size(), ID($sshr)) +#undef DEF_METHOD + #define DEF_METHOD(_func, _type, _pmux) \ RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, RTLIL::SigSpec sig_y, const std::string &src) { \ RTLIL::Cell *cell = addCell(name, _type); \ -- 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 ++++++++++++++-------------------------- passes/techmap/abc9.cc | 49 +++++++++------ techlibs/xilinx/abc9_map.v | 110 ++++++++++++++++---------------- techlibs/xilinx/synth_xilinx.cc | 6 +- 4 files changed, 135 insertions(+), 166 deletions(-) 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; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index c3c8e0dbc..6aa0b6f95 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -249,7 +249,7 @@ struct abc9_output_filter }; void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file, - bool cleanup, vector lut_costs, bool keepff, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, + bool cleanup, vector lut_costs, bool dff, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, bool show_tempdir, std::string box_file, std::string lut_file, std::string wire_delay, bool nomfs ) @@ -347,7 +347,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); log_assert(!design->module(ID($__abc9__))); { - AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); + AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, /*buffer.c_str()*/ "" /* map_filename */, true /* wideports */); reader.parse_xaiger(); } ifs.close(); @@ -430,7 +430,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip if (jt == abc9_box.end()) jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; if (jt->second) { - if (!keepff || !box_module->get_bool_attribute("\\abc9_flop")) + if (box_module->get_bool_attribute("\\abc9_flop")) { + if (dff) + boxes.emplace_back(cell); + else + box_module->set_bool_attribute("\\abc9_keep", false); + } + else boxes.emplace_back(cell); } } @@ -795,9 +801,9 @@ struct Abc9Pass : public Pass { log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); log(" 2, 3, .. inputs.\n"); log("\n"); - log(" -keepff\n"); - log(" do not represent (* abc9_flop *) modules as boxes (and thus do not perform\n"); - log(" any form of sequential synthesis).\n"); + log(" -dff\n"); + log(" also pass $_ABC9_FF_ cells through ABC. modules with many clock domains\n"); + log(" are marked as such and automatically partitioned by ABC.\n"); log("\n"); log(" -nocleanup\n"); log(" when this option is used, the temporary files created by this pass\n"); @@ -837,7 +843,7 @@ struct Abc9Pass : public Pass { #endif std::string script_file, clk_str, box_file, lut_file; std::string delay_target, lutin_shared = "-S 1", wire_delay; - bool fast_mode = false, keepff = false, cleanup = true; + bool fast_mode = false, dff = false, cleanup = true; bool show_tempdir = false; bool nomfs = false; vector lut_costs; @@ -928,8 +934,8 @@ struct Abc9Pass : public Pass { fast_mode = true; continue; } - if (arg == "-keepff") { - keepff = true; + if (arg == "-dff") { + dff = true; continue; } if (arg == "-nocleanup") { @@ -985,16 +991,14 @@ struct Abc9Pass : public Pass { typedef SigSpec clkdomain_t; dict clk_to_mergeability; - - if (!keepff) + if (dff) for (auto cell : module->selected_cells()) { - auto inst_module = design->module(cell->type); - if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop")) + if (cell->type != "$__ABC9_FF_") continue; - Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); + Wire *abc9_clock_wire = module->wire(stringf("%s.clock", cell->name.c_str())); if (abc9_clock_wire == NULL) - log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_error("'%s.clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); SigSpec abc9_clock = assign_map(abc9_clock_wire); clkdomain_t key(abc9_clock); @@ -1003,19 +1007,26 @@ struct Abc9Pass : public Pass { auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); log_assert(r2.second); - Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str())); + Wire *abc9_init_wire = module->wire(stringf("%s.init", cell->name.c_str())); if (abc9_init_wire == NULL) - log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_error("'%s.init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); log_assert(GetSize(abc9_init_wire) == 1); SigSpec abc9_init = assign_map(abc9_init_wire); if (!abc9_init.is_fully_const()) - log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_error("'%s.init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); log_assert(r2.second); } + else + for (auto cell : module->selected_cells()) { + auto inst_module = design->module(cell->type); + if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop")) + continue; + cell->set_bool_attribute("\\abc9_keep"); + } design->selected_active_module = module->name.str(); - abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, keepff, + abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, dff, delay_target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, wire_delay, nomfs); design->selected_active_module.clear(); diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 1b58c34c0..1d37952f5 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -51,29 +51,29 @@ // || || // || /\/\/\/\ || // D -->>-----< > || -// R -->>-----< Comb. > || +----------+ -// CE -->>-----< logic >--->>-- $Q --|$__ABC_FF_|--+-->> Q -// $abc9_currQ +-->>-----< > || +----------+ | -// | || \/\/\/\/ || | -// | || || | -// | ++==================++ | -// | | -// +----------------------------------------------+ +// R -->>-----< Comb. > || +-----------+ +// CE -->>-----< logic >--->>-- $Q --|$__ABC9_FF_|--+-->> Q +// abc9_ff.Q +-->>-----< > || +-----------+ | +// | || \/\/\/\/ || | +// | || || | +// | ++==================++ | +// | | +// +-----------------------------------------------+ // // The purpose of the following FD* rules are to wrap the flop with: // (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 // the connectivity of its basic D-Q flop // (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to // capture asynchronous behaviour -// (c) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock +// (c) a special _TECHMAP_REPLACE_.abc9_ff.clock wire to capture its clock // domain and polarity (used when partitioning the module so that `abc9' only // performs sequential synthesis (with reachability analysis) correctly on // one domain at a time) and also used to infer the optional delay target // from the (* abc9_clock_period = %d *) attribute attached to any wire // within -// (d) a special _TECHMAP_REPLACE_.$abc9_init wire to encode the flop's initial +// (d) a special _TECHMAP_REPLACE_.abc9_ff.init wire to encode the flop's initial // state -// (e) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback +// (e) a special _TECHMAP_REPLACE_.abc9_ff.Q wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour // // In order to perform sequential synthesis, `abc9' also requires that @@ -108,12 +108,12 @@ module FDRE (output Q, input C, CE, D, R); ); end endgenerate - $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); + $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; - wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; + wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; + wire [0:0] abc9_ff.init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; endmodule module FDRE_1 (output Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; @@ -135,12 +135,12 @@ module FDRE_1 (output Q, input C, CE, D, R); ); end endgenerate - $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); + $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; - wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; + wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [0:0] abc9_ff.init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; endmodule module FDSE (output Q, input C, CE, D, S); @@ -171,12 +171,12 @@ module FDSE (output Q, input C, CE, D, S); .D(D), .Q($Q), .C(C), .CE(CE), .S(S) ); end endgenerate - $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); + $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; - wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; + wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; + wire [0:0] abc9_ff.init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; endmodule module FDSE_1 (output Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; @@ -197,12 +197,12 @@ module FDSE_1 (output Q, input C, CE, D, S); .D(D), .Q($Q), .C(C), .CE(CE), .S(S) ); end endgenerate - $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ)); + $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; - wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; + wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [0:0] abc9_ff.init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; endmodule module FDCE (output Q, input C, CE, D, CLR); @@ -210,7 +210,7 @@ module FDCE (output Q, input C, CE, D, CLR); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; - wire QQ, $Q, $abc9_currQ; + wire QQ, $Q, $QQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDPE #( @@ -227,7 +227,7 @@ module FDCE (output Q, input C, CE, D, CLR); // $__ABC9_ASYNC1 below ); // Since this is an async flop, async behaviour is dealt with here - $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); + $__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); end else begin assign Q = QQ; @@ -245,18 +245,18 @@ module FDCE (output Q, input C, CE, D, CLR); // $__ABC9_ASYNC0 below ); // Since this is an async flop, async behaviour is dealt with here - $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); + $__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); end endgenerate - $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); + $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; - wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; + wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; + wire [0:0] abc9_ff.init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; endmodule module FDCE_1 (output Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; - wire QQ, $Q, $abc9_currQ; + wire QQ, $Q, $QQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDPE_1 #( @@ -269,7 +269,7 @@ module FDCE_1 (output Q, input C, CE, D, CLR); // behaviour is captured by // $__ABC9_ASYNC1 below ); - $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); + $__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR), .Y(QQ)); end else begin assign Q = QQ; @@ -283,14 +283,14 @@ module FDCE_1 (output Q, input C, CE, D, CLR); // behaviour is captured by // $__ABC9_ASYNC0 below ); - $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ)); + $__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR), .Y(QQ)); end endgenerate - $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); + $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; - wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; + wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [0:0] abc9_ff.init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; endmodule module FDPE (output Q, input C, CE, D, PRE); @@ -298,7 +298,7 @@ module FDPE (output Q, input C, CE, D, PRE); parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; - wire QQ, $Q, $abc9_currQ; + wire QQ, $Q, $QQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDCE #( @@ -314,7 +314,7 @@ module FDPE (output Q, input C, CE, D, PRE); // behaviour is captured by // $__ABC9_ASYNC0 below ); - $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); + $__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); end else begin assign Q = QQ; @@ -331,18 +331,18 @@ module FDPE (output Q, input C, CE, D, PRE); // behaviour is captured by // $__ABC9_ASYNC1 below ); - $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); + $__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); end endgenerate - $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); + $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; - wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; + wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; + wire [0:0] abc9_ff.init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; endmodule module FDPE_1 (output Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; - wire QQ, $Q, $abc9_currQ; + wire QQ, $Q, $QQ; generate if (INIT == 1'b1) begin assign Q = ~QQ; FDCE_1 #( @@ -355,7 +355,7 @@ module FDPE_1 (output Q, input C, CE, D, PRE); // behaviour is captured by // $__ABC9_ASYNC0 below ); - $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); + $__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE), .Y(QQ)); end else begin assign Q = QQ; @@ -369,14 +369,14 @@ module FDPE_1 (output Q, input C, CE, D, PRE); // behaviour is captured by // $__ABC9_ASYNC1 below ); - $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ)); + $__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE), .Y(QQ)); end endgenerate - $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ)); + $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); // Special signals - wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0; - wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; + wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; + wire [0:0] abc9_ff.init = 1'b0; + wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; endmodule `endif diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 10aa7be5f..af9f21756 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -108,7 +108,7 @@ struct SynthXilinxPass : public ScriptPass log(" flatten design before synthesis\n"); log("\n"); log(" -dff\n"); - log(" enable sequential synthesis with 'abc9'\n"); + log(" run 'abc9' with -dff option\n"); log("\n"); log(" -retime\n"); log(" run 'abc' with -dff option\n"); @@ -559,8 +559,8 @@ struct SynthXilinxPass : public ScriptPass abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut"; else abc9_opts += " -lut +/xilinx/abc9_xc7.lut"; - if (!dff_mode) - abc9_opts += " -keepff"; + if (dff_mode) + abc9_opts += " -dff"; run("abc9" + abc9_opts); run("techmap -map +/xilinx/abc9_unmap.v"); } -- cgit v1.2.3 From ec1756c0941fac02614c25307b17bb41fe36f468 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 12:39:52 -0800 Subject: Update comments --- techlibs/xilinx/abc9_map.v | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 1d37952f5..af58e217c 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -65,19 +65,14 @@ // the connectivity of its basic D-Q flop // (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to // capture asynchronous behaviour -// (c) a special _TECHMAP_REPLACE_.abc9_ff.clock wire to capture its clock -// domain and polarity (used when partitioning the module so that `abc9' only -// performs sequential synthesis (with reachability analysis) correctly on -// one domain at a time) and also used to infer the optional delay target -// from the (* abc9_clock_period = %d *) attribute attached to any wire -// within -// (d) a special _TECHMAP_REPLACE_.abc9_ff.init wire to encode the flop's initial -// state +// (c) a special abc9_ff.clock wire to capture its clock domain and polarity +// (indicated to `abc9' so that it only performs sequential synthesis +// (with reachability analysis) correctly on one domain at a time) +// (d) a special abc9_ff.init wire to encode the flop's initial state +// NOTE: in order to perform sequential synthesis, `abc9' also requires +// that the initial value of all flops be zero // (e) a special _TECHMAP_REPLACE_.abc9_ff.Q wire that will be used for feedback // into the (combinatorial) FD* cell to facilitate clock-enable behaviour -// -// In order to perform sequential synthesis, `abc9' also requires that -// the initial value of all flops be zero. module FDRE (output Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; -- cgit v1.2.3 From ca42af56a49a7ab3a55adab22f139d34ddb147b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 12:41:57 -0800 Subject: Update doc --- passes/techmap/abc9.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 6aa0b6f95..d39aa7638 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -802,8 +802,8 @@ struct Abc9Pass : public Pass { log(" 2, 3, .. inputs.\n"); log("\n"); log(" -dff\n"); - log(" also pass $_ABC9_FF_ cells through ABC. modules with many clock domains\n"); - log(" are marked as such and automatically partitioned by ABC.\n"); + log(" also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n"); + log(" domains are marked as such and automatically partitioned by ABC.\n"); log("\n"); log(" -nocleanup\n"); log(" when this option is used, the temporary files created by this pass\n"); @@ -825,8 +825,8 @@ struct Abc9Pass : public Pass { log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); log("ABC on logic snippets extracted from your design. You will not get any useful\n"); log("output when passing an ABC script that writes a file. Instead write your full\n"); - log("design as an XAIGER file with write_xaiger and then load that into ABC externally\n"); - log("if you want to use ABC to convert your design into another format.\n"); + log("design as an XAIGER file with `write_xaiger' and then load that into ABC\n"); + log("externally if you want to use ABC to convert your design into another format.\n"); log("\n"); log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); log("\n"); -- cgit v1.2.3 From 345e98f87105316da9797e01bdbdd3932269cfdf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 12:42:28 -0800 Subject: Add 'abc9 -dff' to CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index fc0cdc92e..481ba266e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -57,6 +57,7 @@ Yosys 0.9 .. Yosys 0.9-dev always_latch and always_ff) - Added "xilinx_dffopt" pass - Added "scratchpad" pass + - Added "abc9 -dff" - Added "synth_xilinx -dff" Yosys 0.8 .. Yosys 0.9 -- cgit v1.2.3 From a051801b72c7d526a1c04cf2635ae8d7fe43a135 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 12:53:26 -0800 Subject: synth_xilinx -dff to work with abc too --- techlibs/xilinx/synth_xilinx.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index e2a625f9b..51d2cbbd2 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -108,10 +108,11 @@ struct SynthXilinxPass : public ScriptPass log(" flatten design before synthesis\n"); log("\n"); log(" -dff\n"); - log(" run 'abc9' with -dff option\n"); + log(" run 'abc'/'abc9' with -dff option\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); + log(" run 'abc' with '-D 1' option to enable flip-flop retiming.\n"); + log(" implies -dff.\n"); log("\n"); log(" -abc9\n"); log(" use new ABC9 flow (EXPERIMENTAL)\n"); @@ -195,6 +196,7 @@ struct SynthXilinxPass : public ScriptPass continue; } if (args[argidx] == "-retime") { + dff_mode = true; retime = true; continue; } @@ -542,7 +544,7 @@ struct SynthXilinxPass : public ScriptPass if (flatten_before_abc) run("flatten"); if (help_mode) - run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut'; option for '-retime')"); + run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for 'nowidelut', '-dff', '-retime')"); else if (abc9) { if (family != "xc7") log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, " @@ -565,10 +567,16 @@ struct SynthXilinxPass : public ScriptPass run("techmap -map +/xilinx/abc9_unmap.v"); } else { + std::string abc_opts; if (nowidelut) - run("abc -luts 2:2,3,6:5" + string(retime ? " -dff -D 1" : "")); + abc_opts += " -luts 2:2,3,6:5"; else - run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff -D 1" : "")); + abc_opts += " -luts 2:2,3,6:5,10,20"; + if (dff_mode) + abc_opts += " -dff"; + if (retime) + abc_opts += " -D 1"; + run("abc" + abc_opts); } run("clean"); @@ -581,7 +589,7 @@ struct SynthXilinxPass : public ScriptPass techmap_args += stringf("[-map %s]", ff_map_file.c_str()); else if (!abc9) techmap_args += stringf(" -map %s", ff_map_file.c_str()); - run("techmap " + techmap_args, "(option without '-abc9')"); + run("techmap " + techmap_args, "(only if '-abc9')"); run("xilinx_dffopt"); } -- cgit v1.2.3 From 6e866030c286d70f6ccff805e58b1fdd9a1a322b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 14:38:59 -0800 Subject: Combine tests to check multiple clock domains --- tests/arch/xilinx/abc9_dff.ys | 43 ++++++++++--------------------------------- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/tests/arch/xilinx/abc9_dff.ys b/tests/arch/xilinx/abc9_dff.ys index 6611b4f18..b457cefce 100644 --- a/tests/arch/xilinx/abc9_dff.ys +++ b/tests/arch/xilinx/abc9_dff.ys @@ -1,55 +1,32 @@ read_verilog < Date: Thu, 2 Jan 2020 15:58:45 -0800 Subject: Cleanup --- passes/techmap/abc9.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index a7e748ce7..8e17460e1 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -190,11 +190,10 @@ struct Abc9Pass : public ScriptPass run("flatten -wb @abc9_holes"); run("techmap @abc9_holes"); run("aigmap @abc9_holes"); - run("select -list @abc9_holes"); if (dff_mode) run("abc9_ops -prep_dff"); run("opt -purge @abc9_holes"); - run("setattr -mod -set whitebox 1 @abc9_holes"); + run("wbflip @abc9_holes"); auto selected_modules = active_design->selected_modules(); active_design->selection_stack.emplace_back(false); -- cgit v1.2.3 From 7fe268fcdb17d28dbb187d4c5c3b53e648c190ca Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 16:00:26 -0800 Subject: Move scc operations out of inner loop --- passes/techmap/abc9.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8e17460e1..df59ff857 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -189,6 +189,8 @@ struct Abc9Pass : public ScriptPass run("select -set abc9_holes A:abc9_holes"); run("flatten -wb @abc9_holes"); run("techmap @abc9_holes"); + run("scc -set_attr abc9_scc_id {}"); + run("abc9_ops -break_scc"); run("aigmap @abc9_holes"); if (dff_mode) run("abc9_ops -prep_dff"); @@ -207,8 +209,6 @@ struct Abc9Pass : public ScriptPass continue; } - log_push(); - active_design->selection().select(mod); std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; @@ -216,14 +216,10 @@ struct Abc9Pass : public ScriptPass tempdir_name[0] = tempdir_name[4] = '_'; tempdir_name = make_temp_dir(tempdir_name); - run("scc -set_attr abc9_scc_id {}"); - run("abc9_ops -break_scc"); - run("aigmap"); run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()), "write_xaiger -map /input.sym /input.xaig"); run(stringf("%s -tempdir %s", map_cmd.str().c_str(), tempdir_name.c_str()), "abc9_map [options] -tempdir "); - run("abc9_ops -unbreak_scc"); if (cleanup) { @@ -232,11 +228,11 @@ struct Abc9Pass : public ScriptPass } active_design->selection().selected_modules.clear(); - - log_pop(); } active_design->selection_stack.pop_back(); + + run("abc9_ops -unbreak_scc"); } } Abc9Pass; -- cgit v1.2.3 From 32695e5032fcaa932a67f63946ae5e2a1edc8d65 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 16:06:39 -0800 Subject: scc command to ignore blackboxes --- passes/cmds/scc.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc index 99f4fbae8..dd26f8258 100644 --- a/passes/cmds/scc.cc +++ b/passes/cmds/scc.cc @@ -301,10 +301,10 @@ struct SccPass : public Pass { RTLIL::Selection newSelection(false); int scc_counter = 0; - for (auto &mod_it : design->modules_) - if (design->selected(mod_it.second)) + for (auto mod : design->modules()) + if (!mod->get_blackbox_attribute() && design->selected(mod)) { - SccWorker worker(design, mod_it.second, nofeedbackMode, allCellTypes, maxDepth); + SccWorker worker(design, mod, nofeedbackMode, allCellTypes, maxDepth); if (!setAttr.empty()) { -- cgit v1.2.3 From 4eaf41505256fc6f20065b3e5a64d74e607b15e7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 16:13:44 -0800 Subject: aigmap everything --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index df59ff857..e7fcb9165 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -191,7 +191,7 @@ struct Abc9Pass : public ScriptPass run("techmap @abc9_holes"); run("scc -set_attr abc9_scc_id {}"); run("abc9_ops -break_scc"); - run("aigmap @abc9_holes"); + run("aigmap"); if (dff_mode) run("abc9_ops -prep_dff"); run("opt -purge @abc9_holes"); -- cgit v1.2.3 From a050f9c80887f9962c326566c1f351c991e0c8b0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 Jan 2020 16:14:04 -0800 Subject: Remove a few log_{push,pop}() --- passes/techmap/abc9_map.cc | 7 ------- passes/techmap/abc9_ops.cc | 1 - 2 files changed, 8 deletions(-) diff --git a/passes/techmap/abc9_map.cc b/passes/techmap/abc9_map.cc index 9b56f04a8..171289c6d 100644 --- a/passes/techmap/abc9_map.cc +++ b/passes/techmap/abc9_map.cc @@ -266,8 +266,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip fprintf(f, "%s\n", abc9_script.c_str()); fclose(f); - log_push(); - int count_outputs = design->scratchpad_get_int("write_xaiger.num_outputs"); log("Extracted %d AND gates and %d wires to a netlist network with %d inputs and %d outputs.\n", design->scratchpad_get_int("write_xaiger.num_ands"), @@ -645,8 +643,6 @@ clone_lut: //{ // log("Don't call ABC as there is nothing to map.\n"); //} - - log_pop(); } struct Abc9MapPass : public Pass { @@ -759,7 +755,6 @@ struct Abc9MapPass : public Pass { void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ABC9_MAP pass (technology mapping using ABC9).\n"); - log_push(); #ifdef ABCEXTERNAL std::string exe_file = ABCEXTERNAL; @@ -913,8 +908,6 @@ struct Abc9MapPass : public Pass { delay_target, lutin_shared, fast_mode, all_cells, show_tempdir, box_file, lut_file, wire_delay, nomfs, tempdir_name); } - - log_pop(); } } Abc9MapPass; diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index dcb8a8a78..a4059bd4d 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -436,7 +436,6 @@ struct Abc9OpsPass : public Pass { void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ABC9_OPS pass (helper functions for ABC9).\n"); - log_push(); bool break_scc_mode = false; bool unbreak_scc_mode = false; -- 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 ++++++++++++++++++++++++++++++++++++++++------- passes/techmap/abc9.cc | 14 ++-- 2 files changed, 148 insertions(+), 30 deletions(-) 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"; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index e7fcb9165..6dd4de2e0 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -185,17 +185,17 @@ struct Abc9Pass : public ScriptPass void script() YS_OVERRIDE { - run("abc9_ops -prep_holes"); - run("select -set abc9_holes A:abc9_holes"); - run("flatten -wb @abc9_holes"); - run("techmap @abc9_holes"); run("scc -set_attr abc9_scc_id {}"); - run("abc9_ops -break_scc"); + run("abc9_ops -break_scc"/*" -prep_holes"*/); +// run("select -set abc9_holes A:abc9_holes"); +// run("dump @abc9_holes"); +// run("flatten -wb @abc9_holes"); +// run("techmap @abc9_holes"); run("aigmap"); if (dff_mode) run("abc9_ops -prep_dff"); - run("opt -purge @abc9_holes"); - run("wbflip @abc9_holes"); +// run("opt -purge @abc9_holes"); +// run("wbflip @abc9_holes"); auto selected_modules = active_design->selected_modules(); active_design->selection_stack.emplace_back(false); -- 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 +++++----------------------------------------- passes/techmap/abc9.cc | 6 +++- passes/techmap/abc9_ops.cc | 48 +++++++++++++++++++++-------- 3 files changed, 48 insertions(+), 81 deletions(-) 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; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 6dd4de2e0..25fe3fbc8 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -195,7 +195,11 @@ struct Abc9Pass : public ScriptPass if (dff_mode) run("abc9_ops -prep_dff"); // run("opt -purge @abc9_holes"); -// run("wbflip @abc9_holes"); + + run("abc9_ops -prep_holes"); + + run("select -set abc9_holes A:abc9_holes"); + run("wbflip @abc9_holes"); auto selected_modules = active_design->selected_modules(); active_design->selection_stack.emplace_back(false); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index a4059bd4d..c671553e2 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -288,8 +288,6 @@ void prep_holes(RTLIL::Module *module) // 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); log_assert(w); @@ -333,6 +331,7 @@ void prep_holes(RTLIL::Module *module) holes_module->set_bool_attribute("\\abc9_holes"); dict cell_cache; + dict> box_ports; int port_id = 1; for (auto cell : box_list) { @@ -350,24 +349,47 @@ void prep_holes(RTLIL::Module *module) 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; + auto r2 = box_ports.insert(cell->type); + if (r2.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 + r2.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()) { + r2.first->second.push_back(carry_in); + r2.first->second.push_back(carry_out); + } } // 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) { + for (const 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) -- 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 +++++++++++++++------------------------------ passes/techmap/abc9.cc | 6 +- passes/techmap/abc9_ops.cc | 1 + 3 files changed, 79 insertions(+), 164 deletions(-) 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) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 25fe3fbc8..af37ecb5c 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -187,17 +187,13 @@ struct Abc9Pass : public ScriptPass { run("scc -set_attr abc9_scc_id {}"); run("abc9_ops -break_scc"/*" -prep_holes"*/); -// run("select -set abc9_holes A:abc9_holes"); -// run("dump @abc9_holes"); // run("flatten -wb @abc9_holes"); // run("techmap @abc9_holes"); run("aigmap"); + run("abc9_ops -prep_holes"); if (dff_mode) run("abc9_ops -prep_dff"); // run("opt -purge @abc9_holes"); - - run("abc9_ops -prep_holes"); - run("select -set abc9_holes A:abc9_holes"); run("wbflip @abc9_holes"); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index c671553e2..bcf622dba 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -322,6 +322,7 @@ void prep_holes(RTLIL::Module *module) } } + cell->attributes["\\abc9_box_order"] = box_list.size(); box_list.emplace_back(cell); } log_assert(!box_list.empty()); -- 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 ---------------------------------------------- passes/techmap/abc9.cc | 12 +++++----- passes/techmap/abc9_ops.cc | 2 -- 3 files changed, 7 insertions(+), 63 deletions(-) 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); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index af37ecb5c..da56f42ea 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -186,15 +186,17 @@ struct Abc9Pass : public ScriptPass void script() YS_OVERRIDE { run("scc -set_attr abc9_scc_id {}"); - run("abc9_ops -break_scc"/*" -prep_holes"*/); -// run("flatten -wb @abc9_holes"); -// run("techmap @abc9_holes"); + run("abc9_ops -break_scc"); run("aigmap"); + run("abc9_ops -prep_holes"); + run("select -set abc9_holes A:abc9_holes"); + run("flatten -wb @abc9_holes"); + run("techmap @abc9_holes"); + run("aigmap @abc9_holes"); if (dff_mode) run("abc9_ops -prep_dff"); -// run("opt -purge @abc9_holes"); - run("select -set abc9_holes A:abc9_holes"); + run("opt -purge @abc9_holes"); run("wbflip @abc9_holes"); auto selected_modules = active_design->selected_modules(); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index bcf622dba..632f2bc8a 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -386,8 +386,6 @@ void prep_holes(RTLIL::Module *module) } } - // NB: Assume box_module->ports are sorted alphabetically - // (as RTLIL::Module::fixup_ports() would do) for (const auto &port_name : box_ports.at(cell->type)) { RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); -- 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 +------- passes/techmap/abc9.cc | 7 ++---- passes/techmap/abc9_ops.cc | 55 +++++++++++++--------------------------------- 3 files changed, 18 insertions(+), 53 deletions(-) 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(); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index da56f42ea..0da815870 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -186,14 +186,11 @@ struct Abc9Pass : public ScriptPass void script() YS_OVERRIDE { run("scc -set_attr abc9_scc_id {}"); - run("abc9_ops -break_scc"); - run("aigmap"); - - run("abc9_ops -prep_holes"); + run("abc9_ops -break_scc -prep_holes"); run("select -set abc9_holes A:abc9_holes"); run("flatten -wb @abc9_holes"); run("techmap @abc9_holes"); - run("aigmap @abc9_holes"); + run("aigmap"); if (dff_mode) run("abc9_ops -prep_dff"); run("opt -purge @abc9_holes"); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 632f2bc8a..2f07de8d4 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -21,6 +21,7 @@ #include "kernel/register.h" #include "kernel/sigtools.h" #include "kernel/utils.h" +#include "kernel/celltypes.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -194,58 +195,32 @@ void prep_holes(RTLIL::Module *module) SigMap sigmap(module); - // 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_") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_drivers[Y].insert(cell->name); - 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()); - toposort.node(cell->name); - bit_users[A].insert(cell->name); - bit_users[B].insert(cell->name); - bit_drivers[Y].insert(cell->name); - continue; - } - if (cell->type == "$__ABC9_FF_") continue; - RTLIL::Module* inst_module = design->module(cell->type); - if (inst_module) { - if (!inst_module->attributes.count("\\abc9_box_id") || cell->get_bool_attribute("\\abc9_keep")) - continue; + auto inst_module = module->design->module(cell->type); + bool abc9_box = inst_module && inst_module->attributes.count("\\abc9_box_id") && !cell->get_bool_attribute("\\abc9_keep"); + abc9_box_seen = abc9_box_seen || abc9_box; - for (const auto &conn : cell->connections()) { - auto port_wire = inst_module->wire(conn.first); - // 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 && !yosys_celltypes.cell_known(cell->type)) + continue; - abc9_box_seen = true; + for (auto conn : cell->connections()) { + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); - toposort.node(cell->name); + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); } + + toposort.node(cell->name); } if (!abc9_box_seen) -- 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 ++++++------- passes/techmap/abc9.cc | 5 ++- passes/techmap/abc9_map.cc | 18 ++-------- passes/techmap/abc9_ops.cc | 85 +++++++++++++++++++++++----------------------- 4 files changed, 59 insertions(+), 73 deletions(-) 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(); } } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 0da815870..d51ed3352 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -186,7 +186,10 @@ struct Abc9Pass : public ScriptPass void script() YS_OVERRIDE { run("scc -set_attr abc9_scc_id {}"); - run("abc9_ops -break_scc -prep_holes"); + if (help_mode) + run("abc9_ops -break_scc -prep_holes [-dff]", "(option for -dff)"); + else + run("abc9_ops -break_scc -prep_holes" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); run("select -set abc9_holes A:abc9_holes"); run("flatten -wb @abc9_holes"); run("techmap @abc9_holes"); diff --git a/passes/techmap/abc9_map.cc b/passes/techmap/abc9_map.cc index 171289c6d..d007dbcc2 100644 --- a/passes/techmap/abc9_map.cc +++ b/passes/techmap/abc9_map.cc @@ -355,28 +355,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx; } - dict abc9_box; vector boxes; for (auto cell : cells) { if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) { module->remove(cell); continue; } - auto jt = abc9_box.find(cell->type); - if (jt == abc9_box.end()) { - RTLIL::Module* box_module = design->module(cell->type); - jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; - } - if (jt->second) { - auto kt = cell->attributes.find("\\abc9_keep"); - bool abc9_keep = false; - if (kt != cell->attributes.end()) { - abc9_keep = kt->second.as_bool(); - cell->attributes.erase(kt); - } - if (!abc9_keep) - boxes.emplace_back(cell); - } + if (cell->attributes.erase("\\abc9_box_seq")) + boxes.emplace_back(cell); } dict> bit_drivers, bit_users; diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 2f07de8d4..ab5aa9f8d 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -109,39 +109,31 @@ void prep_dff(RTLIL::Module *module) typedef SigSpec clkdomain_t; dict clk_to_mergeability; - //if (dff_mode) - for (auto cell : module->selected_cells()) { - if (cell->type != "$__ABC9_FF_") - continue; + for (auto cell : module->selected_cells()) { + if (cell->type != "$__ABC9_FF_") + continue; - Wire *abc9_clock_wire = module->wire(stringf("%s.clock", cell->name.c_str())); - if (abc9_clock_wire == NULL) - log_error("'%s.clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - SigSpec abc9_clock = assign_map(abc9_clock_wire); - - clkdomain_t key(abc9_clock); - - auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1)); - auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); - log_assert(r2.second); - - Wire *abc9_init_wire = module->wire(stringf("%s.init", cell->name.c_str())); - if (abc9_init_wire == NULL) - log_error("'%s.init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - log_assert(GetSize(abc9_init_wire) == 1); - SigSpec abc9_init = assign_map(abc9_init_wire); - if (!abc9_init.is_fully_const()) - log_error("'%s.init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); - log_assert(r2.second); - } - //else - // for (auto cell : module->selected_cells()) { - // auto inst_module = design->module(cell->type); - // if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop")) - // continue; - // cell->set_bool_attribute("\\abc9_keep"); - // } + Wire *abc9_clock_wire = module->wire(stringf("%s.clock", cell->name.c_str())); + if (abc9_clock_wire == NULL) + log_error("'%s.clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + SigSpec abc9_clock = assign_map(abc9_clock_wire); + + clkdomain_t key(abc9_clock); + + auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1)); + auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second)); + log_assert(r2.second); + + Wire *abc9_init_wire = module->wire(stringf("%s.init", cell->name.c_str())); + if (abc9_init_wire == NULL) + log_error("'%s.init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + log_assert(GetSize(abc9_init_wire) == 1); + SigSpec abc9_init = assign_map(abc9_init_wire); + if (!abc9_init.is_fully_const()) + log_error("'%s.init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); + r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const())); + log_assert(r2.second); + } RTLIL::Module *holes_module = design->module(stringf("%s$holes", module->name.c_str())); if (holes_module) { @@ -188,7 +180,7 @@ void prep_dff(RTLIL::Module *module) } } -void prep_holes(RTLIL::Module *module) +void prep_holes(RTLIL::Module *module, bool dff) { auto design = module->design; log_assert(design); @@ -204,10 +196,15 @@ void prep_holes(RTLIL::Module *module) continue; auto inst_module = module->design->module(cell->type); - bool abc9_box = inst_module && inst_module->attributes.count("\\abc9_box_id") && !cell->get_bool_attribute("\\abc9_keep"); - abc9_box_seen = abc9_box_seen || abc9_box; - - if (!abc9_box && !yosys_celltypes.cell_known(cell->type)) + bool abc9_box = inst_module && inst_module->attributes.count("\\abc9_box_id"); + bool abc9_flop = false; + if (abc9_box) { + abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); + if (abc9_flop && !dff) + continue; + abc9_box_seen = abc9_box; + } + else if (!yosys_celltypes.cell_known(cell->type)) continue; for (auto conn : cell->connections()) { @@ -215,7 +212,7 @@ void prep_holes(RTLIL::Module *module) for (auto bit : sigmap(conn.second)) bit_users[bit].insert(cell->name); - if (cell->output(conn.first)) + if (cell->output(conn.first) && !abc9_flop) for (auto bit : sigmap(conn.second)) bit_drivers[bit].insert(cell->name); } @@ -255,8 +252,7 @@ void prep_holes(RTLIL::Module *module) log_assert(cell); RTLIL::Module* box_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 */); @@ -297,7 +293,7 @@ void prep_holes(RTLIL::Module *module) } } - cell->attributes["\\abc9_box_order"] = box_list.size(); + cell->attributes["\\abc9_box_seq"] = box_list.size(); box_list.emplace_back(cell); } log_assert(!box_list.empty()); @@ -437,6 +433,7 @@ struct Abc9OpsPass : public Pass { bool unbreak_scc_mode = false; bool prep_dff_mode = false; bool prep_holes_mode = false; + bool dff_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -457,6 +454,10 @@ struct Abc9OpsPass : public Pass { prep_holes_mode = true; continue; } + if (arg == "-dff") { + dff_mode = true; + continue; + } break; } extra_args(args, argidx, design); @@ -479,7 +480,7 @@ struct Abc9OpsPass : public Pass { if (prep_dff_mode) prep_dff(mod); if (prep_holes_mode) - prep_holes(mod); + prep_holes(mod, dff_mode); } } } Abc9OpsPass; -- cgit v1.2.3 From 8293a3fe749701c7df425acd81e24a2a34f5032e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 4 Jan 2020 09:30:48 -0800 Subject: Cleanup --- passes/techmap/abc9_map.cc | 46 ++++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/passes/techmap/abc9_map.cc b/passes/techmap/abc9_map.cc index d007dbcc2..b3642ab22 100644 --- a/passes/techmap/abc9_map.cc +++ b/passes/techmap/abc9_map.cc @@ -198,7 +198,7 @@ struct abc9_output_filter void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file, vector lut_costs, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, - const std::vector &cells, bool show_tempdir, std::string box_file, std::string lut_file, + bool show_tempdir, std::string box_file, std::string lut_file, std::string wire_delay, bool nomfs, std::string tempdir_name ) { @@ -355,15 +355,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx; } - vector boxes; - for (auto cell : cells) { - if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) { - module->remove(cell); - continue; - } - if (cell->attributes.erase("\\abc9_box_seq")) - boxes.emplace_back(cell); - } + for (auto it = module->cells_.begin(); it != module->cells_.end(); ) + if (it->second->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) + it = module->cells_.erase(it); + else + ++it; dict> bit_drivers, bit_users; TopoSort toposort; @@ -455,9 +451,18 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip cell->attributes = mapped_cell->attributes; } + auto abc9_box = cell->attributes.erase("\\abc9_box_seq"); + if (abc9_box) { + module->swap_names(cell, existing_cell); + module->remove(existing_cell); + } RTLIL::Module* box_module = design->module(mapped_cell->type); auto abc9_flop = box_module && box_module->attributes.count("\\abc9_flop"); for (auto &conn : mapped_cell->connections()) { + // Skip entire box ports composed entirely of padding only + if (abc9_box && conn.second.is_wire() && conn.second.as_wire()->get_bool_attribute(ID(abc9_padding))) + continue; + RTLIL::SigSpec newsig; for (auto c : conn.second.chunks()) { if (c.width == 0) @@ -483,23 +488,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip } } - for (auto existing_cell : boxes) { - Cell *cell = module->cell(remap_name(existing_cell->name)); - if (cell) { - for (auto &conn : existing_cell->connections()) { - if (!conn.second.is_wire()) - continue; - Wire *wire = conn.second.as_wire(); - if (!wire->get_bool_attribute(ID(abc9_padding))) - continue; - cell->unsetPort(conn.first); - log_debug("Dropping padded port connection for %s (%s) .%s (%s )\n", log_id(cell), cell->type.c_str(), log_id(conn.first), log_signal(conn.second)); - } - module->swap_names(cell, existing_cell); - } - module->remove(existing_cell); - } - // Copy connections (and rename) from mapped_mod to module for (auto conn : mapped_mod->connections()) { if (!conn.first.is_fully_const()) { @@ -888,10 +876,8 @@ struct Abc9MapPass : public Pass { continue; } - const std::vector all_cells = mod->selected_cells(); - abc9_module(design, mod, script_file, exe_file, lut_costs, - delay_target, lutin_shared, fast_mode, all_cells, show_tempdir, + delay_target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, wire_delay, nomfs, tempdir_name); } } -- 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 ++++++++++++++++---------- passes/techmap/abc9_map.cc | 13 ++++--------- passes/techmap/abc9_ops.cc | 39 --------------------------------------- 3 files changed, 20 insertions(+), 58 deletions(-) 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*/); diff --git a/passes/techmap/abc9_map.cc b/passes/techmap/abc9_map.cc index b3642ab22..e061cadeb 100644 --- a/passes/techmap/abc9_map.cc +++ b/passes/techmap/abc9_map.cc @@ -445,24 +445,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip if (existing_cell) { cell->parameters = existing_cell->parameters; cell->attributes = existing_cell->attributes; + if (cell->attributes.erase("\\abc9_box_seq")) { + module->swap_names(cell, existing_cell); + module->remove(existing_cell); + } } else { cell->parameters = mapped_cell->parameters; cell->attributes = mapped_cell->attributes; } - auto abc9_box = cell->attributes.erase("\\abc9_box_seq"); - if (abc9_box) { - module->swap_names(cell, existing_cell); - module->remove(existing_cell); - } RTLIL::Module* box_module = design->module(mapped_cell->type); auto abc9_flop = box_module && box_module->attributes.count("\\abc9_flop"); for (auto &conn : mapped_cell->connections()) { - // Skip entire box ports composed entirely of padding only - if (abc9_box && conn.second.is_wire() && conn.second.as_wire()->get_bool_attribute(ID(abc9_padding))) - continue; - RTLIL::SigSpec newsig; for (auto c : conn.second.chunks()) { if (c.width == 0) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index ab5aa9f8d..730431ebf 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -254,45 +254,6 @@ void prep_holes(RTLIL::Module *module, bool dff) RTLIL::Module* box_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 */); - - // 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 (const auto &port_name : box_module->ports) { - RTLIL::Wire* 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->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); - } - } - } - cell->attributes["\\abc9_box_seq"] = box_list.size(); box_list.emplace_back(cell); } -- cgit v1.2.3