aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/ice40/synth_ice40.cc
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/ice40/synth_ice40.cc')
-rw-r--r--techlibs/ice40/synth_ice40.cc151
1 files changed, 130 insertions, 21 deletions
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index abd890a56..a3890268a 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -29,7 +29,7 @@ struct SynthIce40Pass : public ScriptPass
{
SynthIce40Pass() : ScriptPass("synth_ice40", "synthesis for iCE40 FPGAs") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -37,6 +37,10 @@ struct SynthIce40Pass : public ScriptPass
log("\n");
log("This command runs synthesis for iCE40 FPGAs.\n");
log("\n");
+ log(" -device < hx | lp | u >\n");
+ log(" relevant only for '-abc9' flow, optimise timing for the specified device.\n");
+ log(" default: hx\n");
+ log("\n");
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
@@ -69,9 +73,19 @@ struct SynthIce40Pass : public ScriptPass
log(" -nodffe\n");
log(" do not use SB_DFFE* cells in output netlist\n");
log("\n");
+ log(" -dffe_min_ce_use <min_ce_use>\n");
+ log(" do not use SB_DFFE* cells if the resulting CE line would go to less\n");
+ log(" than min_ce_use SB_DFFE* in output netlist\n");
+ log("\n");
log(" -nobram\n");
log(" do not use SB_RAM40_4K* cells in output netlist\n");
log("\n");
+ log(" -dsp\n");
+ log(" use iCE40 UltraPlus DSP cells for large arithmetic\n");
+ log("\n");
+ log(" -noabc\n");
+ log(" use built-in Yosys LUT techmapping instead of abc\n");
+ log("\n");
log(" -abc2\n");
log(" run two passes of 'abc' for slightly improved logic density\n");
log("\n");
@@ -79,16 +93,20 @@ struct SynthIce40Pass : public ScriptPass
log(" generate an output netlist (and BLIF file) suitable for VPR\n");
log(" (this feature is experimental and incomplete)\n");
log("\n");
+ log(" -abc9\n");
+ log(" use new ABC9 flow (EXPERIMENTAL)\n");
+ log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
- string top_opt, blif_file, edif_file, json_file;
- bool nocarry, nodffe, nobram, flatten, retime, abc2, vpr;
+ string top_opt, blif_file, edif_file, json_file, abc, device_opt;
+ bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr;
+ int min_ce_use;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
blif_file = "";
@@ -96,14 +114,19 @@ struct SynthIce40Pass : public ScriptPass
json_file = "";
nocarry = false;
nodffe = false;
+ min_ce_use = -1;
nobram = false;
+ dsp = false;
flatten = true;
retime = false;
+ noabc = false;
abc2 = false;
vpr = false;
+ abc = "abc";
+ device_opt = "hx";
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -147,6 +170,10 @@ struct SynthIce40Pass : public ScriptPass
retime = true;
continue;
}
+ if (args[argidx] == "-relut") {
+ // removed, opt_lut is always run
+ continue;
+ }
if (args[argidx] == "-nocarry") {
nocarry = true;
continue;
@@ -155,10 +182,22 @@ struct SynthIce40Pass : public ScriptPass
nodffe = true;
continue;
}
+ if (args[argidx] == "-dffe_min_ce_use" && argidx+1 < args.size()) {
+ min_ce_use = atoi(args[++argidx].c_str());
+ continue;
+ }
if (args[argidx] == "-nobram") {
nobram = true;
continue;
}
+ if (args[argidx] == "-dsp") {
+ dsp = true;
+ continue;
+ }
+ if (args[argidx] == "-noabc") {
+ noabc = true;
+ continue;
+ }
if (args[argidx] == "-abc2") {
abc2 = true;
continue;
@@ -167,12 +206,25 @@ struct SynthIce40Pass : public ScriptPass
vpr = true;
continue;
}
+ if (args[argidx] == "-abc9") {
+ abc = "abc9";
+ continue;
+ }
+ if (args[argidx] == "-device" && argidx+1 < args.size()) {
+ device_opt = args[++argidx];
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
if (!design->full_selection())
- log_cmd_error("This comannd only operates on fully selected designs!\n");
+ log_cmd_error("This command only operates on fully selected designs!\n");
+ if (device_opt != "hx" && device_opt != "lp" && device_opt !="u")
+ log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str());
+
+ if (abc == "abc9" && retime)
+ log_cmd_error("-retime option not currently compatible with -abc9!\n");
log_header(design, "Executing SYNTH_ICE40 pass.\n");
log_push();
@@ -182,44 +234,78 @@ struct SynthIce40Pass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
- run("read_verilog -lib +/ice40/cells_sim.v");
+ std::string define;
+ if (device_opt == "lp")
+ define = "-D ICE40_LP";
+ else if (device_opt == "u")
+ define = "-D ICE40_U";
+ else
+ define = "-D ICE40_HX";
+ run("read_verilog -icells " + define + " -lib +/ice40/cells_sim.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ run("proc");
}
- if (flatten && check_label("flatten", "(unless -noflatten)"))
+ if (check_label("flatten", "(unless -noflatten)"))
{
- run("proc");
- run("flatten");
- run("tribuf -logic");
- run("deminout");
+ if (flatten) {
+ run("flatten");
+ run("tribuf -logic");
+ run("deminout");
+ }
}
if (check_label("coarse"))
{
- run("synth -run coarse");
+ run("opt_expr");
+ run("opt_clean");
+ run("check");
+ run("opt");
+ run("wreduce");
+ run("peepopt");
+ run("opt_clean");
+ run("share");
+ run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
+ run("opt_expr");
+ run("opt_clean");
+ if (help_mode || dsp)
+ run("ice40_dsp", "(if -dsp)");
+ run("alumacc");
+ run("opt");
+ run("fsm");
+ run("opt -fast");
+ run("memory -nomap");
+ run("opt_clean");
}
- if (!nobram && check_label("bram", "(skip if -nobram)"))
+ if (!nobram && check_label("map_bram", "(skip if -nobram)"))
{
run("memory_bram -rules +/ice40/brams.txt");
run("techmap -map +/ice40/brams_map.v");
+ run("ice40_braminit");
}
- if (check_label("fine"))
+ if (check_label("map_ffram"))
{
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
run("opt -undriven -fine");
+ }
+
+ if (check_label("map_gates"))
+ {
if (nocarry)
run("techmap");
- else
+ else {
+ run("ice40_wrapcarry");
run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
+ }
if (retime || help_mode)
- run("abc -dff", "(only if -retime)");
+ run(abc + " -dff", "(only if -retime)");
run("ice40_opt");
}
@@ -228,7 +314,11 @@ struct SynthIce40Pass : public ScriptPass
run("dffsr2dff");
if (!nodffe)
run("dff2dffe -direct-match $_DFF_*");
- run("techmap -D NO_LUT -map +/ice40/cells_map.v");
+ if (min_ce_use >= 0) {
+ run("opt_merge");
+ run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
+ }
+ run("techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
run("ice40_ffinit");
@@ -239,12 +329,31 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("map_luts"))
{
if (abc2 || help_mode) {
- run("abc", " (only if -abc2)");
+ run(abc, " (only if -abc2)");
run("ice40_opt", "(only if -abc2)");
}
run("techmap -map +/ice40/latches_map.v");
- run("abc -lut 4");
+ if (noabc || help_mode) {
+ run("simplemap", " (only if -noabc)");
+ run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)");
+ }
+ if (!noabc) {
+ if (abc == "abc9") {
+ int wire_delay;
+ if (device_opt == "lp")
+ wire_delay = 400;
+ else if (device_opt == "u")
+ wire_delay = 750;
+ else
+ wire_delay = 250;
+ run(abc + stringf(" -W %d -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
+ }
+ else
+ run(abc + " -dress -lut 4", "(skip if -noabc)");
+ }
+ run("techmap -D NO_LUT -map +/ice40/cells_map.v");
run("clean");
+ run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");
}
if (check_label("map_cells"))