3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-12 20:18:20 +00:00

Merge remote-tracking branch 'origin/master' into xaig_dff

This commit is contained in:
Eddie Hung 2019-12-12 14:57:17 -08:00
commit bea15b537b
18 changed files with 238 additions and 64 deletions

View file

@ -364,16 +364,16 @@ Verilog Attributes and non-standard features
it as the external-facing pin of an I/O pad, and prevents ``iopadmap`` it as the external-facing pin of an I/O pad, and prevents ``iopadmap``
from inserting another pad cell on it. 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` blackbox or whitebox definition to a corresponding entry in a `abc9`
box-file. 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 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 `abc9` to preserve the integrity of carry-chains. Specifying this attribute
onto a bus port will affect only its most significant bit. 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, 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 for example, to specify the clk-to-Q delay of a flip-flop for consideration
during techmapping. during techmapping.

View file

@ -50,6 +50,14 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
cell->setPort("\\O", st.lut->getPort("\\O")); cell->setPort("\\O", st.lut->getPort("\\O"));
cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT")); 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.carry);
pm.autoremove(st.lut); pm.autoremove(st.lut);
} }
@ -62,28 +70,79 @@ struct Ice40WrapCarryPass : public Pass {
log("\n"); log("\n");
log(" ice40_wrapcarry [selection]\n"); log(" ice40_wrapcarry [selection]\n");
log("\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("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"); log("\n");
} }
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE 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"); log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\n");
size_t argidx; size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) for (argidx = 1; argidx < args.size(); argidx++)
{ {
// if (args[argidx] == "-singleton") { if (args[argidx] == "-unwrap") {
// singleton_mode = true; unwrap = true;
// continue; continue;
// } }
break; break;
} }
extra_args(args, argidx, design); extra_args(args, argidx, design);
for (auto module : design->selected_modules()) for (auto module : design->selected_modules()) {
ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry); 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; } Ice40WrapCarryPass;

View file

@ -1,12 +1,12 @@
// Diamond flip-flops // 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 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 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 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 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 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 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 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 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 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 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 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

View file

@ -50,7 +50,7 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);
// A[2]: 1111 0000 1111 0000 // A[2]: 1111 0000 1111 0000
// A[3]: 1111 1111 0000 0000 // A[3]: 1111 1111 0000 0000
.LUT(16'b 0110_1001_1001_0110) .LUT(16'b 0110_1001_1001_0110)
) fadd ( ) carry (
.A(AA[i]), .A(AA[i]),
.B(BB[i]), .B(BB[i]),
.CI(C[i]), .CI(C[i]),

View file

@ -61,22 +61,3 @@ module \$lut (A, Y);
endgenerate endgenerate
endmodule endmodule
`endif `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

View file

@ -41,6 +41,11 @@ static void run_ice40_opts(Module *module)
for (auto cell : module->selected_cells()) 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") if (cell->type == "\\SB_LUT4")
{ {
sb_lut_cells.push_back(cell); sb_lut_cells.push_back(cell);
@ -112,6 +117,21 @@ static void run_ice40_opts(Module *module)
if (GetSize(replacement_output)) { if (GetSize(replacement_output)) {
optimized_co.insert(sigmap(cell->getPort("\\CO")[0])); 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->connect(cell->getPort("\\CO")[0], replacement_output);
module->design->scratchpad_set_bool("opt.did_something", true); 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", log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",

View file

@ -363,6 +363,7 @@ struct SynthIce40Pass : public ScriptPass
else else
run(abc + " -dress -lut 4", "(skip if -noabc)"); run(abc + " -dress -lut 4", "(skip if -noabc)");
} }
run("ice40_wrapcarry -unwrap");
run("techmap -D NO_LUT -map +/ice40/cells_map.v"); run("techmap -D NO_LUT -map +/ice40/cells_map.v");
run("clean"); run("clean");
run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0"); run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");

View file

@ -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)) $(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 # Add the cell models and mappings for the VQM backend
families := max10 a10gx cyclonev cyclone10 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_sim.v)))
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.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)) #$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v))

View file

@ -36,10 +36,10 @@ struct SynthIntelPass : public ScriptPass {
log("\n"); log("\n");
log("This command runs synthesis for Intel FPGAs.\n"); log("This command runs synthesis for Intel FPGAs.\n");
log("\n"); log("\n");
log(" -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n"); log(" -family <max10 | arria10gx | cyclone10lp | cyclonev | cycloneiv | cycloneive>\n");
log(" generate the synthesis netlist for the specified 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(" 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(" Cyclone V and Arria 10 GX devices are experimental.\n");
log("\n"); log("\n");
log(" -top <module>\n"); log(" -top <module>\n");
@ -148,11 +148,11 @@ struct SynthIntelPass : public ScriptPass {
if (!design->full_selection()) if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n"); log_cmd_error("This command only operates on fully selected designs!\n");
if (family_opt != "max10" && if (family_opt != "max10" &&
family_opt != "a10gx" && family_opt != "arria10gx" &&
family_opt != "cyclonev" && family_opt != "cyclonev" &&
family_opt != "cycloneiv" && family_opt != "cycloneiv" &&
family_opt != "cycloneive" && family_opt != "cycloneive" &&
family_opt != "cyclone10") family_opt != "cyclone10lp")
log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str()); log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str());
log_header(design, "Executing SYNTH_INTEL pass.\n"); log_header(design, "Executing SYNTH_INTEL pass.\n");
@ -214,7 +214,7 @@ struct SynthIntelPass : public ScriptPass {
} }
if (check_label("map_luts")) { 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" : "")); run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));
else else
run("abc -lut 4" + string(retime ? " -dff" : "")); run("abc -lut 4" + string(retime ? " -dff" : ""));

View file

@ -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 read_verilog -icells -formal <<EOT
module top(input CI, I0, output [1:0] CO, output O); module top(input CI, I0, output [1:0] CO, output O);
wire A = 1'b0, B = 1'b0; wire A = 1'b0, B = 1'b0;
@ -20,7 +40,68 @@ module top(input CI, I0, output [1:0] CO, output O);
endmodule endmodule
EOT 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 design -load postopt
select -assert-count 1 t:* select -assert-count 1 t:*
select -assert-count 1 t:$lut 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

View file

@ -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

View file

@ -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