From 8de17877d4073a6e593ea650b8eca0488f653d24 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Dec 2019 14:48:00 -0800 Subject: [PATCH 01/19] 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 < Date: Tue, 3 Dec 2019 14:48:11 -0800 Subject: [PATCH 02/19] 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 Date: Tue, 3 Dec 2019 14:48:39 -0800 Subject: [PATCH 03/19] 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 Date: Tue, 3 Dec 2019 14:49:10 -0800 Subject: [PATCH 04/19] $__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 Date: Tue, 3 Dec 2019 14:51:39 -0800 Subject: [PATCH 05/19] 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 Date: Thu, 5 Dec 2019 07:01:02 -0800 Subject: [PATCH 06/19] 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 < Date: Thu, 5 Dec 2019 07:01:18 -0800 Subject: [PATCH 07/19] 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 Date: Fri, 6 Dec 2019 17:27:47 -0800 Subject: [PATCH 08/19] 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 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 < Date: Mon, 9 Dec 2019 11:48:28 -0800 Subject: [PATCH 09/19] 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 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=< Date: Mon, 9 Dec 2019 12:45:22 -0800 Subject: [PATCH 10/19] 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 Date: Mon, 9 Dec 2019 13:27:09 -0800 Subject: [PATCH 11/19] -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 Date: Mon, 9 Dec 2019 14:20:35 -0800 Subject: [PATCH 12/19] 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 < Date: Mon, 9 Dec 2019 14:28:54 -0800 Subject: [PATCH 13/19] 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 Date: Mon, 9 Dec 2019 14:29:29 -0800 Subject: [PATCH 14/19] 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", From eab3272cdeed697bdb9664c2d8a133d336addb7c Mon Sep 17 00:00:00 2001 From: Dan Ravensloft Date: Tue, 10 Dec 2019 13:31:45 +0000 Subject: [PATCH 15/19] synth_intel: cyclone10 -> cyclone10lp --- techlibs/intel/Makefile.inc | 2 +- techlibs/intel/{cyclone10 => cyclone10lp}/cells_arith.v | 0 techlibs/intel/{cyclone10 => cyclone10lp}/cells_map.v | 0 techlibs/intel/{cyclone10 => cyclone10lp}/cells_sim.v | 0 techlibs/intel/synth_intel.cc | 6 +++--- 5 files changed, 4 insertions(+), 4 deletions(-) rename techlibs/intel/{cyclone10 => cyclone10lp}/cells_arith.v (100%) rename techlibs/intel/{cyclone10 => cyclone10lp}/cells_map.v (100%) rename techlibs/intel/{cyclone10 => cyclone10lp}/cells_sim.v (100%) diff --git a/techlibs/intel/Makefile.inc b/techlibs/intel/Makefile.inc index 4e8f423c8..92a83b5af 100644 --- a/techlibs/intel/Makefile.inc +++ b/techlibs/intel/Makefile.inc @@ -7,7 +7,7 @@ $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k. $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v)) # Add the cell models and mappings for the VQM backend -families := max10 a10gx cyclonev cyclone10 cycloneiv cycloneive +families := max10 a10gx cyclonev cyclone10lp cycloneiv cycloneive $(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v))) $(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.v))) #$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v)) diff --git a/techlibs/intel/cyclone10/cells_arith.v b/techlibs/intel/cyclone10lp/cells_arith.v similarity index 100% rename from techlibs/intel/cyclone10/cells_arith.v rename to techlibs/intel/cyclone10lp/cells_arith.v diff --git a/techlibs/intel/cyclone10/cells_map.v b/techlibs/intel/cyclone10lp/cells_map.v similarity index 100% rename from techlibs/intel/cyclone10/cells_map.v rename to techlibs/intel/cyclone10lp/cells_map.v diff --git a/techlibs/intel/cyclone10/cells_sim.v b/techlibs/intel/cyclone10lp/cells_sim.v similarity index 100% rename from techlibs/intel/cyclone10/cells_sim.v rename to techlibs/intel/cyclone10lp/cells_sim.v diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index e5dc1adc7..5e6d2df2c 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -36,10 +36,10 @@ struct SynthIntelPass : public ScriptPass { log("\n"); log("This command runs synthesis for Intel FPGAs.\n"); log("\n"); - log(" -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n"); + log(" -family \n"); log(" generate the synthesis netlist for the specified family.\n"); log(" MAX10 is the default target if no family argument specified.\n"); - log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n"); + log(" For Cyclone IV GX devices, use cycloneiv argument; for Cyclone IV E, use cycloneive.\n"); log(" Cyclone V and Arria 10 GX devices are experimental.\n"); log("\n"); log(" -top \n"); @@ -152,7 +152,7 @@ struct SynthIntelPass : public ScriptPass { family_opt != "cyclonev" && family_opt != "cycloneiv" && family_opt != "cycloneive" && - family_opt != "cyclone10") + family_opt != "cyclone10lp") log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str()); log_header(design, "Executing SYNTH_INTEL pass.\n"); From 85a14895ca31ec8c34bf5c296a5740a798b06693 Mon Sep 17 00:00:00 2001 From: Dan Ravensloft Date: Tue, 10 Dec 2019 13:40:32 +0000 Subject: [PATCH 16/19] synth_intel: a10gx -> arria10gx --- techlibs/intel/Makefile.inc | 2 +- techlibs/intel/{a10gx => arria10gx}/cells_arith.v | 0 techlibs/intel/{a10gx => arria10gx}/cells_map.v | 0 techlibs/intel/{a10gx => arria10gx}/cells_sim.v | 0 techlibs/intel/synth_intel.cc | 6 +++--- 5 files changed, 4 insertions(+), 4 deletions(-) rename techlibs/intel/{a10gx => arria10gx}/cells_arith.v (100%) rename techlibs/intel/{a10gx => arria10gx}/cells_map.v (100%) rename techlibs/intel/{a10gx => arria10gx}/cells_sim.v (100%) diff --git a/techlibs/intel/Makefile.inc b/techlibs/intel/Makefile.inc index 92a83b5af..d97a9b58f 100644 --- a/techlibs/intel/Makefile.inc +++ b/techlibs/intel/Makefile.inc @@ -7,7 +7,7 @@ $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k. $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v)) # Add the cell models and mappings for the VQM backend -families := max10 a10gx cyclonev cyclone10lp cycloneiv cycloneive +families := max10 arria10gx cyclonev cyclone10lp cycloneiv cycloneive $(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v))) $(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.v))) #$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v)) diff --git a/techlibs/intel/a10gx/cells_arith.v b/techlibs/intel/arria10gx/cells_arith.v similarity index 100% rename from techlibs/intel/a10gx/cells_arith.v rename to techlibs/intel/arria10gx/cells_arith.v diff --git a/techlibs/intel/a10gx/cells_map.v b/techlibs/intel/arria10gx/cells_map.v similarity index 100% rename from techlibs/intel/a10gx/cells_map.v rename to techlibs/intel/arria10gx/cells_map.v diff --git a/techlibs/intel/a10gx/cells_sim.v b/techlibs/intel/arria10gx/cells_sim.v similarity index 100% rename from techlibs/intel/a10gx/cells_sim.v rename to techlibs/intel/arria10gx/cells_sim.v diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index 5e6d2df2c..c8c690e45 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -36,7 +36,7 @@ struct SynthIntelPass : public ScriptPass { log("\n"); log("This command runs synthesis for Intel FPGAs.\n"); log("\n"); - log(" -family \n"); + log(" -family \n"); log(" generate the synthesis netlist for the specified family.\n"); log(" MAX10 is the default target if no family argument specified.\n"); log(" For Cyclone IV GX devices, use cycloneiv argument; for Cyclone IV E, use cycloneive.\n"); @@ -148,7 +148,7 @@ struct SynthIntelPass : public ScriptPass { if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); if (family_opt != "max10" && - family_opt != "a10gx" && + family_opt != "arria10gx" && family_opt != "cyclonev" && family_opt != "cycloneiv" && family_opt != "cycloneive" && @@ -214,7 +214,7 @@ struct SynthIntelPass : public ScriptPass { } if (check_label("map_luts")) { - if (family_opt == "a10gx" || family_opt == "cyclonev") + if (family_opt == "arria10gx" || family_opt == "cyclonev") run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : "")); else run("abc -lut 4" + string(retime ? " -dff" : "")); From f022645cd2564ef47a6e8cf80c1452cd25f7ace2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Dec 2019 13:02:07 -0800 Subject: [PATCH 17/19] Fix bitwidth mismatch; suppresses iverilog warning --- techlibs/ecp5/cells_ff.vh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/ecp5/cells_ff.vh b/techlibs/ecp5/cells_ff.vh index 501c1b3b2..6b745f391 100644 --- a/techlibs/ecp5/cells_ff.vh +++ b/techlibs/ecp5/cells_ff.vh @@ -1,12 +1,12 @@ // Diamond flip-flops -module FD1P3AX(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3AY(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3AX(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3AY(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .CE(SP), .DI(D), .Q(Q)); endmodule module FD1P3BX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule module FD1P3DX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule module FD1P3IX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule module FD1P3JX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1S3AX(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule -module FD1S3AY(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule +module FD1S3AX(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .DI(D), .Q(Q)); endmodule +module FD1S3AY(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .DI(D), .Q(Q)); endmodule module FD1S3BX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule module FD1S3DX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule module FD1S3IX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule From 2666482282421bb54213ba01054111eadc401373 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Dec 2019 16:38:43 -0800 Subject: [PATCH 18/19] Update README.md :: abc_ -> abc9_ --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1ce5d47ea..5cc52e842 100644 --- a/README.md +++ b/README.md @@ -364,16 +364,16 @@ Verilog Attributes and non-standard features it as the external-facing pin of an I/O pad, and prevents ``iopadmap`` from inserting another pad cell on it. -- The module attribute ``abc_box_id`` specifies a positive integer linking a +- The module attribute ``abc9_box_id`` specifies a positive integer linking a blackbox or whitebox definition to a corresponding entry in a `abc9` box-file. -- The port attribute ``abc_carry`` marks the carry-in (if an input port) and +- The port attribute ``abc9_carry`` marks the carry-in (if an input port) and carry-out (if output port) ports of a box. This information is necessary for `abc9` to preserve the integrity of carry-chains. Specifying this attribute onto a bus port will affect only its most significant bit. -- The port attribute ``abc_arrival`` specifies an integer (for output ports +- The port attribute ``abc9_arrival`` specifies an integer (for output ports only) to be used as the arrival time of this sequential port. It can be used, for example, to specify the clk-to-Q delay of a flip-flop for consideration during techmapping. From 9ab1feeaf11adb6b675ac4034e246cb137d07db9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 12 Dec 2019 14:56:15 -0800 Subject: [PATCH 19/19] 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 0eac08f3f..6fd73c1e0 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -39,8 +39,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 ( @@ -62,8 +62,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 ( @@ -84,8 +84,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 ( @@ -101,7 +101,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 (