From 98c9ea605b5cb2eb540ae5b804a18f8921f0bc46 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Dec 2019 17:05:02 -0800 Subject: [PATCH 01/16] techmap/aigmap of whiteboxes to occur before abc9 instead of in write_xaiger --- techlibs/ecp5/synth_ecp5.cc | 5 +++++ techlibs/ice40/synth_ice40.cc | 5 +++++ techlibs/xilinx/synth_xilinx.cc | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 4cbb56ea1..b099c25d3 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -312,6 +312,11 @@ struct SynthEcp5Pass : public ScriptPass run("techmap " + techmap_args); if (abc9) { + run("select -set abc9_boxes A:abc9_box_id A:whitebox=1"); + run("wbflip @abc9_boxes"); + run("techmap -autoproc @abc9_boxes"); + run("aigmap @abc9_boxes"); + run("wbflip @abc9_boxes"); run("read_verilog -icells -lib +/ecp5/abc9_model.v"); if (nowidelut) run("abc9 -lut +/ecp5/abc9_5g_nowide.lut -box +/ecp5/abc9_5g.box -W 200 -nomfs"); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 901194b06..2f0bdb130 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -350,6 +350,11 @@ struct SynthIce40Pass : public ScriptPass } if (!noabc) { if (abc == "abc9") { + run("select -set abc9_boxes A:abc9_box_id A:whitebox=1"); + run("wbflip @abc9_boxes"); + run("techmap -autoproc @abc9_boxes"); + run("aigmap @abc9_boxes"); + run("wbflip @abc9_boxes"); run("read_verilog -icells -lib +/ice40/abc9_model.v"); int wire_delay; if (device_opt == "lp") diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 2c5686a35..8c30148c0 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -533,6 +533,11 @@ struct SynthXilinxPass : public ScriptPass 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"); + run("select -set abc9_boxes A:abc9_box_id A:whitebox=1"); + run("wbflip @abc9_boxes"); + run("techmap -autoproc @abc9_boxes"); + run("aigmap @abc9_boxes"); + run("wbflip @abc9_boxes"); 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); From f2ac36de4ae372cd4467580ca1b28757ea7c9ff7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Dec 2019 17:06:10 -0800 Subject: [PATCH 02/16] write_xaiger to inst each cell type once, do not call techmap/aigmap --- backends/aiger/xaiger.cc | 46 ++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 627133314..7765c37bf 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -605,15 +605,25 @@ struct XAigerWriter RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); + dict cell_cache; + int port_id = 1; int box_count = 0; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); + log_assert(box_module); + IdString derived_name = box_module->derive(module->design, cell->parameters); + box_module = module->design->module(derived_name); + if (box_module->has_processes()) + log_error("ABC9 box '%s' contains processes!\n", box_module->name.c_str()); + int box_inputs = 0, box_outputs = 0; - Cell *holes_cell = nullptr; - if (box_module->get_bool_attribute("\\whitebox")) { + auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); + Cell *holes_cell = r.first->second; + if (r.second && !holes_cell && box_module->get_bool_attribute("\\whitebox")) { holes_cell = holes_module->addCell(cell->name, cell->type); holes_cell->parameters = cell->parameters; + r.first->second = holes_cell; } // NB: Assume box_module->ports are sorted alphabetically @@ -622,8 +632,8 @@ struct XAigerWriter RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); RTLIL::Wire *holes_wire; - RTLIL::SigSpec port_wire; - if (w->port_input) { + RTLIL::SigSpec port_sig; + if (w->port_input) for (int i = 0; i < GetSize(w); i++) { box_inputs++; holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); @@ -634,31 +644,33 @@ struct XAigerWriter holes_module->ports.push_back(holes_wire->name); } if (holes_cell) - port_wire.append(holes_wire); + port_sig.append(holes_wire); } - if (!port_wire.empty()) - holes_cell->setPort(w->name, port_wire); - } if (w->port_output) { box_outputs += GetSize(w); for (int i = 0; i < GetSize(w); i++) { if (GetSize(w) == 1) - holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), log_id(w->name))); else - holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), log_id(w->name), i)); holes_wire->port_output = true; holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); if (holes_cell) - port_wire.append(holes_wire); + port_sig.append(holes_wire); else holes_module->connect(holes_wire, State::S0); } - if (!port_wire.empty()) - holes_cell->setPort(w->name, port_wire); + } + if (!port_sig.empty()) { + if (r.second) + holes_cell->setPort(w->name, port_sig); + else + holes_module->connect(holes_cell->getPort(w->name), port_sig); } } + write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_module->attributes.at("\\abc9_box_id").as_int()); @@ -685,16 +697,8 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - // TODO: Should not need to opt_merge if we only instantiate - // each box type once... - Pass::call(holes_module->design, "opt_merge -share_all"); - Pass::call(holes_module->design, "flatten -wb"); - // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, - // instead of per write_xaiger call - Pass::call(holes_module->design, "techmap"); - Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) if (!cell->type.in("$_NOT_", "$_AND_")) log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); From 91467938c477c5c668f5ea1a38fef59e2b19db5c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Dec 2019 17:08:19 -0800 Subject: [PATCH 03/16] Stray newline --- backends/aiger/xaiger.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7765c37bf..8074fa835 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -670,7 +670,6 @@ struct XAigerWriter } } - write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_module->attributes.at("\\abc9_box_id").as_int()); From 151f7533e89d1a6db9c52b3c5d77adb2089db366 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Dec 2019 16:26:19 -0800 Subject: [PATCH 04/16] Add testcase --- tests/various/bug1531.ys | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/various/bug1531.ys diff --git a/tests/various/bug1531.ys b/tests/various/bug1531.ys new file mode 100644 index 000000000..542223030 --- /dev/null +++ b/tests/various/bug1531.ys @@ -0,0 +1,34 @@ +read_verilog < Date: Wed, 11 Dec 2019 16:26:26 -0800 Subject: [PATCH 05/16] Preserve size of $genval$-s in for loops --- frontends/ast/simplify.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 44fd32cdc..8cbf5a6e2 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1198,6 +1198,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, varbuf = new AstNode(AST_LOCALPARAM, varbuf); varbuf->str = init_ast->children[0]->str; + auto resolved = current_scope.at(init_ast->children[0]->str); + if (resolved->range_valid) { + varbuf->range_left = resolved->range_left; + varbuf->range_right = resolved->range_right; + varbuf->range_swapped = resolved->range_swapped; + varbuf->range_valid = resolved->range_valid; + log_dump(varbuf->range_left, varbuf->range_right); + } + AstNode *backup_scope_varbuf = current_scope[varbuf->str]; current_scope[varbuf->str] = varbuf; @@ -2998,6 +3007,14 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma current_ast_mod->children.push_back(p); str = p->str; id2ast = p; + + auto resolved = current_scope.at(index_var); + if (resolved->range_valid) { + p->range_left = resolved->range_left; + p->range_right = resolved->range_right; + p->range_swapped = resolved->range_swapped; + p->range_valid = resolved->range_valid; + } } } From 1ac1697e15ff72e69f4dfbf6922f0871c81bdff2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Dec 2019 16:59:00 -0800 Subject: [PATCH 06/16] Stray log_dump --- frontends/ast/simplify.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 8cbf5a6e2..b94a8d710 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1204,7 +1204,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, varbuf->range_right = resolved->range_right; varbuf->range_swapped = resolved->range_swapped; varbuf->range_valid = resolved->range_valid; - log_dump(varbuf->range_left, varbuf->range_right); } AstNode *backup_scope_varbuf = current_scope[varbuf->str]; From 23fcfd0adb51f800936b70999a5f95fe59ee7631 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 12 Dec 2019 07:34:07 -0800 Subject: [PATCH 07/16] Make SV2017 compliant courtesy of @wsnyder --- tests/simple/mem_arst.v | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/simple/mem_arst.v b/tests/simple/mem_arst.v index 9bd38fcb3..88d0553b9 100644 --- a/tests/simple/mem_arst.v +++ b/tests/simple/mem_arst.v @@ -7,11 +7,9 @@ module MyMem #( input Clk_i, input [AddrWidth-1:0] Addr_i, input [DataWidth-1:0] Data_i, - output [DataWidth-1:0] Data_o, + output reg [DataWidth-1:0] Data_o, input WR_i); - reg [DataWidth-1:0] Data_o; - localparam Size = 2**AddrWidth; (* mem2reg *) From 41ed6ca7a5a18aa3a2ce42e76012c43fdf2de73b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 17 Dec 2019 17:32:48 +0100 Subject: [PATCH 08/16] Fix sim for assignments with lhs --- passes/sat/sim.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 4c3022c70..d5634b26d 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -230,7 +230,7 @@ struct SimInstance bool did_something = false; sig = sigmap(sig); - log_assert(GetSize(sig) == GetSize(value)); + log_assert(GetSize(sig) <= GetSize(value)); for (int i = 0; i < GetSize(sig); i++) if (state_nets.at(sig[i]) != value[i]) { From 3b559de6e9f8972c1e52ee8bf6d9a600bcfa187f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Dec 2019 12:21:12 -0800 Subject: [PATCH 09/16] Interpret "abc9 -lut" as lut string only if [0-9:] --- passes/techmap/abc9.cc | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8276c3c16..d03e5da8e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -981,29 +981,28 @@ struct Abc9Pass : public Pass { //} if (arg == "-lut" && argidx+1 < args.size()) { string arg = args[++argidx]; - 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 { - pos = arg.find_first_of('.'); + 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_file = arg; - rewrite_filename(lut_file); - if (!lut_file.empty() && !is_absolute_path(lut_file)) - lut_file = std::string(pwd) + "/" + lut_file; - } - else { + 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; } - 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)); continue; } if (arg == "-luts" && argidx+1 < args.size()) { @@ -1072,7 +1071,7 @@ struct Abc9Pass : public Pass { box_file = "+/dummy.box"; rewrite_filename(box_file); - if (!box_file.empty() && !is_absolute_path(box_file)) + if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+') box_file = std::string(pwd) + "/" + box_file; dict box_lookup; From 561ae1c5c4e694656fb4ce9198e62f0efbe4c705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Ko=C5=9Bcielnicki?= Date: Thu, 19 Dec 2019 08:49:21 +0100 Subject: [PATCH 10/16] xilinx_dffopt: Keep order of LUT inputs. See rationale at https://github.com/YosysHQ/yosys/pull/1557#discussion_r359196549 --- techlibs/xilinx/xilinx_dffopt.cc | 46 +++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/techlibs/xilinx/xilinx_dffopt.cc b/techlibs/xilinx/xilinx_dffopt.cc index 1256a08cb..13a0b9b83 100644 --- a/techlibs/xilinx/xilinx_dffopt.cc +++ b/techlibs/xilinx/xilinx_dffopt.cc @@ -27,8 +27,31 @@ typedef std::pair> LutData; // Compute a LUT implementing (select ^ select_inv) ? alt_data : data. Returns true if successful. bool merge_lut(LutData &result, const LutData &data, const LutData select, bool select_inv, SigBit alt_data, int max_lut_size) { - // First, gather input signals. + // First, gather input signals -- insert new signals at the beginning + // of the vector, so they don't disturb the likely-critical D LUT input + // timings. result.second = data.second; + // D lut inputs initially start at 0. + int idx_data = 0; + // Now add the control input LUT inputs. + std::vector idx_sel; + for (auto bit : select.second) { + int idx = -1; + for (int i = 0; i < GetSize(result.second); i++) + if (result.second[i] == bit) + idx = i; + if (idx == -1) { + idx = 0; + // Insert new signal at the beginning and bump all indices. + result.second.insert(result.second.begin(), bit); + idx_data++; + for (int &sidx : idx_sel) + sidx++; + } + idx_sel.push_back(idx); + } + // Insert the Q signal, if any, to the slowest input -- it will have + // no problem meeting timing. int idx_alt = -1; if (alt_data.wire) { // Check if we already have it. @@ -37,22 +60,13 @@ bool merge_lut(LutData &result, const LutData &data, const LutData select, bool idx_alt = i; // If not, add it. if (idx_alt == -1) { - idx_alt = GetSize(result.second); - result.second.push_back(alt_data); + idx_alt = 0; + result.second.insert(result.second.begin(), alt_data); + idx_data++; + for (int &sidx : idx_sel) + sidx++; } } - std::vector idx_sel; - for (auto bit : select.second) { - int idx = -1; - for (int i = 0; i < GetSize(result.second); i++) - if (result.second[i] == bit) - idx = i; - if (idx == -1) { - idx = GetSize(result.second); - result.second.push_back(bit); - } - idx_sel.push_back(idx); - } // If LUT would be too large, bail. if (GetSize(result.second) > max_lut_size) @@ -75,7 +89,7 @@ bool merge_lut(LutData &result, const LutData &data, const LutData select, bool new_bit = alt_data.data == State::S1; } else { // Use original LUT. - int lut_idx = i & ((1 << GetSize(data.second)) - 1); + int lut_idx = i >> idx_data & ((1 << GetSize(data.second)) - 1); new_bit = data.first.bits[lut_idx] == State::S1; } result.first.bits[i] = new_bit ? State::S1 : State::S0; From 8b2c9f4518aa27662a29de5d282df44f1bba6dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Ko=C5=9Bcielnicki?= Date: Wed, 27 Nov 2019 18:13:00 +0100 Subject: [PATCH 11/16] xilinx: Add simulation models for remaining CLB primitives. --- techlibs/xilinx/cells_sim.v | 201 +++++++++++++++++++++++++++++++++- techlibs/xilinx/cells_xtra.py | 26 ++--- techlibs/xilinx/cells_xtra.v | 139 ----------------------- 3 files changed, 210 insertions(+), 156 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index cf7923777..47ba794bf 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -227,6 +227,14 @@ module MUXCY(output O, input CI, DI, S); assign O = S ? CI : DI; endmodule +module MUXF5(output O, input I0, I1, S); + assign O = S ? I1 : I0; +endmodule + +module MUXF6(output O, input I0, I1, S); + assign O = S ? I1 : I0; +endmodule + (* abc9_box_id = 1, lib_whitebox *) module MUXF7(output O, input I0, I1, S); assign O = S ? I1 : I0; @@ -237,6 +245,10 @@ module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule +module MUXF9(output O, input I0, I1, S); + assign O = S ? I1 : I0; +endmodule + module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule @@ -258,6 +270,26 @@ module CARRY4( assign CO[3] = S[3] ? CO[2] : DI[3]; endmodule +module CARRY8( + output [7:0] CO, + output [7:0] O, + input CI, + input CI_TOP, + input [7:0] DI, S +); + parameter CARRY_TYPE = "SINGLE_CY8"; + wire CI4 = (CARRY_TYPE == "DUAL_CY4" ? CI_TOP : CO[3]); + assign O = S ^ {CO[6:4], CI4, CO[2:0], CI}; + assign CO[0] = S[0] ? CI : DI[0]; + assign CO[1] = S[1] ? CO[0] : DI[1]; + assign CO[2] = S[2] ? CO[1] : DI[2]; + assign CO[3] = S[3] ? CO[2] : DI[3]; + assign CO[4] = S[4] ? CI4 : DI[4]; + assign CO[5] = S[5] ? CO[4] : DI[5]; + assign CO[6] = S[6] ? CO[5] : DI[6]; + assign CO[7] = S[7] ? CO[6] : DI[7]; +endmodule + `ifdef _EXPLICIT_CARRY module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S); @@ -281,6 +313,16 @@ endmodule `endif +module ORCY (output O, input CI, I); + assign O = CI | I; +endmodule + +module MULT_AND (output LO, input I0, I1); + assign LO = I0 & I1; +endmodule + +// Flip-flops and latches. + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L238-L250 module FDRE ( @@ -414,6 +456,51 @@ module FDPE ( endcase endgenerate 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 + module FDRE_1 ( (* abc9_arrival=303 *) output reg Q, @@ -480,8 +567,8 @@ module LDCE ( wire clr = CLR ^ IS_CLR_INVERTED; wire g = G ^ IS_G_INVERTED; always @* - if (clr) Q = 1'b0; - else if (GE && g) Q = D; + if (clr) Q <= 1'b0; + else if (GE && g) Q <= D; endmodule module LDPE ( @@ -502,8 +589,59 @@ module LDPE ( wire g = G ^ IS_G_INVERTED; wire pre = PRE ^ IS_PRE_INVERTED; always @* - if (pre) Q = 1'b1; - else if (GE && g) Q = D; + if (pre) Q <= 1'b1; + else if (GE && g) Q <= D; +endmodule + +module LDCPE ( + output reg Q, + (* invertible_pin = "IS_CLR_INVERTED" *) + input CLR, + (* invertible_pin = "IS_D_INVERTED" *) + input D, + (* invertible_pin = "IS_G_INVERTED" *) + input G, + (* invertible_pin = "IS_GE_INVERTED" *) + input GE, + (* invertible_pin = "IS_PRE_INVERTED" *) + input PRE +); + parameter [0:0] INIT = 1'b1; + parameter [0:0] IS_CLR_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_G_INVERTED = 1'b0; + parameter [0:0] IS_GE_INVERTED = 1'b0; + parameter [0:0] IS_PRE_INVERTED = 1'b0; + initial Q = INIT; + wire d = D ^ IS_D_INVERTED; + wire g = G ^ IS_G_INVERTED; + wire ge = GE ^ IS_GE_INVERTED; + wire clr = CLR ^ IS_CLR_INVERTED; + wire pre = PRE ^ IS_PRE_INVERTED; + always @* + if (clr) Q <= 1'b0; + else if (pre) Q <= 1'b1; + else if (ge && g) Q <= d; +endmodule + +module AND2B1L ( + output O, + input DI, + (* invertible_pin = "IS_SRI_INVERTED" *) + input SRI +); + parameter [0:0] IS_SRI_INVERTED = 1'b0; + assign O = DI & ~(SRI ^ IS_SRI_INVERTED); +endmodule + +module OR2L ( + output O, + input DI, + (* invertible_pin = "IS_SRI_INVERTED" *) + input SRI +); + parameter [0:0] IS_SRI_INVERTED = 1'b0; + assign O = DI | (SRI ^ IS_SRI_INVERTED); endmodule // LUTRAM. @@ -1369,6 +1507,20 @@ endmodule // Shift registers. +module SRL16 ( + output Q, + input A0, A1, A2, A3, + (* clkbuf_sink *) + input CLK, + input D +); + parameter [15:0] INIT = 16'h0000; + + reg [15:0] r = INIT; + assign Q = r[{A3,A2,A1,A0}]; + always @(posedge CLK) r <= { r[14:0], D }; +endmodule + module SRL16E ( // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905 (* abc9_arrival=1472 *) @@ -1393,6 +1545,22 @@ module SRL16E ( endgenerate endmodule +module SRLC16 ( + output Q, + output Q15, + input A0, A1, A2, A3, + (* clkbuf_sink *) + input CLK, + input D +); + parameter [15:0] INIT = 16'h0000; + + reg [15:0] r = INIT; + assign Q15 = r[15]; + assign Q = r[{A3,A2,A1,A0}]; + always @(posedge CLK) r <= { r[14:0], D }; +endmodule + module SRLC16E ( output Q, output Q15, @@ -1445,6 +1613,31 @@ module SRLC32E ( endgenerate endmodule +module CFGLUT5 ( + output CDO, + output O5, + output O6, + input I4, + input I3, + input I2, + input I1, + input I0, + input CDI, + input CE, + (* clkbuf_sink *) + (* invertible_pin = "IS_CLK_INVERTED" *) + input CLK +); + parameter [31:0] INIT = 32'h00000000; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + wire clk = CLK ^ IS_CLK_INVERTED; + reg [31:0] r = INIT; + assign CDO = r[31]; + assign O5 = r[{1'b0, I3, I2, I1, I0}]; + assign O6 = r[{I4, I3, I2, I1, I0}]; + always @(posedge clk) if (CE) r <= {r[30:0], CDI}; +endmodule + // DSP // Virtex 2, Virtex 2 Pro, Spartan 3. diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py index 6d5adf1aa..d5c58c5d7 100644 --- a/techlibs/xilinx/cells_xtra.py +++ b/techlibs/xilinx/cells_xtra.py @@ -65,9 +65,9 @@ CELLS = [ # CLB -- registers/latches. # Virtex 1/2/4/5, Spartan 3. - Cell('FDCPE', port_attrs={'C': ['clkbuf_sink']}), + # Cell('FDCPE', port_attrs={'C': ['clkbuf_sink']}), # Cell('FDRSE', port_attrs={'C': ['clkbuf_sink']}), - Cell('LDCPE', port_attrs={'C': ['clkbuf_sink']}), + # Cell('LDCPE', port_attrs={'C': ['clkbuf_sink']}), # Virtex 6, Spartan 6, Series 7, Ultrascale. # Cell('FDCE'), # Cell('FDPE'), @@ -75,8 +75,8 @@ CELLS = [ # Cell('FDSE'), # Cell('LDCE'), # Cell('LDPE'), - Cell('AND2B1L'), - Cell('OR2L'), + # Cell('AND2B1L'), + # Cell('OR2L'), # CLB -- other. # Cell('LUT1'), @@ -86,23 +86,23 @@ CELLS = [ # Cell('LUT5'), # Cell('LUT6'), # Cell('LUT6_2'), - Cell('MUXF5'), - Cell('MUXF6'), + # Cell('MUXF5'), + # Cell('MUXF6'), # Cell('MUXF7'), # Cell('MUXF8'), - Cell('MUXF9'), + # Cell('MUXF9'), # Cell('CARRY4'), - Cell('CARRY8'), + # Cell('CARRY8'), # Cell('MUXCY'), # Cell('XORCY'), - Cell('ORCY'), - Cell('MULT_AND'), - Cell('SRL16', port_attrs={'CLK': ['clkbuf_sink']}), + # Cell('ORCY'), + # Cell('MULT_AND'), + # Cell('SRL16', port_attrs={'CLK': ['clkbuf_sink']}), # Cell('SRL16E', port_attrs={'CLK': ['clkbuf_sink']}), - Cell('SRLC16', port_attrs={'CLK': ['clkbuf_sink']}), + # Cell('SRLC16', port_attrs={'CLK': ['clkbuf_sink']}), # Cell('SRLC16E', port_attrs={'CLK': ['clkbuf_sink']}), # Cell('SRLC32E', port_attrs={'CLK': ['clkbuf_sink']}), - Cell('CFGLUT5', port_attrs={'CLK': ['clkbuf_sink']}), + # Cell('CFGLUT5', port_attrs={'CLK': ['clkbuf_sink']}), # Block RAM. # Virtex. diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index 66b7c583f..c3e5c72f9 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -1,144 +1,5 @@ // Created by cells_xtra.py from Xilinx models -module FDCPE (...); - 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; - output 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; -endmodule - -module LDCPE (...); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_CLR_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_G_INVERTED = 1'b0; - parameter [0:0] IS_GE_INVERTED = 1'b0; - parameter [0:0] IS_PRE_INVERTED = 1'b0; - output Q; - (* invertible_pin = "IS_CLR_INVERTED" *) - input CLR; - (* invertible_pin = "IS_D_INVERTED" *) - input D; - (* invertible_pin = "IS_G_INVERTED" *) - input G; - (* invertible_pin = "IS_GE_INVERTED" *) - input GE; - (* invertible_pin = "IS_PRE_INVERTED" *) - input PRE; -endmodule - -module AND2B1L (...); - parameter [0:0] IS_SRI_INVERTED = 1'b0; - output O; - input DI; - (* invertible_pin = "IS_SRI_INVERTED" *) - input SRI; -endmodule - -module OR2L (...); - parameter [0:0] IS_SRI_INVERTED = 1'b0; - output O; - input DI; - (* invertible_pin = "IS_SRI_INVERTED" *) - input SRI; -endmodule - -module MUXF5 (...); - output O; - input I0; - input I1; - input S; -endmodule - -module MUXF6 (...); - output O; - input I0; - input I1; - input S; -endmodule - -module MUXF9 (...); - output O; - input I0; - input I1; - input S; -endmodule - -module CARRY8 (...); - parameter CARRY_TYPE = "SINGLE_CY8"; - output [7:0] CO; - output [7:0] O; - input CI; - input CI_TOP; - input [7:0] DI; - input [7:0] S; -endmodule - -module ORCY (...); - output O; - input CI; - input I; -endmodule - -module MULT_AND (...); - output LO; - input I0; - input I1; -endmodule - -module SRL16 (...); - parameter [15:0] INIT = 16'h0000; - output Q; - input A0; - input A1; - input A2; - input A3; - (* clkbuf_sink *) - input CLK; - input D; -endmodule - -module SRLC16 (...); - parameter [15:0] INIT = 16'h0000; - output Q; - output Q15; - input A0; - input A1; - input A2; - input A3; - (* clkbuf_sink *) - input CLK; - input D; -endmodule - -module CFGLUT5 (...); - parameter [31:0] INIT = 32'h00000000; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - output CDO; - output O5; - output O6; - input I4; - input I3; - input I2; - input I1; - input I0; - input CDI; - input CE; - (* clkbuf_sink *) - (* invertible_pin = "IS_CLK_INVERTED" *) - input CLK; -endmodule - module RAMB16_S1 (...); parameter [0:0] INIT = 1'h0; parameter [0:0] SRVAL = 1'h0; From 2a8cfdebbba39782304afdf91b8fcfbf0bd58eb0 Mon Sep 17 00:00:00 2001 From: Graham Edgecombe Date: Tue, 19 Nov 2019 19:45:59 +0000 Subject: [PATCH 12/16] Add PYTHON_CONFIG variable to the Makefile --- Makefile | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 6e7681cf3..c60e0afa6 100644 --- a/Makefile +++ b/Makefile @@ -152,7 +152,8 @@ ifeq ($(ENABLE_PYOSYS),1) PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)" PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"") PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.) -PYTHON_PREFIX := $(shell $(PYTHON_EXECUTABLE)-config --prefix) +PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config +PYTHON_PREFIX := $(shell $(PYTHON_CONFIG) --prefix) PYTHON_DESTDIR := $(PYTHON_PREFIX)/lib/python$(PYTHON_VERSION)/site-packages # Reload Makefile.conf to override python specific variables if defined @@ -305,17 +306,17 @@ ifeq ($(ENABLE_PYOSYS),1) #Detect name of boost_python library. Some distros usbe boost_python-py, other boost_python, some only use the major version number, some a concatenation of major and minor version numbers ifeq ($(OS), Darwin) BOOST_PYTHON_LIB ?= $(shell \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ echo ""; fi; fi; fi; fi;) else BOOST_PYTHON_LIB ?= $(shell \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \ - if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \ + if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \ echo ""; fi; fi; fi; fi;) endif @@ -325,19 +326,19 @@ endif ifeq ($(OS), Darwin) ifeq ($(PYTHON_MAJOR_VERSION),3) -LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem -CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON +LDLIBS += $(shell $(PYTHON_CONFIG) --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem +CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON else -LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem -CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON +LDLIBS += $(shell $(PYTHON_CONFIG) --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem +CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON endif else ifeq ($(PYTHON_MAJOR_VERSION),3) -LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem -CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON +LDLIBS += $(shell $(PYTHON_CONFIG) --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem +CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON else -LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem -CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON +LDLIBS += $(shell $(PYTHON_CONFIG) --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem +CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON endif endif From 319cba70d37eafdb8bbd3ddf6a0f9c238d53d0c2 Mon Sep 17 00:00:00 2001 From: Graham Edgecombe Date: Tue, 19 Nov 2019 19:46:15 +0000 Subject: [PATCH 13/16] Fix linking with Python 3.8 The behaviour of python-config --libs has changed in Python 3.8. For example, compare the output of it with Python 3.7 and 3.8 on an ArchLinux system: $ python3.7-config --libs -lpython3.7m -lcrypt -lpthread -ldl -lutil -lm $ python3.8-config --libs -lcrypt -lpthread -ldl -lutil -lm -lm $ The lack of -lpython in the latter case causes the linker to fail when attempting to build Yosys against Python 3.8. Passing the new --embed flag to python-config adds -lpython, just like earlier versions of Python: $ python3.8-config --embed --libs -lpython3.8 -lcrypt -lpthread -ldl -lutil -lm -lm $ This commit adds code for automatically detecting support for the --embed flag. If it is supported, it is passed to all python-config invocations. This fixes building against Python 3.8. --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index c60e0afa6..a85f6350c 100644 --- a/Makefile +++ b/Makefile @@ -152,7 +152,14 @@ ifeq ($(ENABLE_PYOSYS),1) PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)" PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"") PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.) + +ENABLE_PYTHON_CONFIG_EMBED ?= $(shell $(PYTHON_EXECUTABLE)-config --embed --libs > /dev/null && echo 1) +ifeq ($(ENABLE_PYTHON_CONFIG_EMBED),1) +PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config --embed +else PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config +endif + PYTHON_PREFIX := $(shell $(PYTHON_CONFIG) --prefix) PYTHON_DESTDIR := $(PYTHON_PREFIX)/lib/python$(PYTHON_VERSION)/site-packages From 10e82e103f7b95d5a50d2ac85bc8e07e4461e388 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Dec 2019 12:05:45 -0800 Subject: [PATCH 14/16] Revert "Optimise write_xaiger" --- backends/aiger/xaiger.cc | 45 +++++++++++++++------------------ techlibs/ecp5/synth_ecp5.cc | 5 ---- techlibs/ice40/synth_ice40.cc | 5 ---- techlibs/xilinx/synth_xilinx.cc | 5 ---- 4 files changed, 21 insertions(+), 39 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 8074fa835..627133314 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -605,25 +605,15 @@ struct XAigerWriter RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); - dict cell_cache; - int port_id = 1; int box_count = 0; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); - log_assert(box_module); - IdString derived_name = box_module->derive(module->design, cell->parameters); - box_module = module->design->module(derived_name); - if (box_module->has_processes()) - log_error("ABC9 box '%s' contains processes!\n", box_module->name.c_str()); - int box_inputs = 0, box_outputs = 0; - auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); - Cell *holes_cell = r.first->second; - if (r.second && !holes_cell && box_module->get_bool_attribute("\\whitebox")) { + Cell *holes_cell = nullptr; + if (box_module->get_bool_attribute("\\whitebox")) { holes_cell = holes_module->addCell(cell->name, cell->type); holes_cell->parameters = cell->parameters; - r.first->second = holes_cell; } // NB: Assume box_module->ports are sorted alphabetically @@ -632,8 +622,8 @@ struct XAigerWriter RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); RTLIL::Wire *holes_wire; - RTLIL::SigSpec port_sig; - if (w->port_input) + RTLIL::SigSpec port_wire; + if (w->port_input) { for (int i = 0; i < GetSize(w); i++) { box_inputs++; holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); @@ -644,29 +634,28 @@ struct XAigerWriter holes_module->ports.push_back(holes_wire->name); } if (holes_cell) - port_sig.append(holes_wire); + port_wire.append(holes_wire); } + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); + } if (w->port_output) { box_outputs += GetSize(w); for (int i = 0; i < GetSize(w); i++) { if (GetSize(w) == 1) - holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), log_id(w->name))); + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); else - holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), log_id(w->name), i)); + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); holes_wire->port_output = true; holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); if (holes_cell) - port_sig.append(holes_wire); + port_wire.append(holes_wire); else holes_module->connect(holes_wire, State::S0); } - } - if (!port_sig.empty()) { - if (r.second) - holes_cell->setPort(w->name, port_sig); - else - holes_module->connect(holes_cell->getPort(w->name), port_sig); + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } } @@ -696,8 +685,16 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); + // TODO: Should not need to opt_merge if we only instantiate + // each box type once... + Pass::call(holes_module->design, "opt_merge -share_all"); + Pass::call(holes_module->design, "flatten -wb"); + // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, + // instead of per write_xaiger call + Pass::call(holes_module->design, "techmap"); + Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) if (!cell->type.in("$_NOT_", "$_AND_")) log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 16ff9c57a..b71bb2395 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -321,11 +321,6 @@ struct SynthEcp5Pass : public ScriptPass run("techmap " + techmap_args); if (abc9) { - run("select -set abc9_boxes A:abc9_box_id A:whitebox=1"); - run("wbflip @abc9_boxes"); - run("techmap -autoproc @abc9_boxes"); - run("aigmap @abc9_boxes"); - run("wbflip @abc9_boxes"); run("read_verilog -icells -lib +/ecp5/abc9_model.v"); if (nowidelut) run("abc9 -lut +/ecp5/abc9_5g_nowide.lut -box +/ecp5/abc9_5g.box -W 200 -nomfs"); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 5073ba917..ed7a16c08 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -350,11 +350,6 @@ struct SynthIce40Pass : public ScriptPass } if (!noabc) { if (abc == "abc9") { - run("select -set abc9_boxes A:abc9_box_id A:whitebox=1"); - run("wbflip @abc9_boxes"); - run("techmap -autoproc @abc9_boxes"); - run("aigmap @abc9_boxes"); - run("wbflip @abc9_boxes"); run("read_verilog -icells -lib +/ice40/abc9_model.v"); int wire_delay; if (device_opt == "lp") diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ff530b819..971089b28 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -540,11 +540,6 @@ struct SynthXilinxPass : public ScriptPass 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"); - run("select -set abc9_boxes A:abc9_box_id A:whitebox=1"); - run("wbflip @abc9_boxes"); - run("techmap -autoproc @abc9_boxes"); - run("aigmap @abc9_boxes"); - run("wbflip @abc9_boxes"); 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); From ff2645ce0b8d0e639b0e83db35476036dde34f0d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Dec 2019 13:38:32 -0800 Subject: [PATCH 15/16] Put specify/endspecify inside `` --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5cc52e842..0250c7846 100644 --- a/README.md +++ b/README.md @@ -454,10 +454,10 @@ Verilog Attributes and non-standard features expressions over parameters and constant values are allowed). The intended use for this is synthesis-time DRC. -- There is limited support for converting specify .. endspecify statements to - special ``$specify2``, ``$specify3``, and ``$specrule`` cells, for use in - blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable this - functionality. (By default specify .. endspecify blocks are ignored.) +- There is limited support for converting ``specify`` .. ``endspecify`` + statements to special ``$specify2``, ``$specify3``, and ``$specrule`` cells, + for use in blackboxes and whiteboxes. Use ``read_verilog -specify`` to + enable this functionality. (By default these blocks are ignored.) Non-standard or SystemVerilog features for formal verification From 7928eb113c5a310924f4bb8ab26d0dafe902d6ec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Dec 2019 11:24:39 -0800 Subject: [PATCH 16/16] 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 6fd73c1e0..7b9427b2f 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -88,6 +88,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