summaryrefslogtreecommitdiff
path: root/techlibs/ice40
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/ice40')
-rw-r--r--techlibs/ice40/Makefile.inc1
-rw-r--r--techlibs/ice40/ice40_ffinit.cc38
-rw-r--r--techlibs/ice40/ice40_ffssr.cc9
-rw-r--r--techlibs/ice40/ice40_opt.cc38
-rw-r--r--techlibs/ice40/latches_map.v11
-rw-r--r--techlibs/ice40/synth_ice40.cc210
6 files changed, 150 insertions, 157 deletions
diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc
index 83009d17..14761c6c 100644
--- a/techlibs/ice40/Makefile.inc
+++ b/techlibs/ice40/Makefile.inc
@@ -23,6 +23,7 @@ techlibs/ice40/brams_init3.vh: techlibs/ice40/brams_init.mk
$(eval $(call add_share_file,share/ice40,techlibs/ice40/arith_map.v))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_map.v))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v))
diff --git a/techlibs/ice40/ice40_ffinit.cc b/techlibs/ice40/ice40_ffinit.cc
index 8c4b9a37..c914b20e 100644
--- a/techlibs/ice40/ice40_ffinit.cc
+++ b/techlibs/ice40/ice40_ffinit.cc
@@ -37,7 +37,7 @@ struct Ice40FfinitPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing ICE40_FFINIT pass (implement FF init values).\n");
+ log_header(design, "Executing ICE40_FFINIT pass (implement FF init values).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -57,6 +57,7 @@ struct Ice40FfinitPass : public Pass {
SigMap sigmap(module);
pool<Wire*> init_wires;
dict<SigBit, State> initbits;
+ dict<SigBit, SigBit> initbit_to_wire;
pool<SigBit> handled_initbits;
for (auto wire : module->selected_wires())
@@ -78,11 +79,14 @@ struct Ice40FfinitPass : public Pass {
if (initbits.count(bit)) {
if (initbits.at(bit) != val)
- log_error("Conflicting init values for signal %s.\n", log_signal(bit));
+ log_error("Conflicting init values for signal %s (%s = %s, %s = %s).\n",
+ log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val),
+ log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit)));
continue;
}
initbits[bit] = val;
+ initbit_to_wire[bit] = SigBit(wire, i);
}
}
@@ -97,17 +101,23 @@ struct Ice40FfinitPass : public Pass {
if (!sb_dff_types.count(cell->type))
continue;
- SigBit sig_d = sigmap(cell->getPort("\\D"));
- SigBit sig_q = sigmap(cell->getPort("\\Q"));
+ SigSpec sig_d = cell->getPort("\\D");
+ SigSpec sig_q = cell->getPort("\\Q");
- if (!initbits.count(sig_q))
+ if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
continue;
- State val = initbits.at(sig_q);
- handled_initbits.insert(sig_q);
+ SigBit bit_d = sigmap(sig_d[0]);
+ SigBit bit_q = sigmap(sig_q[0]);
+
+ if (!initbits.count(bit_q))
+ continue;
+
+ State val = initbits.at(bit_q);
+ handled_initbits.insert(bit_q);
log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type),
- log_signal(sig_q), val != State::S0 ? '1' : '0');
+ log_signal(bit_q), val != State::S0 ? '1' : '0');
if (val == State::S0)
continue;
@@ -127,14 +137,14 @@ struct Ice40FfinitPass : public Pass {
cell->unsetPort("\\R");
}
- Wire *new_sig_d = module->addWire(NEW_ID);
- Wire *new_sig_q = module->addWire(NEW_ID);
+ Wire *new_bit_d = module->addWire(NEW_ID);
+ Wire *new_bit_q = module->addWire(NEW_ID);
- module->addNotGate(NEW_ID, sig_d, new_sig_d);
- module->addNotGate(NEW_ID, new_sig_q, sig_q);
+ module->addNotGate(NEW_ID, bit_d, new_bit_d);
+ module->addNotGate(NEW_ID, new_bit_q, bit_q);
- cell->setPort("\\D", new_sig_d);
- cell->setPort("\\Q", new_sig_q);
+ cell->setPort("\\D", new_bit_d);
+ cell->setPort("\\Q", new_bit_q);
}
for (auto wire : init_wires)
diff --git a/techlibs/ice40/ice40_ffssr.cc b/techlibs/ice40/ice40_ffssr.cc
index 9ebc3c0d..9afbc0fc 100644
--- a/techlibs/ice40/ice40_ffssr.cc
+++ b/techlibs/ice40/ice40_ffssr.cc
@@ -35,7 +35,7 @@ struct Ice40FfssrPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing ICE40_FFSSR pass (merge synchronous set/reset into FF cells).\n");
+ log_header(design, "Executing ICE40_FFSSR pass (merge synchronous set/reset into FF cells).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -81,7 +81,12 @@ struct Ice40FfssrPass : public Pass {
for (auto cell : ff_cells)
{
- SigBit bit_d = sigmap(cell->getPort("\\D"));
+ SigSpec sig_d = cell->getPort("\\D");
+
+ if (GetSize(sig_d) < 1)
+ continue;
+
+ SigBit bit_d = sigmap(sig_d[0]);
if (sr_muxes.count(bit_d) == 0)
continue;
diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index 677ac8d7..ae72f5d6 100644
--- a/techlibs/ice40/ice40_opt.cc
+++ b/techlibs/ice40/ice40_opt.cc
@@ -26,7 +26,7 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-static void run_ice40_opts(Module *module)
+static void run_ice40_opts(Module *module, bool unlut_mode)
{
pool<SigBit> optimized_co;
vector<Cell*> sb_lut_cells;
@@ -84,6 +84,9 @@ static void run_ice40_opts(Module *module)
inbits.append(cell->getPort("\\I3"));
sigmap.apply(inbits);
+ if (unlut_mode)
+ goto remap_lut;
+
if (optimized_co.count(inbits[0])) goto remap_lut;
if (optimized_co.count(inbits[1])) goto remap_lut;
if (optimized_co.count(inbits[2])) goto remap_lut;
@@ -101,7 +104,7 @@ static void run_ice40_opts(Module *module)
cell->setParam("\\LUT", cell->getParam("\\LUT_INIT"));
cell->unsetParam("\\LUT_INIT");
- cell->setPort("\\A", SigSpec({cell->getPort("\\I0"), cell->getPort("\\I1"), cell->getPort("\\I2"), cell->getPort("\\I3")}));
+ cell->setPort("\\A", SigSpec({cell->getPort("\\I3"), cell->getPort("\\I2"), cell->getPort("\\I1"), cell->getPort("\\I0")}));
cell->setPort("\\Y", cell->getPort("\\O"));
cell->unsetPort("\\I0");
cell->unsetPort("\\I1");
@@ -127,23 +130,32 @@ struct Ice40OptPass : public Pass {
log("\n");
log(" do\n");
log(" <ice40 specific optimizations>\n");
- log(" opt_const -mux_undef -undriven [-full]\n");
- log(" opt_share\n");
+ log(" opt_expr -mux_undef -undriven [-full]\n");
+ log(" opt_merge\n");
log(" opt_rmdff\n");
log(" opt_clean\n");
log(" while <changed design>\n");
log("\n");
+ log("When called with the option -unlut, this command will transform all already\n");
+ log("mapped SB_LUT4 cells back to logic.\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- string opt_const_args = "-mux_undef -undriven";
- log_header("Executing ICE40_OPT pass (performing simple optimizations).\n");
+ string opt_expr_args = "-mux_undef -undriven";
+ bool unlut_mode = false;
+
+ log_header(design, "Executing ICE40_OPT pass (performing simple optimizations).\n");
log_push();
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-full") {
- opt_const_args += " -full";
+ opt_expr_args += " -full";
+ continue;
+ }
+ if (args[argidx] == "-unlut") {
+ unlut_mode = true;
continue;
}
break;
@@ -154,26 +166,26 @@ struct Ice40OptPass : public Pass {
{
design->scratchpad_unset("opt.did_something");
- log_header("Running ICE40 specific optimizations.\n");
+ log_header(design, "Running ICE40 specific optimizations.\n");
for (auto module : design->selected_modules())
- run_ice40_opts(module);
+ run_ice40_opts(module, unlut_mode);
- Pass::call(design, "opt_const " + opt_const_args);
- Pass::call(design, "opt_share");
+ Pass::call(design, "opt_expr " + opt_expr_args);
+ Pass::call(design, "opt_merge");
Pass::call(design, "opt_rmdff");
Pass::call(design, "opt_clean");
if (design->scratchpad_get_bool("opt.did_something") == false)
break;
- log_header("Rerunning OPT passes. (Removed registers in this run.)\n");
+ log_header(design, "Rerunning OPT passes. (Removed registers in this run.)\n");
}
design->optimize();
design->sort();
design->check();
- log_header("Finished OPT passes. (There is nothing left to do.)\n");
+ log_header(design, "Finished OPT passes. (There is nothing left to do.)\n");
log_pop();
}
} Ice40OptPass;
diff --git a/techlibs/ice40/latches_map.v b/techlibs/ice40/latches_map.v
new file mode 100644
index 00000000..c28f88cf
--- /dev/null
+++ b/techlibs/ice40/latches_map.v
@@ -0,0 +1,11 @@
+module \$_DLATCH_N_ (E, D, Q);
+ wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
+ input E, D;
+ output Q = !E ? D : Q;
+endmodule
+
+module \$_DLATCH_P_ (E, D, Q);
+ wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
+ input E, D;
+ output Q = E ? D : Q;
+endmodule
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 92d53f4a..38a9cf9d 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -25,18 +25,11 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-bool check_label(bool &active, std::string run_from, std::string run_to, std::string label)
+struct SynthIce40Pass : public ScriptPass
{
- if (label == run_from)
- active = true;
- if (label == run_to)
- active = false;
- return active;
-}
+ SynthIce40Pass() : ScriptPass("synth_ice40", "synthesis for iCE40 FPGAs") { }
-struct SynthIce40Pass : public Pass {
- SynthIce40Pass() : Pass("synth_ice40", "synthesis for iCE40 FPGAs") { }
- virtual void help()
+ virtual void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -77,73 +70,29 @@ struct SynthIce40Pass : public Pass {
log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
+ help_script();
log("\n");
- log(" begin:\n");
- log(" read_verilog -lib +/ice40/cells_sim.v\n");
- log(" hierarchy -check -top <top>\n");
- log("\n");
- log(" flatten: (unless -noflatten)\n");
- log(" proc\n");
- log(" flatten\n");
- log(" tribuf -logic\n");
- log("\n");
- log(" coarse:\n");
- log(" synth -run coarse\n");
- log("\n");
- log(" bram: (skip if -nobram)\n");
- log(" memory_bram -rules +/ice40/brams.txt\n");
- log(" techmap -map +/ice40/brams_map.v\n");
- log("\n");
- log(" fine:\n");
- log(" opt -fast -mux_undef -undriven -fine\n");
- log(" memory_map\n");
- log(" opt -undriven -fine\n");
- log(" techmap -map +/techmap.v [-map +/ice40/arith_map.v]\n");
- log(" abc -dff (only if -retime)\n");
- log(" ice40_opt\n");
- log("\n");
- log(" map_ffs:\n");
- log(" dffsr2dff\n");
- log(" dff2dffe -direct-match $_DFF_*\n");
- log(" techmap -map +/ice40/cells_map.v\n");
- log(" opt_const -mux_undef\n");
- log(" simplemap\n");
- log(" ice40_ffinit\n");
- log(" ice40_ffssr\n");
- log(" ice40_opt -full\n");
- log("\n");
- log(" map_luts:\n");
- log(" abc (only if -abc2)\n");
- log(" ice40_opt (only if -abc2)\n");
- log(" abc -lut 4\n");
- log(" clean\n");
- log("\n");
- log(" map_cells:\n");
- log(" techmap -map +/ice40/cells_map.v\n");
- log(" clean\n");
- log("\n");
- log(" check:\n");
- log(" hierarchy -check\n");
- log(" stat\n");
- log(" check -noinit\n");
- log("\n");
- log(" blif:\n");
- log(" write_blif -gates -attr -param <file-name>\n");
- log("\n");
- log(" edif:\n");
- log(" write_edif <file-name>\n");
- log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+
+ string top_opt, blif_file, edif_file;
+ bool nocarry, nobram, flatten, retime, abc2;
+
+ virtual void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ blif_file = "";
+ edif_file = "";
+ nocarry = false;
+ nobram = false;
+ flatten = true;
+ retime = false;
+ abc2 = false;
+ }
+
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- std::string top_opt = "-auto-top";
- std::string run_from, run_to;
- std::string blif_file, edif_file;
- bool nocarry = false;
- bool nobram = false;
- bool flatten = true;
- bool retime = false;
- bool abc2 = false;
+ string run_from, run_to;
+ clear_flags();
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -199,97 +148,102 @@ struct SynthIce40Pass : public Pass {
if (!design->full_selection())
log_cmd_error("This comannd only operates on fully selected designs!\n");
- bool active = run_from.empty();
-
- log_header("Executing SYNTH_ICE40 pass.\n");
+ log_header(design, "Executing SYNTH_ICE40 pass.\n");
log_push();
- if (check_label(active, run_from, run_to, "begin"))
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ virtual void script() YS_OVERRIDE
+ {
+ if (check_label("begin"))
{
- Pass::call(design, "read_verilog -lib +/ice40/cells_sim.v");
- Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
+ run("read_verilog -lib +/ice40/cells_sim.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
}
- if (flatten && check_label(active, run_from, run_to, "flatten"))
+ if (flatten && check_label("flatten", "(unless -noflatten)"))
{
- Pass::call(design, "proc");
- Pass::call(design, "flatten");
- Pass::call(design, "tribuf -logic");
+ run("proc");
+ run("flatten");
+ run("tribuf -logic");
+ run("deminout");
}
- if (check_label(active, run_from, run_to, "coarse"))
+ if (check_label("coarse"))
{
- Pass::call(design, "synth -run coarse");
+ run("synth -run coarse");
}
- if (!nobram && check_label(active, run_from, run_to, "bram"))
+ if (!nobram && check_label("bram", "(skip if -nobram)"))
{
- Pass::call(design, "memory_bram -rules +/ice40/brams.txt");
- Pass::call(design, "techmap -map +/ice40/brams_map.v");
+ run("memory_bram -rules +/ice40/brams.txt");
+ run("techmap -map +/ice40/brams_map.v");
}
- if (check_label(active, run_from, run_to, "fine"))
+ if (check_label("fine"))
{
- Pass::call(design, "opt -fast -mux_undef -undriven -fine");
- Pass::call(design, "memory_map");
- Pass::call(design, "opt -undriven -fine");
+ run("opt -fast -mux_undef -undriven -fine");
+ run("memory_map");
+ run("opt -undriven -fine");
if (nocarry)
- Pass::call(design, "techmap");
+ run("techmap");
else
- Pass::call(design, "techmap -map +/techmap.v -map +/ice40/arith_map.v");
- if (retime)
- Pass::call(design, "abc -dff");
- Pass::call(design, "ice40_opt");
+ run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
+ if (retime || help_mode)
+ run("abc -dff", "(only if -retime)");
+ run("ice40_opt");
}
- if (check_label(active, run_from, run_to, "map_ffs"))
+ if (check_label("map_ffs"))
{
- Pass::call(design, "dffsr2dff");
- Pass::call(design, "dff2dffe -direct-match $_DFF_*");
- Pass::call(design, "techmap -map +/ice40/cells_map.v");
- Pass::call(design, "opt_const -mux_undef");
- Pass::call(design, "simplemap");
- Pass::call(design, "ice40_ffinit");
- Pass::call(design, "ice40_ffssr");
- Pass::call(design, "ice40_opt -full");
+ run("dffsr2dff");
+ run("dff2dffe -direct-match $_DFF_*");
+ run("techmap -map +/ice40/cells_map.v");
+ run("opt_expr -mux_undef");
+ run("simplemap");
+ run("ice40_ffinit");
+ run("ice40_ffssr");
+ run("ice40_opt -full");
}
- if (check_label(active, run_from, run_to, "map_luts"))
+ if (check_label("map_luts"))
{
- if (abc2) {
- Pass::call(design, "abc");
- Pass::call(design, "ice40_opt");
+ if (abc2 || help_mode) {
+ run("abc", " (only if -abc2)");
+ run("ice40_opt", "(only if -abc2)");
}
- Pass::call(design, "abc -lut 4");
- Pass::call(design, "clean");
+ run("techmap -map +/ice40/latches_map.v");
+ run("abc -lut 4");
+ run("clean");
}
- if (check_label(active, run_from, run_to, "map_cells"))
+ if (check_label("map_cells"))
{
- Pass::call(design, "techmap -map +/ice40/cells_map.v");
- Pass::call(design, "clean");
+ run("techmap -map +/ice40/cells_map.v");
+ run("clean");
}
- if (check_label(active, run_from, run_to, "check"))
+ if (check_label("check"))
{
- Pass::call(design, "hierarchy -check");
- Pass::call(design, "stat");
- Pass::call(design, "check -noinit");
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
}
- if (check_label(active, run_from, run_to, "blif"))
+ if (check_label("blif"))
{
- if (!blif_file.empty())
- Pass::call(design, stringf("write_blif -gates -attr -param %s", blif_file.c_str()));
+ if (!blif_file.empty() || help_mode)
+ run(stringf("write_blif -gates -attr -param %s", help_mode ? "<file-name>" : blif_file.c_str()));
}
- if (check_label(active, run_from, run_to, "edif"))
+ if (check_label("edif"))
{
- if (!edif_file.empty())
- Pass::call(design, stringf("write_edif %s", edif_file.c_str()));
+ if (!edif_file.empty() || help_mode)
+ run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
}
-
- log_pop();
}
} SynthIce40Pass;