aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddie Hung <eddie@fpgeh.com>2019-12-09 17:38:48 -0800
committerGitHub <noreply@github.com>2019-12-09 17:38:48 -0800
commit7e5602ad17b20f14e56fc4c64198ca2d576917df (patch)
tree5127cc0a4159e23f2e8fcdabcea4b792062ea09f
parentecb0c68f0751b3bd97f8da94e7bd2258987d58e1 (diff)
parentfb203d2a2c02c3df1a2c6a92ec196e579495c8d4 (diff)
downloadyosys-7e5602ad17b20f14e56fc4c64198ca2d576917df.tar.gz
yosys-7e5602ad17b20f14e56fc4c64198ca2d576917df.tar.bz2
yosys-7e5602ad17b20f14e56fc4c64198ca2d576917df.zip
Merge pull request #1545 from YosysHQ/eddie/ice40_wrapcarry_attr
Preserve SB_CARRY name and attributes when using $__ICE40_CARRY_WRAPPER
-rw-r--r--passes/pmgen/ice40_wrapcarry.cc75
-rw-r--r--techlibs/ice40/arith_map.v2
-rw-r--r--techlibs/ice40/cells_map.v19
-rw-r--r--techlibs/ice40/ice40_opt.cc20
-rw-r--r--techlibs/ice40/synth_ice40.cc1
-rw-r--r--tests/arch/ice40/ice40_opt.ys83
-rw-r--r--tests/arch/ice40/ice40_wrapcarry.ys54
-rw-r--r--tests/arch/ice40/wrapcarry.ys22
8 files changed, 225 insertions, 51 deletions
diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc
index 69ef3cd82..6e154147f 100644
--- a/passes/pmgen/ice40_wrapcarry.cc
+++ b/passes/pmgen/ice40_wrapcarry.cc
@@ -50,6 +50,14 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
cell->setPort("\\O", st.lut->getPort("\\O"));
cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT"));
+ 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);
}
@@ -62,28 +70,79 @@ 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 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(CI)));
+ 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($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)));
+
+ 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 == 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);
+ }
+ }
+ }
}
} Ice40WrapCarryPass;
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]),
diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v
index 662423f0a..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 carry (
- .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/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index ea56d3f4d..371ceb623 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);
@@ -112,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",
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/ice40_opt.ys b/tests/arch/ice40/ice40_opt.ys
index b17c69c91..5186d4800 100644
--- a/tests/arch/ice40/ice40_opt.ys
+++ b/tests/arch/ice40/ice40_opt.ys
@@ -1,4 +1,24 @@
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;
\$__ICE40_CARRY_WRAPPER #(
@@ -20,7 +40,68 @@ 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
+
+# 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
+select -assert-count 1 t:SB_CARRY c:carry %i
diff --git a/tests/arch/ice40/ice40_wrapcarry.ys b/tests/arch/ice40/ice40_wrapcarry.ys
new file mode 100644
index 000000000..fb9fccc3a
--- /dev/null
+++ b/tests/arch/ice40/ice40_wrapcarry.ys
@@ -0,0 +1,54 @@
+read_verilog <<EOT
+module top(input A, B, CI, output O, CO);
+ SB_CARRY carry (
+ .I0(A),
+ .I1(B),
+ .CI(CI),
+ .CO(CO)
+ );
+ 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
+
+design -reset
+read_verilog <<EOT
+module top(input A, B, CI, output O, CO);
+ (* foo = "bar", answer = 42, keep=0 *)
+ 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: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
diff --git a/tests/arch/ice40/wrapcarry.ys b/tests/arch/ice40/wrapcarry.ys
deleted file mode 100644
index 10c029e68..000000000
--- a/tests/arch/ice40/wrapcarry.ys
+++ /dev/null
@@ -1,22 +0,0 @@
-read_verilog <<EOT
-module top(input A, B, CI, output O, CO);
- SB_CARRY carry (
- .I0(A),
- .I1(B),
- .CI(CI),
- .CO(CO)
- );
- 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