From 8de17877d4073a6e593ea650b8eca0488f653d24 Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Tue, 3 Dec 2019 14:48:00 -0800 Subject: [PATCH 01/14] Add testcase --- tests/arch/ice40/ice40_opt.ys | 60 +++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/arch/ice40/ice40_opt.ys b/tests/arch/ice40/ice40_opt.ys index b17c69c91..58c33acaa 100644 --- a/tests/arch/ice40/ice40_opt.ys +++ b/tests/arch/ice40/ice40_opt.ys @@ -24,3 +24,63 @@ equiv_opt -assert -map +/ice40/cells_map.v -map +/ice40/cells_sim.v ice40_opt design -load postopt select -assert-count 1 t:* select -assert-count 1 t:$lut + +# https://github.com/YosysHQ/yosys/issues/1543 +design -reset +read_verilog <<EOT +module delay_element (input wire clk, input wire reset, input wire enable, + input wire chainin, output wire chainout, output reg latch); + + + reg const_zero = 0; + reg const_one = 1; + + wire delay_tap; + + + //carry logic + (* keep *) SB_CARRY carry ( .CO(chainout), .I0(const_zero), + .I1(const_one), .CI(chainin)); + + + //flip flop latch + (* keep *) SB_DFFER flipflop( .Q(latch), .C(clk), .E(enable), + .D(delay_tap), .R(reset)); + + + //LUT table + // the LUT should just echo the carry in (I3) + // carry I0 = LUT I1 + // carry I1 = LUT I2 + // carry in = LUT I3 + // LUT_INIT[0] = 0 + // LUT_INIT[1] = 0 + // LUT_INIT[2] = 0 + // LUT_INIT[3] = 0 + // LUT_INIT[4] = 0 + // LUT_INIT[5] = 0 + // LUT_INIT[6] = 0 + // LUT_INIT[7] = 0 + // LUT_INIT[8] = 1 + // LUT_INIT[9] = 1 + // LUT_INIT[10] = 1 + // LUT_INIT[11] = 1 + // LUT_INIT[12] = 1 + // LUT_INIT[13] = 1 + // LUT_INIT[14] = 1 + // LUT_INIT[15] = 1 + + (* keep *) SB_LUT4 lut( .O(delay_tap), .I0(const_zero), .I1(const_zero), + .I2(const_one), .I3(chainin)); + + //TODO: is this the right way round?? + defparam lut.LUT_INIT=16'hFF00; + + +endmodule // delay_element +EOT + +synth_ice40 +select -assert-count 1 t:SB_LUT4 +select -assert-count 1 t:SB_CARRY +select -assert-count 1 t:SB_CARRY a:keep %i From 5897b918b3735e9bd621966fdcf0c52bb11cebc2 Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Tue, 3 Dec 2019 14:48:11 -0800 Subject: [PATCH 02/14] ice40_wrapcarry to preserve SB_CARRY's attributes --- passes/pmgen/ice40_wrapcarry.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc index 69ef3cd82..66054ea42 100644 --- a/passes/pmgen/ice40_wrapcarry.cc +++ b/passes/pmgen/ice40_wrapcarry.cc @@ -50,6 +50,8 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) cell->setPort("\\O", st.lut->getPort("\\O")); cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT")); + cell->attributes = std::move(st.carry->attributes); + pm.autoremove(st.carry); pm.autoremove(st.lut); } From 1ea9ce0ad7d2a44b88353be3a44eedf306ac786e Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Tue, 3 Dec 2019 14:48:39 -0800 Subject: [PATCH 03/14] ice40_opt to ignore (* keep *) -ed cells --- techlibs/ice40/ice40_opt.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index ea56d3f4d..aa5c43649 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -41,6 +41,11 @@ static void run_ice40_opts(Module *module) for (auto cell : module->selected_cells()) { + if (!cell->type.in("\\SB_LUT4", "\\SB_CARRY", "$__ICE40_CARRY_WRAPPER")) + continue; + if (cell->has_keep_attr()) + continue; + if (cell->type == "\\SB_LUT4") { sb_lut_cells.push_back(cell); From ed3f35917531e5757699261aae92135f59205bf2 Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Tue, 3 Dec 2019 14:49:10 -0800 Subject: [PATCH 04/14] $__ICE40_CARRY_WRAPPER to use _TECHMAP_REPLACE_ for SB_CARRY to preserve name and attr --- techlibs/ice40/cells_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index 662423f0a..efd763ef6 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -65,7 +65,7 @@ endmodule `ifndef NO_ADDER module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3); parameter LUT = 0; - SB_CARRY carry ( + SB_CARRY _TECHMAP_REPLACE_ ( .I0(A), .I1(B), .CI(CI), From 67f1ce2d4340c359137ac00e4ca085e6711986f3 Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Tue, 3 Dec 2019 14:51:39 -0800 Subject: [PATCH 05/14] Check SB_CARRY name also preserved --- tests/arch/ice40/ice40_opt.ys | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/arch/ice40/ice40_opt.ys b/tests/arch/ice40/ice40_opt.ys index 58c33acaa..860e2e211 100644 --- a/tests/arch/ice40/ice40_opt.ys +++ b/tests/arch/ice40/ice40_opt.ys @@ -84,3 +84,4 @@ synth_ice40 select -assert-count 1 t:SB_LUT4 select -assert-count 1 t:SB_CARRY select -assert-count 1 t:SB_CARRY a:keep %i +select -assert-count 1 t:SB_CARRY c:carry %i From d8fbf88980d6ccd22e2aa3f34c4ff2a39aeed9df Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Thu, 5 Dec 2019 07:01:02 -0800 Subject: [PATCH 06/14] Add WIP test for unwrapping $__ICE40_CARRY_WRAPPER --- tests/arch/ice40/wrapcarry.ys | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/arch/ice40/wrapcarry.ys b/tests/arch/ice40/wrapcarry.ys index 10c029e68..a4b0d357a 100644 --- a/tests/arch/ice40/wrapcarry.ys +++ b/tests/arch/ice40/wrapcarry.ys @@ -20,3 +20,33 @@ EOT ice40_wrapcarry select -assert-count 1 t:$__ICE40_CARRY_WRAPPER + +design -reset +read_verilog <<EOT +module top(input A, B, CI, output O, CO); + (* foo = "bar", answer = 42 *) + SB_CARRY carry ( + .I0(A), + .I1(B), + .CI(CI), + .CO(CO) + ); + (* keep, blah="blah", answer = 43 *) + SB_LUT4 #( + .LUT_INIT(16'b 0110_1001_1001_0110) + ) adder ( + .I0(1'b0), + .I1(A), + .I2(B), + .I3(1'b0), + .O(O) + ); +endmodule +EOT + +ice40_wrapcarry +select -assert-count 1 t:$__ICE40_CARRY_WRAPPER +select -assert-count 0 t:* t:$__ICE40_CARRY_WRAPPER %d +select -assert-count 1 a:foo=bar a:answer=42 %i a:keep %i a:blah=blah %i +techmap -map +/ice40/cells_map.v +#TODO: Check unwrapped attributes From a7e0cca48003dbb212326c37c0b8a5580c2e6d2c Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Thu, 5 Dec 2019 07:01:18 -0800 Subject: [PATCH 07/14] Merge SB_CARRY+SB_LUT4's attributes when creating $__ICE40_CARRY_WRAPPER --- passes/pmgen/ice40_wrapcarry.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc index 66054ea42..b84790d8f 100644 --- a/passes/pmgen/ice40_wrapcarry.cc +++ b/passes/pmgen/ice40_wrapcarry.cc @@ -51,6 +51,7 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT")); cell->attributes = std::move(st.carry->attributes); + cell->attributes.insert(st.lut->attributes.begin(), st.lut->attributes.end()); pm.autoremove(st.carry); pm.autoremove(st.lut); From 946d5854c0b2e63a3757a0fbdf41276255967bc8 Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Fri, 6 Dec 2019 17:27:47 -0800 Subject: [PATCH 08/14] Drop keep=0 attributes on SB_CARRY --- passes/pmgen/ice40_wrapcarry.cc | 8 ++++++++ tests/arch/ice40/wrapcarry.ys | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc index b84790d8f..8b3cf38bb 100644 --- a/passes/pmgen/ice40_wrapcarry.cc +++ b/passes/pmgen/ice40_wrapcarry.cc @@ -51,6 +51,9 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT")); cell->attributes = std::move(st.carry->attributes); + auto it = cell->attributes.find(ID::keep); + if (it != cell->attributes.end() && !it->second.as_bool()) + cell->attributes.erase(it); cell->attributes.insert(st.lut->attributes.begin(), st.lut->attributes.end()); pm.autoremove(st.carry); @@ -69,6 +72,11 @@ struct Ice40WrapCarryPass : public Pass { log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n"); log("mapping."); log("\n"); + log("Attributes on both cells will be merged, with SB_CARRY attributes having priority\n"); + log("over SB_LUT4 attributes, except when (* keep *) attributes present on the SB_CARRY4\n"); + log("that logically evaluate to false will be dropped (thus allowing the keep attribute,\n"); + log("if any, on the SB_LUT4 to be adopted).\n"); + log("\n"); } void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { diff --git a/tests/arch/ice40/wrapcarry.ys b/tests/arch/ice40/wrapcarry.ys index a4b0d357a..579335b27 100644 --- a/tests/arch/ice40/wrapcarry.ys +++ b/tests/arch/ice40/wrapcarry.ys @@ -24,7 +24,7 @@ select -assert-count 1 t:$__ICE40_CARRY_WRAPPER design -reset read_verilog <<EOT module top(input A, B, CI, output O, CO); - (* foo = "bar", answer = 42 *) + (* foo = "bar", answer = 42, keep=0 *) SB_CARRY carry ( .I0(A), .I1(B), @@ -47,6 +47,6 @@ EOT ice40_wrapcarry select -assert-count 1 t:$__ICE40_CARRY_WRAPPER select -assert-count 0 t:* t:$__ICE40_CARRY_WRAPPER %d -select -assert-count 1 a:foo=bar a:answer=42 %i a:keep %i a:blah=blah %i +select -assert-count 1 a:foo=bar a:answer=42 %i a:keep=1 %i a:blah=blah %i techmap -map +/ice40/cells_map.v #TODO: Check unwrapped attributes From e05372778a26e5cbc5166f208eddc6a1b42ed198 Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Mon, 9 Dec 2019 11:48:28 -0800 Subject: [PATCH 09/14] ice40_wrapcarry to really preserve attributes via -unwrap option --- passes/pmgen/ice40_wrapcarry.cc | 72 ++++++++++++++----- techlibs/ice40/cells_map.v | 19 ----- techlibs/ice40/synth_ice40.cc | 1 + .../{wrapcarry.ys => ice40_wrapcarry.ys} | 8 ++- 4 files changed, 61 insertions(+), 39 deletions(-) rename tests/arch/ice40/{wrapcarry.ys => ice40_wrapcarry.ys} (70%) diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc index 8b3cf38bb..522c8c363 100644 --- a/passes/pmgen/ice40_wrapcarry.cc +++ b/passes/pmgen/ice40_wrapcarry.cc @@ -50,11 +50,13 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) cell->setPort("\\O", st.lut->getPort("\\O")); cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT")); - cell->attributes = std::move(st.carry->attributes); - auto it = cell->attributes.find(ID::keep); - if (it != cell->attributes.end() && !it->second.as_bool()) - cell->attributes.erase(it); - cell->attributes.insert(st.lut->attributes.begin(), st.lut->attributes.end()); + for (const auto &a : st.carry->attributes) + cell->attributes[stringf("\\SB_CARRY.%s", a.first.c_str())] = a.second; + for (const auto &a : st.lut->attributes) + cell->attributes[stringf("\\SB_LUT4.%s", a.first.c_str())] = a.second; + cell->attributes[ID(SB_LUT4.name)] = Const(st.lut->name.str()); + if (st.carry->get_bool_attribute(ID::keep) || st.lut->get_bool_attribute(ID::keep)) + cell->attributes[ID::keep] = true; pm.autoremove(st.carry); pm.autoremove(st.lut); @@ -68,33 +70,69 @@ struct Ice40WrapCarryPass : public Pass { log("\n"); log(" ice40_wrapcarry [selection]\n"); log("\n"); - log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUTs,\n"); + log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUT4s,\n"); log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n"); - log("mapping."); + log("mapping.\n"); log("\n"); - log("Attributes on both cells will be merged, with SB_CARRY attributes having priority\n"); - log("over SB_LUT4 attributes, except when (* keep *) attributes present on the SB_CARRY4\n"); - log("that logically evaluate to false will be dropped (thus allowing the keep attribute,\n"); - log("if any, on the SB_LUT4 to be adopted).\n"); + log("Attributes on both cells will have their names prefixed with 'SB_CARRY.' or\n"); + log("'SB_LUT4.' and attached to the wrapping cell.\n"); + log("A (* keep *) attribute on either cell will be logically OR-ed together.\n"); + log("\n"); + log(" -unwrap\n"); + log(" unwrap $__ICE40_CARRY_WRAPPER cells back into SB_CARRYs and SB_LUT4s,\n"); + log(" including restoring their attributes.\n"); log("\n"); } void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { + bool unwrap = false; + log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - // if (args[argidx] == "-singleton") { - // singleton_mode = true; - // continue; - // } + if (args[argidx] == "-unwrap") { + unwrap = true; + continue; + } break; } extra_args(args, argidx, design); - for (auto module : design->selected_modules()) - ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry); + for (auto module : design->selected_modules()) { + if (!unwrap) + ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry); + else { + for (auto cell : module->selected_cells()) { + if (cell->type != ID($__ICE40_CARRY_WRAPPER)) + continue; + + auto carry = module->addCell(NEW_ID, ID(SB_CARRY)); + carry->setPort(ID(I0), cell->getPort(ID(A))); + carry->setPort(ID(I1), cell->getPort(ID(B))); + carry->setPort(ID(CI), cell->getPort(ID(CO))); + module->swap_names(carry, cell); + auto lut = module->addCell(cell->attributes.at(ID(SB_LUT4.name)).decode_string(), ID(SB_LUT4)); + lut->setParam(ID(WIDTH), 4); + lut->setParam(ID(LUT), cell->getParam(ID(LUT))); + lut->setPort(ID(A), { cell->getPort(ID(I0)), cell->getPort(ID(A)), cell->getPort(ID(B)), cell->getPort(ID(I3)) }); + lut->setPort(ID(Y), cell->getPort(ID(O))); + + for (const auto &a : cell->attributes) + if (a.first.begins_with("\\SB_CARRY.\\")) + carry->attributes[a.first.c_str() + strlen("\\SB_CARRY.")] = a.second; + else if (a.first.begins_with("\\SB_LUT4.\\")) + lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second; + else if (a.first.in(ID(SB_LUT4.name), ID::keep)) + continue; + else + log_abort(); + + module->remove(cell); + } + } + } } } Ice40WrapCarryPass; diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index efd763ef6..759549e30 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -61,22 +61,3 @@ module \$lut (A, Y); endgenerate endmodule `endif - -`ifndef NO_ADDER -module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3); - parameter LUT = 0; - SB_CARRY _TECHMAP_REPLACE_ ( - .I0(A), - .I1(B), - .CI(CI), - .CO(CO) - ); - \$lut #( - .WIDTH(4), - .LUT(LUT) - ) lut ( - .A({I0,A,B,I3}), - .Y(O) - ); -endmodule -`endif diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 901194b06..ed7a16c08 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -363,6 +363,7 @@ struct SynthIce40Pass : public ScriptPass else run(abc + " -dress -lut 4", "(skip if -noabc)"); } + run("ice40_wrapcarry -unwrap"); run("techmap -D NO_LUT -map +/ice40/cells_map.v"); run("clean"); run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0"); diff --git a/tests/arch/ice40/wrapcarry.ys b/tests/arch/ice40/ice40_wrapcarry.ys similarity index 70% rename from tests/arch/ice40/wrapcarry.ys rename to tests/arch/ice40/ice40_wrapcarry.ys index 579335b27..fb9fccc3a 100644 --- a/tests/arch/ice40/wrapcarry.ys +++ b/tests/arch/ice40/ice40_wrapcarry.ys @@ -47,6 +47,8 @@ EOT ice40_wrapcarry select -assert-count 1 t:$__ICE40_CARRY_WRAPPER select -assert-count 0 t:* t:$__ICE40_CARRY_WRAPPER %d -select -assert-count 1 a:foo=bar a:answer=42 %i a:keep=1 %i a:blah=blah %i -techmap -map +/ice40/cells_map.v -#TODO: Check unwrapped attributes +select -assert-count 1 a:keep=1 a:SB_CARRY.\foo=bar %i a:SB_CARRY.\answer=42 %i a:SB_LUT4.\blah=blah %i a:SB_LUT4.\answer=43 %i + +ice40_wrapcarry -unwrap +select -assert-count 1 c:carry a:src=<<EOT:3 %i a:keep=0 %i a:foo=bar %i a:answer=42 %i +select -assert-count 1 c:adder a:src=<<EOT:10 %i a:keep=1 %i a:blah=blah %i a:answer=43 %i From 500ed9b501386b38faf6388b43c42abdbc0ee3ec Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Mon, 9 Dec 2019 12:45:22 -0800 Subject: [PATCH 10/14] Sensitive to direct inst of $__ICE40_CARRY_WRAPPER; recreate SB_LUT4 --- passes/pmgen/ice40_wrapcarry.cc | 18 +++++++++++------- techlibs/ice40/arith_map.v | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc index 522c8c363..8c953308a 100644 --- a/passes/pmgen/ice40_wrapcarry.cc +++ b/passes/pmgen/ice40_wrapcarry.cc @@ -111,20 +111,24 @@ struct Ice40WrapCarryPass : public Pass { auto carry = module->addCell(NEW_ID, ID(SB_CARRY)); carry->setPort(ID(I0), cell->getPort(ID(A))); carry->setPort(ID(I1), cell->getPort(ID(B))); - carry->setPort(ID(CI), cell->getPort(ID(CO))); + carry->setPort(ID(CI), cell->getPort(ID(CI))); + carry->setPort(ID(CO), cell->getPort(ID(CO))); module->swap_names(carry, cell); - auto lut = module->addCell(cell->attributes.at(ID(SB_LUT4.name)).decode_string(), ID(SB_LUT4)); - lut->setParam(ID(WIDTH), 4); - lut->setParam(ID(LUT), cell->getParam(ID(LUT))); - lut->setPort(ID(A), { cell->getPort(ID(I0)), cell->getPort(ID(A)), cell->getPort(ID(B)), cell->getPort(ID(I3)) }); - lut->setPort(ID(Y), cell->getPort(ID(O))); + auto lut_name = cell->attributes.at(ID(SB_LUT4.name), Const(NEW_ID.str())).decode_string(); + auto lut = module->addCell(lut_name, ID(SB_LUT4)); + lut->setParam(ID(LUT_INIT), cell->getParam(ID(LUT))); + lut->setPort(ID(I0), cell->getPort(ID(I0))); + lut->setPort(ID(I1), cell->getPort(ID(A))); + lut->setPort(ID(I2), cell->getPort(ID(B))); + lut->setPort(ID(I3), cell->getPort(ID(I3))); + lut->setPort(ID(O), cell->getPort(ID(O))); for (const auto &a : cell->attributes) if (a.first.begins_with("\\SB_CARRY.\\")) carry->attributes[a.first.c_str() + strlen("\\SB_CARRY.")] = a.second; else if (a.first.begins_with("\\SB_LUT4.\\")) lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second; - else if (a.first.in(ID(SB_LUT4.name), ID::keep)) + else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID(module_not_derived), ID(src))) continue; else log_abort(); diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v index 26b24db9e..00a07247b 100644 --- a/techlibs/ice40/arith_map.v +++ b/techlibs/ice40/arith_map.v @@ -50,7 +50,7 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO); // A[2]: 1111 0000 1111 0000 // A[3]: 1111 1111 0000 0000 .LUT(16'b 0110_1001_1001_0110) - ) fadd ( + ) carry ( .A(AA[i]), .B(BB[i]), .CI(C[i]), From bbdf2452b3bf5bd5d835fc1d6936568cb0a32a1a Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Mon, 9 Dec 2019 13:27:09 -0800 Subject: [PATCH 11/14] -unwrap to create $lut not SB_LUT4 for opt_lut --- passes/pmgen/ice40_wrapcarry.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc index 8c953308a..4bddece30 100644 --- a/passes/pmgen/ice40_wrapcarry.cc +++ b/passes/pmgen/ice40_wrapcarry.cc @@ -115,13 +115,11 @@ struct Ice40WrapCarryPass : public Pass { carry->setPort(ID(CO), cell->getPort(ID(CO))); module->swap_names(carry, cell); auto lut_name = cell->attributes.at(ID(SB_LUT4.name), Const(NEW_ID.str())).decode_string(); - auto lut = module->addCell(lut_name, ID(SB_LUT4)); - lut->setParam(ID(LUT_INIT), cell->getParam(ID(LUT))); - lut->setPort(ID(I0), cell->getPort(ID(I0))); - lut->setPort(ID(I1), cell->getPort(ID(A))); - lut->setPort(ID(I2), cell->getPort(ID(B))); - lut->setPort(ID(I3), cell->getPort(ID(I3))); - lut->setPort(ID(O), cell->getPort(ID(O))); + auto lut = module->addCell(lut_name, ID($lut)); + lut->setParam(ID(WIDTH), 4); + lut->setParam(ID(LUT), cell->getParam(ID(LUT))); + lut->setPort(ID(A), {cell->getPort(ID(I0)), cell->getPort(ID(A)), cell->getPort(ID(B)), cell->getPort(ID(I3)) }); + lut->setPort(ID(Y), cell->getPort(ID(O))); for (const auto &a : cell->attributes) if (a.first.begins_with("\\SB_CARRY.\\")) From eff858cd33403a13736ac74cce6964648306e594 Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Mon, 9 Dec 2019 14:20:35 -0800 Subject: [PATCH 12/14] unmap $__ICE40_CARRY_WRAPPER in test --- tests/arch/ice40/ice40_opt.ys | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/arch/ice40/ice40_opt.ys b/tests/arch/ice40/ice40_opt.ys index 860e2e211..5186d4800 100644 --- a/tests/arch/ice40/ice40_opt.ys +++ b/tests/arch/ice40/ice40_opt.ys @@ -1,3 +1,23 @@ +read_verilog -icells -formal <<EOT +module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3); + parameter LUT = 0; + SB_CARRY carry ( + .I0(A), + .I1(B), + .CI(CI), + .CO(CO) + ); + \$lut #( + .WIDTH(4), + .LUT(LUT) + ) lut ( + .A({I0,A,B,I3}), + .Y(O) + ); +endmodule +EOT +design -stash unmap + read_verilog -icells -formal <<EOT module top(input CI, I0, output [1:0] CO, output O); wire A = 1'b0, B = 1'b0; @@ -20,7 +40,7 @@ module top(input CI, I0, output [1:0] CO, output O); endmodule EOT -equiv_opt -assert -map +/ice40/cells_map.v -map +/ice40/cells_sim.v ice40_opt +equiv_opt -assert -map %unmap -map +/ice40/cells_sim.v ice40_opt design -load postopt select -assert-count 1 t:* select -assert-count 1 t:$lut From 36a88be609b942f9bc1a5e44ecdbe432a3fa56e8 Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Mon, 9 Dec 2019 14:28:54 -0800 Subject: [PATCH 13/14] ice40_wrapcarry -unwrap to preserve 'src' attribute --- passes/pmgen/ice40_wrapcarry.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc index 4bddece30..6e154147f 100644 --- a/passes/pmgen/ice40_wrapcarry.cc +++ b/passes/pmgen/ice40_wrapcarry.cc @@ -121,16 +121,24 @@ struct Ice40WrapCarryPass : public Pass { lut->setPort(ID(A), {cell->getPort(ID(I0)), cell->getPort(ID(A)), cell->getPort(ID(B)), cell->getPort(ID(I3)) }); lut->setPort(ID(Y), cell->getPort(ID(O))); + Const src; for (const auto &a : cell->attributes) if (a.first.begins_with("\\SB_CARRY.\\")) carry->attributes[a.first.c_str() + strlen("\\SB_CARRY.")] = a.second; else if (a.first.begins_with("\\SB_LUT4.\\")) lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second; - else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID(module_not_derived), ID(src))) + else if (a.first == ID(src)) + src = a.second; + else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID(module_not_derived))) continue; else log_abort(); + if (!src.empty()) { + carry->attributes.insert(std::make_pair(ID(src), src)); + lut->attributes.insert(std::make_pair(ID(src), src)); + } + module->remove(cell); } } From fb203d2a2c02c3df1a2c6a92ec196e579495c8d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung <eddie@fpgeh.com> Date: Mon, 9 Dec 2019 14:29:29 -0800 Subject: [PATCH 14/14] ice40_opt to restore attributes/name when unwrapping --- techlibs/ice40/ice40_opt.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index aa5c43649..371ceb623 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -117,6 +117,21 @@ static void run_ice40_opts(Module *module) if (GetSize(replacement_output)) { optimized_co.insert(sigmap(cell->getPort("\\CO")[0])); + auto it = cell->attributes.find(ID(SB_LUT4.name)); + if (it != cell->attributes.end()) { + module->rename(cell, it->second.decode_string()); + decltype(Cell::attributes) new_attr; + for (const auto &a : cell->attributes) + if (a.first.begins_with("\\SB_LUT4.\\")) + new_attr[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second; + else if (a.first == ID(src)) + new_attr.insert(std::make_pair(a.first, a.second)); + else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID(module_not_derived))) + continue; + else + log_abort(); + cell->attributes = std::move(new_attr); + } module->connect(cell->getPort("\\CO")[0], replacement_output); module->design->scratchpad_set_bool("opt.did_something", true); log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",