aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs')
-rwxr-xr-xtechlibs/achronix/speedster22i/cells_sim.v6
-rw-r--r--techlibs/anlogic/anlogic_eqn.cc4
-rw-r--r--techlibs/common/prep.cc6
-rw-r--r--techlibs/common/simlib.v176
-rw-r--r--techlibs/common/synth.cc2
-rw-r--r--techlibs/ecp5/Makefile.inc2
-rw-r--r--techlibs/ecp5/arith_map.v2
-rw-r--r--techlibs/ecp5/cells_bb.v152
-rw-r--r--techlibs/ecp5/cells_map.v18
-rw-r--r--techlibs/ecp5/cells_sim.v41
-rw-r--r--techlibs/ecp5/ecp5_ffinit.cc203
-rw-r--r--techlibs/ecp5/synth_ecp5.cc5
-rw-r--r--techlibs/gowin/Makefile.inc10
-rw-r--r--techlibs/gowin/arith_map.v12
-rw-r--r--techlibs/gowin/bram.txt29
-rw-r--r--techlibs/gowin/brams_init3.vh12
-rw-r--r--techlibs/gowin/brams_map.v103
-rw-r--r--techlibs/gowin/cells_map.v6
-rw-r--r--techlibs/gowin/cells_sim.v134
-rw-r--r--techlibs/gowin/determine_init.cc72
-rw-r--r--techlibs/gowin/dram.txt17
-rw-r--r--techlibs/gowin/drams_map.v31
-rw-r--r--techlibs/gowin/synth_gowin.cc58
-rw-r--r--techlibs/ice40/Makefile.inc1
-rw-r--r--techlibs/ice40/brams_map.v4
-rw-r--r--techlibs/ice40/cells_sim.v139
-rw-r--r--techlibs/ice40/ice40_braminit.cc159
-rw-r--r--techlibs/ice40/synth_ice40.cc13
-rw-r--r--techlibs/intel/cycloneive/arith_map.v10
-rw-r--r--techlibs/intel/cyclonev/cells_map.v4
-rw-r--r--techlibs/intel/cyclonev/cells_sim.v12
-rw-r--r--techlibs/intel/synth_intel.cc433
-rw-r--r--techlibs/sf2/cells_map.v64
-rw-r--r--techlibs/sf2/cells_sim.v281
-rw-r--r--techlibs/sf2/sf2_iobs.cc217
-rw-r--r--techlibs/sf2/synth_sf2.cc16
-rw-r--r--techlibs/xilinx/Makefile.inc3
-rw-r--r--techlibs/xilinx/arith_map.v282
-rw-r--r--techlibs/xilinx/cells_map.v208
-rw-r--r--techlibs/xilinx/cells_sim.v161
-rw-r--r--techlibs/xilinx/cells_xtra.sh27
-rw-r--r--techlibs/xilinx/cells_xtra.v78
-rw-r--r--techlibs/xilinx/drams.txt4
-rw-r--r--techlibs/xilinx/ff_map.v42
-rw-r--r--techlibs/xilinx/lut2lut.v65
-rw-r--r--techlibs/xilinx/lut_map.v94
-rw-r--r--techlibs/xilinx/synth_xilinx.cc270
47 files changed, 2900 insertions, 788 deletions
diff --git a/techlibs/achronix/speedster22i/cells_sim.v b/techlibs/achronix/speedster22i/cells_sim.v
index a94dce9b1..a0c60b4be 100755
--- a/techlibs/achronix/speedster22i/cells_sim.v
+++ b/techlibs/achronix/speedster22i/cells_sim.v
@@ -30,7 +30,7 @@ endmodule
module PADOUT (output padout, input padin, input oe);
assign padout = padin;
assign oe = oe;
-endmodule
+endmodule
module LUT4 (output dout,
input din0, din1, din2, din3);
@@ -66,14 +66,14 @@ always @(dataa_w or datab_w or datac_w or datad_w) begin
datac_w, datad_w);
end
assign dout = combout_rt & 1'b1;
-endmodule
+endmodule
module DFF (output q,
input d, ck);
reg q;
always @(posedge ck)
q <= d;
-
+
endmodule
diff --git a/techlibs/anlogic/anlogic_eqn.cc b/techlibs/anlogic/anlogic_eqn.cc
index c025c65c4..741bf04cc 100644
--- a/techlibs/anlogic/anlogic_eqn.cc
+++ b/techlibs/anlogic/anlogic_eqn.cc
@@ -52,13 +52,13 @@ struct AnlogicEqnPass : public Pass {
eqn += names[j];
else
eqn += std::string("~") + names[j];
-
+
if (j!=(inputs-1)) eqn += "*";
}
eqn += ")+";
}
}
- if (eqn.empty()) return Const("0");
+ if (eqn.empty()) return Const("0");
eqn = eqn.substr(0, eqn.length()-1);
return Const(eqn);
}
diff --git a/techlibs/common/prep.cc b/techlibs/common/prep.cc
index 86fb4d6c6..cdd21c3b3 100644
--- a/techlibs/common/prep.cc
+++ b/techlibs/common/prep.cc
@@ -195,9 +195,11 @@ struct PrepPass : public ScriptPass
run(nokeepdc ? "opt" : "opt -keepdc");
if (!ifxmode) {
if (help_mode)
- run("wreduce [-memx]");
- else
+ run("wreduce -keepdc [-memx]");
+ else if (nokeepdc)
run(memxmode ? "wreduce -memx" : "wreduce");
+ else
+ run(memxmode ? "wreduce -keepdc -memx" : "wreduce -keepdc");
}
if (!nomemmode) {
run(string("memory_dff") + (help_mode ? " [-nordff]" : nordff ? " -nordff" : ""));
diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v
index 8e43fe058..a424d3089 100644
--- a/techlibs/common/simlib.v
+++ b/techlibs/common/simlib.v
@@ -1271,6 +1271,181 @@ endmodule
// --------------------------------------------------------
+module \$specify2 (EN, SRC, DST);
+
+parameter FULL = 0;
+parameter SRC_WIDTH = 1;
+parameter DST_WIDTH = 1;
+
+parameter SRC_DST_PEN = 0;
+parameter SRC_DST_POL = 0;
+
+parameter T_RISE_MIN = 0;
+parameter T_RISE_TYP = 0;
+parameter T_RISE_MAX = 0;
+
+parameter T_FALL_MIN = 0;
+parameter T_FALL_TYP = 0;
+parameter T_FALL_MAX = 0;
+
+input EN;
+input [SRC_WIDTH-1:0] SRC;
+input [DST_WIDTH-1:0] DST;
+
+localparam SD = SRC_DST_PEN ? (SRC_DST_POL ? 1 : 2) : 0;
+
+`ifdef SIMLIB_SPECIFY
+specify
+ if (EN && SD==0 && !FULL) (SRC => DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && SD==0 && FULL) (SRC *> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && SD==1 && !FULL) (SRC +=> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && SD==1 && FULL) (SRC +*> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && SD==2 && !FULL) (SRC -=> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && SD==2 && FULL) (SRC -*> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+endspecify
+`endif
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$specify3 (EN, SRC, DST, DAT);
+
+parameter FULL = 0;
+parameter SRC_WIDTH = 1;
+parameter DST_WIDTH = 1;
+
+parameter EDGE_EN = 0;
+parameter EDGE_POL = 0;
+
+parameter SRC_DST_PEN = 0;
+parameter SRC_DST_POL = 0;
+
+parameter DAT_DST_PEN = 0;
+parameter DAT_DST_POL = 0;
+
+parameter T_RISE_MIN = 0;
+parameter T_RISE_TYP = 0;
+parameter T_RISE_MAX = 0;
+
+parameter T_FALL_MIN = 0;
+parameter T_FALL_TYP = 0;
+parameter T_FALL_MAX = 0;
+
+input EN;
+input [SRC_WIDTH-1:0] SRC;
+input [DST_WIDTH-1:0] DST, DAT;
+
+localparam ED = EDGE_EN ? (EDGE_POL ? 1 : 2) : 0;
+localparam SD = SRC_DST_PEN ? (SRC_DST_POL ? 1 : 2) : 0;
+localparam DD = DAT_DST_PEN ? (DAT_DST_POL ? 1 : 2) : 0;
+
+`ifdef SIMLIB_SPECIFY
+specify
+ // DD=0
+
+ if (EN && DD==0 && SD==0 && ED==0 && !FULL) ( SRC => (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==0 && ED==0 && FULL) ( SRC *> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==0 && ED==1 && !FULL) (posedge SRC => (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==0 && ED==1 && FULL) (posedge SRC *> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==0 && ED==2 && !FULL) (negedge SRC => (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==0 && ED==2 && FULL) (negedge SRC *> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+
+ if (EN && DD==0 && SD==1 && ED==0 && !FULL) ( SRC +=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==1 && ED==0 && FULL) ( SRC +*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==1 && ED==1 && !FULL) (posedge SRC +=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==1 && ED==1 && FULL) (posedge SRC +*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==1 && ED==2 && !FULL) (negedge SRC +=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==1 && ED==2 && FULL) (negedge SRC +*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+
+ if (EN && DD==0 && SD==2 && ED==0 && !FULL) ( SRC -=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==2 && ED==0 && FULL) ( SRC -*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==2 && ED==1 && !FULL) (posedge SRC -=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==2 && ED==1 && FULL) (posedge SRC -*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==2 && ED==2 && !FULL) (negedge SRC -=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==0 && SD==2 && ED==2 && FULL) (negedge SRC -*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+
+ // DD=1
+
+ if (EN && DD==1 && SD==0 && ED==0 && !FULL) ( SRC => (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==0 && ED==0 && FULL) ( SRC *> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==0 && ED==1 && !FULL) (posedge SRC => (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==0 && ED==1 && FULL) (posedge SRC *> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==0 && ED==2 && !FULL) (negedge SRC => (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==0 && ED==2 && FULL) (negedge SRC *> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+
+ if (EN && DD==1 && SD==1 && ED==0 && !FULL) ( SRC +=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==1 && ED==0 && FULL) ( SRC +*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==1 && ED==1 && !FULL) (posedge SRC +=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==1 && ED==1 && FULL) (posedge SRC +*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==1 && ED==2 && !FULL) (negedge SRC +=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==1 && ED==2 && FULL) (negedge SRC +*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+
+ if (EN && DD==1 && SD==2 && ED==0 && !FULL) ( SRC -=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==2 && ED==0 && FULL) ( SRC -*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==2 && ED==1 && !FULL) (posedge SRC -=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==2 && ED==1 && FULL) (posedge SRC -*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==2 && ED==2 && !FULL) (negedge SRC -=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==1 && SD==2 && ED==2 && FULL) (negedge SRC -*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+
+ // DD=2
+
+ if (EN && DD==2 && SD==0 && ED==0 && !FULL) ( SRC => (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==0 && ED==0 && FULL) ( SRC *> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==0 && ED==1 && !FULL) (posedge SRC => (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==0 && ED==1 && FULL) (posedge SRC *> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==0 && ED==2 && !FULL) (negedge SRC => (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==0 && ED==2 && FULL) (negedge SRC *> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+
+ if (EN && DD==2 && SD==1 && ED==0 && !FULL) ( SRC +=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==1 && ED==0 && FULL) ( SRC +*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==1 && ED==1 && !FULL) (posedge SRC +=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==1 && ED==1 && FULL) (posedge SRC +*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==1 && ED==2 && !FULL) (negedge SRC +=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==1 && ED==2 && FULL) (negedge SRC +*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+
+ if (EN && DD==2 && SD==2 && ED==0 && !FULL) ( SRC -=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==2 && ED==0 && FULL) ( SRC -*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==2 && ED==1 && !FULL) (posedge SRC -=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==2 && ED==1 && FULL) (posedge SRC -*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==2 && ED==2 && !FULL) (negedge SRC -=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+ if (EN && DD==2 && SD==2 && ED==2 && FULL) (negedge SRC -*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX);
+endspecify
+`endif
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$specrule (EN_SRC, EN_DST, SRC, DST);
+
+parameter TYPE = "";
+parameter T_LIMIT = 0;
+parameter T_LIMIT2 = 0;
+
+parameter SRC_WIDTH = 1;
+parameter DST_WIDTH = 1;
+
+parameter SRC_PEN = 0;
+parameter SRC_POL = 0;
+
+parameter DST_PEN = 0;
+parameter DST_POL = 0;
+
+input EN_SRC, EN_DST;
+input [SRC_WIDTH-1:0] SRC;
+input [DST_WIDTH-1:0] DST;
+
+`ifdef SIMLIB_SPECIFY
+specify
+ // TBD
+endspecify
+`endif
+
+endmodule
+
+// --------------------------------------------------------
+
module \$assert (A, EN);
input A, EN;
@@ -1863,4 +2038,5 @@ end
endmodule
`endif
+
// --------------------------------------------------------
diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc
index ccfa76e02..e41c0fe97 100644
--- a/techlibs/common/synth.cc
+++ b/techlibs/common/synth.cc
@@ -201,6 +201,8 @@ struct SynthPass : public ScriptPass
run("check");
run("opt");
run("wreduce");
+ run("peepopt");
+ run("opt_clean");
if (help_mode)
run("techmap -map +/cmp2lut.v", " (if -lut)");
else
diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc
index 8df02be5f..4db087e87 100644
--- a/techlibs/ecp5/Makefile.inc
+++ b/techlibs/ecp5/Makefile.inc
@@ -1,5 +1,5 @@
-OBJS += techlibs/ecp5/synth_ecp5.o
+OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
diff --git a/techlibs/ecp5/arith_map.v b/techlibs/ecp5/arith_map.v
index 1094c5f8a..eb7947601 100644
--- a/techlibs/ecp5/arith_map.v
+++ b/techlibs/ecp5/arith_map.v
@@ -33,7 +33,7 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO);
input CI, BI;
output [Y_WIDTH-1:0] CO;
- wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
wire [Y_WIDTH-1:0] A_buf, B_buf;
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
diff --git a/techlibs/ecp5/cells_bb.v b/techlibs/ecp5/cells_bb.v
index 425d62d24..223e19b9e 100644
--- a/techlibs/ecp5/cells_bb.v
+++ b/techlibs/ecp5/cells_bb.v
@@ -156,6 +156,41 @@ module OSCG(
parameter DIV = 128;
endmodule
+(* blackbox *) (* keep *)
+module USRMCLK(
+ input USRMCLKI, USRMCLKTS,
+ output USRMCLKO
+);
+endmodule
+
+(* blackbox *) (* keep *)
+module JTAGG(
+ input TCK, TMS, TDI, JTDO2, JTDO1,
+ output TDO, JTDI, JTCK, JRTI2, JRTI1,
+ output JSHIFT, JUPDATE, JRSTN, JCE2, JCE1
+);
+parameter ER1 = "ENABLED";
+parameter ER2 = "ENABLED";
+endmodule
+
+(* blackbox *)
+module DELAYF(
+ input A, LOADN, MOVE, DIRECTION,
+ output Z, CFLAG
+);
+ parameter DEL_MODE = "USER_DEFINED";
+ parameter DEL_VALUE = 0;
+endmodule
+
+(* blackbox *)
+module DELAYG(
+ input A,
+ output Z
+);
+ parameter DEL_MODE = "USER_DEFINED";
+ parameter DEL_VALUE = 0;
+endmodule
+
(* blackbox *)
module IDDRX1F(
input D, SCLK, RST,
@@ -165,6 +200,31 @@ module IDDRX1F(
endmodule
(* blackbox *)
+module IDDRX2F(
+ input D, SCLK, ECLK, RST,
+ output Q0, Q1, Q2, Q3
+);
+ parameter GSR = "ENABLED";
+endmodule
+
+(* blackbox *)
+module IDDR71B(
+ input D, SCLK, ECLK, RST, ALIGNWD,
+ output Q0, Q1, Q2, Q3, Q4, Q5, Q6
+);
+ parameter GSR = "ENABLED";
+endmodule
+
+(* blackbox *)
+module IDDRX2DQA(
+ input D, DQSR90, ECLK, SCLK, RST,
+ input RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0,
+ output Q0, Q1, Q2, Q3, QWL
+);
+ parameter GSR = "ENABLED";
+endmodule
+
+(* blackbox *)
module ODDRX1F(
input SCLK, RST, D0, D1,
output Q
@@ -173,6 +233,91 @@ module ODDRX1F(
endmodule
(* blackbox *)
+module ODDRX2F(
+ input SCLK, ECLK, RST, D0, D1, D2, D3,
+ output Q
+);
+ parameter GSR = "ENABLED";
+endmodule
+
+(* blackbox *)
+module ODDR71B(
+ input SCLK, ECLK, RST, D0, D1, D2, D3, D4, D5, D6,
+ output Q
+);
+ parameter GSR = "ENABLED";
+endmodule
+
+(* blackbox *)
+module OSHX2A(
+ input D0, D1, RST, ECLK, SCLK,
+ output Q
+);
+ parameter GSR = "ENABLED";
+endmodule
+
+(* blackbox *)
+module ODDRX2DQA(
+ input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW270,
+ output Q
+);
+ parameter GSR = "ENABLED";
+endmodule
+
+(* blackbox *)
+module ODDRX2DQSB(
+ input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW,
+ output Q
+);
+ parameter GSR = "ENABLED";
+endmodule
+
+(* blackbox *)
+module TSHX2DQA(
+ input T0, T1, SCLK, ECLK, DQSW270, RST,
+ output Q
+);
+ parameter GSR = "ENABLED";
+ parameter REGSET = "SET";
+endmodule
+
+(* blackbox *)
+module TSHX2DQSA(
+ input T0, T1, SCLK, ECLK, DQSW, RST,
+ output Q
+);
+ parameter GSR = "ENABLED";
+ parameter REGSET = "SET";
+endmodule
+
+(* blackbox *)
+module DQSBUFM(
+ input DQSI, READ1, READ0, READCLKSEL2, READCLKSEL1, READCLKSEL0, DDRDEL,
+ input ECLK, SCLK,
+ input DYNDELAY7, DYNDELAY6, DYNDELAY5, DYNDELAY4,
+ input DYNDELAY3, DYNDELAY2, DYNDELAY1, DYNDELAY0,
+ input RST, RDLOADN, RDMOVE, RDDIRECTION, WRLOADN, WRMOVE, WRDIRECTION, PAUSE,
+ output DQSR90, DQSW, DQSW270,
+ output RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0,
+ output DATAVALID, BURSTDET, RDCFLAG, WRCFLAG
+);
+ parameter DQS_LI_DEL_ADJ = "FACTORYONLY";
+ parameter DQS_LI_DEL_VAL = 0;
+ parameter DQS_LO_DEL_ADJ = "FACTORYONLY";
+ parameter DQS_LO_DEL_VAL = 0;
+ parameter GSR = "ENABLED";
+endmodule
+
+(* blackbox *)
+module DDRDLLA(
+ input CLK, RST, UDDCNTLN, FREEZE,
+ output LOCK, DDRDEL, DCNTL7, DCNTL6, DCNTL5, DCNTL4, DCNTL3, DCNTL2, DCNTL1, DCNTL0
+);
+ parameter FORCE_MAX_DELAY = "NO";
+ parameter GSR = "ENABLED";
+endmodule
+
+(* blackbox *)
module CLKDIVF(
input CLKI, RST, ALIGNWD,
output CDIVX
@@ -182,6 +327,13 @@ module CLKDIVF(
endmodule
(* blackbox *)
+module ECLKSYNCB(
+ input ECLKI, STOP,
+ output ECLKO
+);
+endmodule
+
+(* blackbox *)
module DCCA(
input CLKI, CE,
output CLKO
diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v
index 23182bdeb..f6c71a03d 100644
--- a/techlibs/ecp5/cells_map.v
+++ b/techlibs/ecp5/cells_map.v
@@ -47,6 +47,24 @@ module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"
module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+// Diamond I/O buffers
+module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
+module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
+module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
+module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule
+module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
+module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
+module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
+module OBCO (input I, output OT, OC); OLVDS _TECHMAP_REPLACE_ (.A(I), .Z(OT), .ZN(OC)); endmodule
+module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
+module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
+module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
+module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule
+module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule
+
+// For Diamond compatibility, FIXME: add all Diamond flipflop mappings
+module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
+
`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;
diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v
index f27540bd7..1e4002ee0 100644
--- a/techlibs/ecp5/cells_sim.v
+++ b/techlibs/ecp5/cells_sim.v
@@ -203,13 +203,14 @@ endmodule
// ---------------------------------------
-module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q);
+module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
parameter GSR = "ENABLED";
parameter [127:0] CEMUX = "1";
parameter CLKMUX = "CLK";
parameter LSRMUX = "LSR";
parameter SRMODE = "LSR_OVER_CE";
parameter REGSET = "RESET";
+ parameter [127:0] LSRMODE = "LSR";
reg muxce;
always @(*)
@@ -222,8 +223,13 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q);
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
-
- localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0;
+ wire srval;
+ generate
+ if (LSRMODE == "PRLD")
+ assign srval = M;
+ else
+ assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
+ endgenerate
initial Q = srval;
@@ -339,6 +345,8 @@ module TRELLIS_SLICE(
parameter REG1_SD = "0";
parameter REG0_REGSET = "RESET";
parameter REG1_REGSET = "RESET";
+ parameter REG0_LSRMODE = "LSR";
+ parameter REG1_LSRMODE = "LSR";
parameter [127:0] CCU2_INJECT1_0 = "NO";
parameter [127:0] CCU2_INJECT1_1 = "NO";
parameter WREMUX = "WRE";
@@ -428,10 +436,11 @@ module TRELLIS_SLICE(
.CLKMUX(CLKMUX),
.LSRMUX(LSRMUX),
.SRMODE(SRMODE),
- .REGSET(REG0_REGSET)
+ .REGSET(REG0_REGSET),
+ .LSRMODE(REG0_LSRMODE)
) ff_0 (
.CLK(CLK), .LSR(LSR), .CE(CE),
- .DI(muxdi0),
+ .DI(muxdi0), .M(M0),
.Q(Q0)
);
TRELLIS_FF #(
@@ -440,10 +449,11 @@ module TRELLIS_SLICE(
.CLKMUX(CLKMUX),
.LSRMUX(LSRMUX),
.SRMODE(SRMODE),
- .REGSET(REG1_REGSET)
+ .REGSET(REG1_REGSET),
+ .LSRMODE(REG1_LSRMODE)
) ff_1 (
.CLK(CLK), .LSR(LSR), .CE(CE),
- .DI(muxdi1),
+ .DI(muxdi1), .M(M1),
.Q(Q1)
);
endmodule
@@ -547,3 +557,20 @@ module DP16KD(
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
endmodule
+
+// For Diamond compatibility, FIXME: add all Diamond flipflop mappings
+module FD1S3BX(input PD, D, CK, output Q);
+ TRELLIS_FF #(
+ .GSR("DISABLED"),
+ .CEMUX("1"),
+ .CLKMUX("CLK"),
+ .LSRMUX("LSR"),
+ .REGSET("SET"),
+ .SRMODE("ASYNC")
+ ) tff_i (
+ .CLK(CK),
+ .LSR(PD),
+ .DI(D),
+ .Q(Q)
+ );
+endmodule
diff --git a/techlibs/ecp5/ecp5_ffinit.cc b/techlibs/ecp5/ecp5_ffinit.cc
new file mode 100644
index 000000000..dbd16cac9
--- /dev/null
+++ b/techlibs/ecp5/ecp5_ffinit.cc
@@ -0,0 +1,203 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018-19 David Shah <david@symbioticeda.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct Ecp5FfinitPass : public Pass {
+ Ecp5FfinitPass() : Pass("ecp5_ffinit", "ECP5: handle FF init values") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" ecp5_ffinit [options] [selection]\n");
+ log("\n");
+ log("Remove init values for FF output signals when equal to reset value.\n");
+ log("If reset is not used, set the reset value to the init value, otherwise\n");
+ log("unmap out the reset (if not an async reset).\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing ECP5_FFINIT pass (implement FF init values).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-singleton") {
+ // singleton_mode = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ {
+ log("Handling FF init values in %s.\n", log_id(module));
+
+ 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())
+ {
+ if (wire->attributes.count("\\init") == 0)
+ continue;
+
+ SigSpec wirebits = sigmap(wire);
+ Const initval = wire->attributes.at("\\init");
+ init_wires.insert(wire);
+
+ for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
+ {
+ SigBit bit = wirebits[i];
+ State val = initval[i];
+
+ if (val != State::S0 && val != State::S1)
+ continue;
+
+ if (initbits.count(bit)) {
+ if (initbits.at(bit) != val) {
+ log_warning("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)));
+ initbits.at(bit) = State::Sx;
+ }
+ continue;
+ }
+
+ initbits[bit] = val;
+ initbit_to_wire[bit] = SigBit(wire, i);
+ }
+ }
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type != "\\TRELLIS_FF")
+ continue;
+ SigSpec sig_d = cell->getPort("\\DI");
+ SigSpec sig_q = cell->getPort("\\Q");
+ SigSpec sig_lsr = cell->getPort("\\LSR");
+
+ if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
+ continue;
+
+ SigBit bit_d = sigmap(sig_d[0]);
+ SigBit bit_q = sigmap(sig_q[0]);
+
+ std::string regset = "RESET";
+ if (cell->hasParam("\\REGSET"))
+ regset = cell->getParam("\\REGSET").decode_string();
+ State resetState;
+ if (regset == "SET")
+ resetState = State::S1;
+ else if (regset == "RESET")
+ resetState = State::S0;
+ else
+ log_error("FF cell %s has illegal REGSET value %s.\n",
+ log_id(cell), regset.c_str());
+
+ if (!initbits.count(bit_q))
+ continue;
+
+ State val = initbits.at(bit_q);
+
+ if (val == State::Sx)
+ continue;
+
+ log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type),
+ log_signal(bit_q), val != State::S0 ? '1' : '0');
+ // Initval is the same as the reset state. Matches hardware, nowt more to do
+ if (val == resetState) {
+ handled_initbits.insert(bit_q);
+ continue;
+ }
+
+ if (GetSize(sig_lsr) >= 1 && sig_lsr[0] != State::S0) {
+ std::string srmode = "LSR_OVER_CE";
+ if (cell->hasParam("\\SRMODE"))
+ srmode = cell->getParam("\\SRMODE").decode_string();
+ if (srmode == "ASYNC") {
+ log("Async reset value %c for FF cell %s inconsistent with init value %c.\n",
+ resetState != State::S0 ? '1' : '0', log_id(cell), val != State::S0 ? '1' : '0');
+ } else {
+ SigBit bit_lsr = sigmap(sig_lsr[0]);
+ Wire *new_bit_d = module->addWire(NEW_ID);
+ if (resetState == State::S0) {
+ module->addAndnotGate(NEW_ID, bit_d, bit_lsr, new_bit_d);
+ } else {
+ module->addOrGate(NEW_ID, bit_d, bit_lsr, new_bit_d);
+ }
+
+ cell->setPort("\\DI", new_bit_d);
+ cell->setPort("\\LSR", State::S0);
+
+ if(cell->hasPort("\\CE")) {
+ std::string cemux = "CE";
+ if (cell->hasParam("\\CEMUX"))
+ cemux = cell->getParam("\\CEMUX").decode_string();
+ SigSpec sig_ce = cell->getPort("\\CE");
+ if (GetSize(sig_ce) >= 1) {
+ SigBit bit_ce = sigmap(sig_ce[0]);
+ Wire *new_bit_ce = module->addWire(NEW_ID);
+ if (cemux == "INV")
+ module->addAndnotGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce);
+ else
+ module->addOrGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce);
+ cell->setPort("\\CE", new_bit_ce);
+ }
+ }
+ cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET"));
+ handled_initbits.insert(bit_q);
+ }
+ } else {
+ cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET"));
+ handled_initbits.insert(bit_q);
+ }
+ }
+
+ for (auto wire : init_wires)
+ {
+ if (wire->attributes.count("\\init") == 0)
+ continue;
+
+ SigSpec wirebits = sigmap(wire);
+ Const &initval = wire->attributes.at("\\init");
+ bool remove_attribute = true;
+
+ for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) {
+ if (handled_initbits.count(wirebits[i]))
+ initval[i] = State::Sx;
+ else if (initval[i] != State::Sx)
+ remove_attribute = false;
+ }
+
+ if (remove_attribute)
+ wire->attributes.erase("\\init");
+ }
+ }
+ }
+} Ecp5FfinitPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc
index bda03d251..c6e12248e 100644
--- a/techlibs/ecp5/synth_ecp5.cc
+++ b/techlibs/ecp5/synth_ecp5.cc
@@ -253,12 +253,9 @@ struct SynthEcp5Pass : public ScriptPass
if (!nodffe)
run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
- run("opt_expr -mux_undef");
+ run("opt_expr -undriven -mux_undef");
run("simplemap");
- // TODO
-#if 0
run("ecp5_ffinit");
-#endif
}
if (check_label("map_luts"))
diff --git a/techlibs/gowin/Makefile.inc b/techlibs/gowin/Makefile.inc
index 2f82def7d..6f2159349 100644
--- a/techlibs/gowin/Makefile.inc
+++ b/techlibs/gowin/Makefile.inc
@@ -1,7 +1,17 @@
OBJS += techlibs/gowin/synth_gowin.o
+OBJS += techlibs/gowin/determine_init.o
+
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_map.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_sim.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/arith_map.v))
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_map.v))
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/bram.txt))
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/drams_map.v))
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/dram.txt))
+
+
+
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_init3.vh))
diff --git a/techlibs/gowin/arith_map.v b/techlibs/gowin/arith_map.v
index 25e789e4a..e15de6423 100644
--- a/techlibs/gowin/arith_map.v
+++ b/techlibs/gowin/arith_map.v
@@ -25,24 +25,24 @@ module _80_gw1n_alu(A, B, CI, BI, X, Y, CO);
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
-
+
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH-1:0] X, Y;
-
+
input CI, BI;
output [Y_WIDTH-1:0] CO;
-
+
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
-
+
wire [Y_WIDTH-1:0] A_buf, B_buf;
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
-
+
wire [Y_WIDTH-1:0] AA = A_buf;
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
wire [Y_WIDTH-1:0] C = {CO, CI};
-
+
genvar i;
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
ALU #(.ALU_MODE(32'b0))
diff --git a/techlibs/gowin/bram.txt b/techlibs/gowin/bram.txt
new file mode 100644
index 000000000..b5f9a981c
--- /dev/null
+++ b/techlibs/gowin/bram.txt
@@ -0,0 +1,29 @@
+bram $__GW1NR_SDP
+# uncomment when done
+# init 1
+ abits 10 @a10d18
+ dbits 16 @a10d18
+ abits 11 @a11d9
+ dbits 8 @a11d9
+ abits 12 @a12d4
+ dbits 4 @a12d4
+ abits 13 @a13d2
+ dbits 2 @a13d2
+ abits 14 @a14d1
+ dbits 1 @a14d1
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 1 1 @a10d18
+ enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__GW1NR_SDP
+ min bits 2048
+ min efficiency 5
+ shuffle_enable B
+ make_transp
+endmatch
diff --git a/techlibs/gowin/brams_init3.vh b/techlibs/gowin/brams_init3.vh
new file mode 100644
index 000000000..84397fa24
--- /dev/null
+++ b/techlibs/gowin/brams_init3.vh
@@ -0,0 +1,12 @@
+localparam [15:0] INIT_0 = {
+ INIT[ 60], INIT[ 56], INIT[ 52], INIT[ 48], INIT[ 44], INIT[ 40], INIT[ 36], INIT[ 32], INIT[ 28], INIT[ 24], INIT[ 20], INIT[ 16], INIT[ 12], INIT[ 8], INIT[ 4], INIT[ 0]
+};
+localparam [15:0] INIT_1 = {
+ INIT[ 61], INIT[ 57], INIT[ 53], INIT[ 49], INIT[ 45], INIT[ 41], INIT[ 37], INIT[ 33], INIT[ 29], INIT[ 25], INIT[ 21], INIT[ 17], INIT[ 13], INIT[ 9], INIT[ 5], INIT[ 1]
+};
+localparam [15:0] INIT_2 = {
+ INIT[ 62], INIT[ 58], INIT[ 54], INIT[ 50], INIT[ 46], INIT[ 42], INIT[ 38], INIT[ 34], INIT[ 30], INIT[ 26], INIT[ 22], INIT[ 18], INIT[ 14], INIT[ 10], INIT[ 6], INIT[ 2]
+};
+localparam [15:0] INIT_3 = {
+ INIT[ 63], INIT[ 59], INIT[ 55], INIT[ 51], INIT[ 47], INIT[ 43], INIT[ 39], INIT[ 35], INIT[ 31], INIT[ 27], INIT[ 23], INIT[ 19], INIT[ 15], INIT[ 11], INIT[ 7], INIT[ 3]
+};
diff --git a/techlibs/gowin/brams_map.v b/techlibs/gowin/brams_map.v
new file mode 100644
index 000000000..e963cfa88
--- /dev/null
+++ b/techlibs/gowin/brams_map.v
@@ -0,0 +1,103 @@
+/* Semi Dual Port (SDP) memory have the following configurations:
+ * Memory Config RAM(BIT) Port Mode Memory Depth Data Depth
+ * ----------------|---------| ----------|--------------|------------|
+ * B-SRAM_16K_SD1 16K 16Kx1 16,384 1
+ * B-SRAM_8K_SD2 16K 8Kx2 8,192 2
+ * B-SRAM_4K_SD4 16K 4Kx2 4,096 4
+ */
+module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 10;
+ parameter CFG_DBITS = 16;
+ parameter CFG_ENABLE_A = 3;
+
+ parameter [16383:0] INIT = 16384'hx;
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ input [CFG_DBITS-1:0] A1DATA;
+ input [CFG_ENABLE_A-1:0] A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ output [CFG_DBITS-1:0] B1DATA;
+ input B1EN;
+
+
+ generate if (CFG_DBITS == 1) begin
+ SDP #(
+ .READ_MODE(0),
+ .BIT_WIDTH_0(1),
+ .BIT_WIDTH_1(1),
+ .BLK_SEL(3'b000),
+ .RESET_MODE("SYNC")
+ ) _TECHMAP_REPLACE_ (
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
+ .WREB(1'b0), .CEB(B1EN),
+ .RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
+ .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
+ );
+ end else if (CFG_DBITS == 2) begin
+ SDP #(
+ .READ_MODE(0),
+ .BIT_WIDTH_0(2),
+ .BIT_WIDTH_1(2),
+ .BLK_SEL(3'b000),
+ .RESET_MODE("SYNC")
+ ) _TECHMAP_REPLACE_ (
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
+ .WREB(1'b0), .CEB(B1EN),
+ .RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
+ .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
+ );
+ end else if (CFG_DBITS <= 4) begin
+ SDP #(
+ .READ_MODE(0),
+ .BIT_WIDTH_0(4),
+ .BIT_WIDTH_1(4),
+ .BLK_SEL(3'b000),
+ .RESET_MODE("SYNC")
+ ) _TECHMAP_REPLACE_ (
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WREA(A1EN), .OCE(1'b0),
+ .WREB(1'b0), .CEB(B1EN), .CEA(1'b1),
+ .RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
+ .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
+ );
+ end else if (CFG_DBITS <= 8) begin
+ SDP #(
+ .READ_MODE(0),
+ .BIT_WIDTH_0(8),
+ .BIT_WIDTH_1(8),
+ .BLK_SEL(3'b000),
+ .RESET_MODE("SYNC")
+ ) _TECHMAP_REPLACE_ (
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
+ .WREB(1'b0), .CEB(B1EN),
+ .RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
+ .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
+ );
+ end else if (CFG_DBITS <= 16) begin
+ SDP #(
+ .READ_MODE(0),
+ .BIT_WIDTH_0(16),
+ .BIT_WIDTH_1(16),
+ .BLK_SEL(3'b000),
+ .RESET_MODE("SYNC")
+ ) _TECHMAP_REPLACE_ (
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WREA(A1EN), .OCE(1'b0),
+ .WREB(1'b0), .CEB(B1EN), .CEA(1'b1),
+ .RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
+ .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
+ );
+ end else begin
+ wire TECHMAP_FAIL = 1'b1;
+ end endgenerate
+
+endmodule
diff --git a/techlibs/gowin/cells_map.v b/techlibs/gowin/cells_map.v
index e1f85effa..ebdc88a0a 100644
--- a/techlibs/gowin/cells_map.v
+++ b/techlibs/gowin/cells_map.v
@@ -1,5 +1,9 @@
module \$_DFF_N_ (input D, C, output Q); DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
-module \$_DFF_P_ (input D, C, output Q); DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
+module \$_DFF_P_ #(parameter INIT = 1'b0) (input D, C, output Q); DFF #(.INIT(INIT)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
+
+module \$__DFFS_PN0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule
+module \$__DFFS_PP0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule
+module \$__DFFS_PP1_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule
module \$lut (A, Y);
parameter WIDTH = 0;
diff --git a/techlibs/gowin/cells_sim.v b/techlibs/gowin/cells_sim.v
index 14441c2fc..ebb238bad 100644
--- a/techlibs/gowin/cells_sim.v
+++ b/techlibs/gowin/cells_sim.v
@@ -38,6 +38,17 @@ module DFFN (output reg Q, input CLK, D);
Q <= D;
endmodule
+module DFFR (output reg Q, input D, CLK, RESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (RESET)
+ Q <= 1'b0;
+ else
+ Q <= D;
+ end
+endmodule // DFFR (positive clock edge; synchronous reset)
+
module VCC(output V);
assign V = 1;
endmodule
@@ -63,3 +74,126 @@ module ALU (input I0, input I1, input I3, input CIN, output COUT, output SUM);
assign {COUT, SUM} = CIN + I1 + I0;
endmodule // alu
+module RAM16S4 (DO, DI, AD, WRE, CLK);
+ parameter WIDTH = 4;
+ parameter INIT_0 = 16'h0000;
+ parameter INIT_1 = 16'h0000;
+ parameter INIT_2 = 16'h0000;
+ parameter INIT_3 = 16'h0000;
+
+ input [WIDTH-1:0] AD;
+ input [WIDTH-1:0] DI;
+ output [WIDTH-1:0] DO;
+ input CLK;
+ input WRE;
+
+ reg [15:0] mem0, mem1, mem2, mem3;
+
+ initial begin
+ mem0 = INIT_0;
+ mem1 = INIT_1;
+ mem2 = INIT_2;
+ mem3 = INIT_3;
+ end
+
+ assign DO[0] = mem0[AD];
+ assign DO[1] = mem1[AD];
+ assign DO[2] = mem2[AD];
+ assign DO[3] = mem3[AD];
+
+ always @(posedge CLK) begin
+ if (WRE) begin
+ mem0[AD] <= DI[0];
+ mem1[AD] <= DI[1];
+ mem2[AD] <= DI[2];
+ mem3[AD] <= DI[3];
+ end
+ end
+
+endmodule // RAM16S4
+
+
+(* blackbox *)
+module SDP (DO, DI, BLKSEL, ADA, ADB, WREA, WREB, CLKA, CLKB, CEA, CEB, OCE, RESETA, RESETB);
+//1'b0: Bypass mode; 1'b1 Pipeline mode
+parameter READ_MODE = 1'b0;
+parameter BIT_WIDTH_0 = 32; // 1, 2, 4, 8, 16, 32
+parameter BIT_WIDTH_1 = 32; // 1, 2, 4, 8, 16, 32
+parameter BLK_SEL = 3'b000;
+parameter RESET_MODE = "SYNC";
+parameter INIT_RAM_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+input CLKA, CEA, CLKB, CEB;
+input OCE; // clock enable of memory output register
+input RESETA, RESETB; // resets output registers, not memory contents
+input WREA, WREB; // 1'b0: read enabled; 1'b1: write enabled
+input [13:0] ADA, ADB;
+input [31:0] DI;
+input [2:0] BLKSEL;
+output [31:0] DO;
+
+endmodule
+
diff --git a/techlibs/gowin/determine_init.cc b/techlibs/gowin/determine_init.cc
new file mode 100644
index 000000000..991e5245a
--- /dev/null
+++ b/techlibs/gowin/determine_init.cc
@@ -0,0 +1,72 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct DetermineInitPass : public Pass {
+ DetermineInitPass() : Pass("determine_init", "Determine the init value of cells") { }
+ void help() YS_OVERRIDE
+ {
+ log("\n");
+ log(" determine_init [selection]\n");
+ log("\n");
+ log("Determine the init value of cells that doesn't allow unknown init value.\n");
+ log("\n");
+ }
+
+ Const determine_init(Const init)
+ {
+ for (int i = 0; i < GetSize(init); i++) {
+ if (init[i] != State::S0 && init[i] != State::S1)
+ init[i] = State::S0;
+ }
+
+ return init;
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing DETERMINE_INIT pass (determine init value for cells).\n");
+
+ extra_args(args, args.size(), design);
+
+ size_t cnt = 0;
+ for (auto module : design->selected_modules())
+ {
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "\\RAM16S4")
+ {
+ cell->setParam("\\INIT_0", determine_init(cell->getParam("\\INIT_0")));
+ cell->setParam("\\INIT_1", determine_init(cell->getParam("\\INIT_1")));
+ cell->setParam("\\INIT_2", determine_init(cell->getParam("\\INIT_2")));
+ cell->setParam("\\INIT_3", determine_init(cell->getParam("\\INIT_3")));
+ cnt++;
+ }
+ }
+ }
+ log_header(design, "Updated %lu cells with determined init value.\n", cnt);
+ }
+} DetermineInitPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/gowin/dram.txt b/techlibs/gowin/dram.txt
new file mode 100644
index 000000000..9db530251
--- /dev/null
+++ b/techlibs/gowin/dram.txt
@@ -0,0 +1,17 @@
+bram $__GW1NR_RAM16S4
+ init 1
+ abits 4
+ dbits 4
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 1
+ transp 0 1
+ clocks 0 1
+ clkpol 0 1
+endbram
+
+match $__GW1NR_RAM16S4
+ make_outreg
+ min wports 1
+endmatch
diff --git a/techlibs/gowin/drams_map.v b/techlibs/gowin/drams_map.v
new file mode 100644
index 000000000..a50ab365a
--- /dev/null
+++ b/techlibs/gowin/drams_map.v
@@ -0,0 +1,31 @@
+module \$__GW1NR_RAM16S4 (CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 4;
+ parameter CFG_DBITS = 4;
+
+ parameter [63:0] INIT = 64'bx;
+ input CLK1;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ output [CFG_DBITS-1:0] A1DATA;
+ input A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ input [CFG_DBITS-1:0] B1DATA;
+ input B1EN;
+
+ `include "brams_init3.vh"
+
+ RAM16S4
+ #(.INIT_0(INIT_0),
+ .INIT_1(INIT_1),
+ .INIT_2(INIT_2),
+ .INIT_3(INIT_3))
+ _TECHMAP_REPLACE_
+ (.AD(B1ADDR),
+ .DI(B1DATA),
+ .DO(A1DATA),
+ .CLK(CLK1),
+ .WRE(B1EN));
+
+
+endmodule
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index 96128a680..ac3dbfb29 100644
--- a/techlibs/gowin/synth_gowin.cc
+++ b/techlibs/gowin/synth_gowin.cc
@@ -49,9 +49,15 @@ struct SynthGowinPass : public ScriptPass
log(" from label is synonymous to 'begin', and empty to label is\n");
log(" synonymous to the end of the command list.\n");
log("\n");
+ log(" -nodffe\n");
+ log(" do not use flipflops with CE in output netlist\n");
+ log("\n");
log(" -nobram\n");
log(" do not use BRAM cells in output netlist\n");
log("\n");
+ log(" -nodram\n");
+ log(" do not use distributed RAM cells in output netlist\n");
+ log("\n");
log(" -noflatten\n");
log(" do not flatten design before synthesis\n");
log("\n");
@@ -65,7 +71,7 @@ struct SynthGowinPass : public ScriptPass
}
string top_opt, vout_file;
- bool retime, flatten, nobram;
+ bool retime, nobram, nodram, flatten, nodffe;
void clear_flags() YS_OVERRIDE
{
@@ -73,7 +79,9 @@ struct SynthGowinPass : public ScriptPass
vout_file = "";
retime = false;
flatten = true;
- nobram = true;
+ nobram = false;
+ nodffe = false;
+ nodram = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -108,10 +116,18 @@ struct SynthGowinPass : public ScriptPass
nobram = true;
continue;
}
+ if (args[argidx] == "-nodram") {
+ nodram = true;
+ continue;
+ }
+ if (args[argidx] == "-nodffe") {
+ nodffe = true;
+ continue;
+ }
if (args[argidx] == "-noflatten") {
flatten = false;
continue;
- }
+ }
break;
}
extra_args(args, argidx, design);
@@ -147,25 +163,43 @@ struct SynthGowinPass : public ScriptPass
{
run("synth -run coarse");
}
- if (!nobram && check_label("bram", "(skip if -nobram)"))
+
+ if (!nobram && check_label("bram", "(skip if -nobram)"))
{
run("memory_bram -rules +/gowin/bram.txt");
- run("techmap -map +/gowin/brams_map.v");
+ run("techmap -map +/gowin/brams_map.v -map +/gowin/cells_sim.v");
}
+
+ if (!nodram && check_label("dram", "(skip if -nodram)"))
+ {
+ run("memory_bram -rules +/gowin/dram.txt");
+ run("techmap -map +/gowin/drams_map.v");
+ run("determine_init");
+ }
+
if (check_label("fine"))
{
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
run("opt -undriven -fine");
run("techmap -map +/techmap.v -map +/gowin/arith_map.v");
- run("opt -fine");
- run("clean -purge");
- run("splitnets -ports");
- run("setundef -undriven -zero");
+ run("techmap -map +/techmap.v");
if (retime || help_mode)
run("abc -dff", "(only if -retime)");
}
+ if (check_label("map_ffs"))
+ {
+ run("dffsr2dff");
+ run("dff2dffs");
+ run("opt_clean");
+ if (!nodffe)
+ run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
+ run("techmap -map +/gowin/cells_map.v");
+ run("opt_expr -mux_undef");
+ run("simplemap");
+ }
+
if (check_label("map_luts"))
{
run("abc -lut 4");
@@ -176,8 +210,10 @@ struct SynthGowinPass : public ScriptPass
{
run("techmap -map +/gowin/cells_map.v");
run("hilomap -hicell VCC V -locell GND G");
- run("iopadmap -inpad IBUF O:I -outpad OBUF I:O");
- run("clean -purge");
+ run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O", "(unless -noiopads)");
+ run("dffinit -ff DFF Q INIT");
+ run("clean");
+
}
if (check_label("check"))
diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc
index 2750901c8..723b59d6f 100644
--- a/techlibs/ice40/Makefile.inc
+++ b/techlibs/ice40/Makefile.inc
@@ -1,5 +1,6 @@
OBJS += techlibs/ice40/synth_ice40.o
+OBJS += techlibs/ice40/ice40_braminit.o
OBJS += techlibs/ice40/ice40_ffssr.o
OBJS += techlibs/ice40/ice40_ffinit.o
OBJS += techlibs/ice40/ice40_opt.o
diff --git a/techlibs/ice40/brams_map.v b/techlibs/ice40/brams_map.v
index 19a61d73b..ad3bccd21 100644
--- a/techlibs/ice40/brams_map.v
+++ b/techlibs/ice40/brams_map.v
@@ -7,8 +7,8 @@ module \$__ICE40_RAM4K (
input [10:0] WADDR,
input [15:0] MASK, WDATA
);
- parameter integer READ_MODE = 0;
- parameter integer WRITE_MODE = 0;
+ parameter [1:0] READ_MODE = 0;
+ parameter [1:0] WRITE_MODE = 0;
parameter [0:0] NEGCLK_R = 0;
parameter [0:0] NEGCLK_W = 0;
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index 2041693cc..f9945b2b5 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -27,18 +27,27 @@ module SB_IO (
reg dout_q_0, dout_q_1;
reg outena_q;
+ // IO tile generates a constant 1'b1 internally if global_cen is not connected
+ wire clken_pulled = CLOCK_ENABLE || CLOCK_ENABLE === 1'bz;
+ reg clken_pulled_ri;
+ reg clken_pulled_ro;
+
generate if (!NEG_TRIGGER) begin
- always @(posedge INPUT_CLK) if (CLOCK_ENABLE) din_q_0 <= PACKAGE_PIN;
- always @(negedge INPUT_CLK) if (CLOCK_ENABLE) din_q_1 <= PACKAGE_PIN;
- always @(posedge OUTPUT_CLK) if (CLOCK_ENABLE) dout_q_0 <= D_OUT_0;
- always @(negedge OUTPUT_CLK) if (CLOCK_ENABLE) dout_q_1 <= D_OUT_1;
- always @(posedge OUTPUT_CLK) if (CLOCK_ENABLE) outena_q <= OUTPUT_ENABLE;
+ always @(posedge INPUT_CLK) clken_pulled_ri <= clken_pulled;
+ always @(posedge INPUT_CLK) if (clken_pulled) din_q_0 <= PACKAGE_PIN;
+ always @(negedge INPUT_CLK) if (clken_pulled_ri) din_q_1 <= PACKAGE_PIN;
+ always @(posedge OUTPUT_CLK) clken_pulled_ro <= clken_pulled;
+ always @(posedge OUTPUT_CLK) if (clken_pulled) dout_q_0 <= D_OUT_0;
+ always @(negedge OUTPUT_CLK) if (clken_pulled_ro) dout_q_1 <= D_OUT_1;
+ always @(posedge OUTPUT_CLK) if (clken_pulled) outena_q <= OUTPUT_ENABLE;
end else begin
- always @(negedge INPUT_CLK) if (CLOCK_ENABLE) din_q_0 <= PACKAGE_PIN;
- always @(posedge INPUT_CLK) if (CLOCK_ENABLE) din_q_1 <= PACKAGE_PIN;
- always @(negedge OUTPUT_CLK) if (CLOCK_ENABLE) dout_q_0 <= D_OUT_0;
- always @(posedge OUTPUT_CLK) if (CLOCK_ENABLE) dout_q_1 <= D_OUT_1;
- always @(negedge OUTPUT_CLK) if (CLOCK_ENABLE) outena_q <= OUTPUT_ENABLE;
+ always @(negedge INPUT_CLK) clken_pulled_ri <= clken_pulled;
+ always @(negedge INPUT_CLK) if (clken_pulled) din_q_0 <= PACKAGE_PIN;
+ always @(posedge INPUT_CLK) if (clken_pulled_ri) din_q_1 <= PACKAGE_PIN;
+ always @(negedge OUTPUT_CLK) clken_pulled_ro <= clken_pulled;
+ always @(negedge OUTPUT_CLK) if (clken_pulled) dout_q_0 <= D_OUT_0;
+ always @(posedge OUTPUT_CLK) if (clken_pulled_ro) dout_q_1 <= D_OUT_1;
+ always @(negedge OUTPUT_CLK) if (clken_pulled) outena_q <= OUTPUT_ENABLE;
end endgenerate
always @* begin
@@ -326,6 +335,8 @@ module SB_RAM40_4K (
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_FILE = "";
+
`ifndef BLACKBOX
wire [15:0] WMASK_I;
wire [15:0] RMASK_I;
@@ -408,43 +419,27 @@ module SB_RAM40_4K (
reg [15:0] memory [0:255];
initial begin
- for (i=0; i<16; i=i+1) begin
-`ifdef YOSYS
- memory[ 0*16 + i] <= INIT_0[16*i +: 16];
- memory[ 1*16 + i] <= INIT_1[16*i +: 16];
- memory[ 2*16 + i] <= INIT_2[16*i +: 16];
- memory[ 3*16 + i] <= INIT_3[16*i +: 16];
- memory[ 4*16 + i] <= INIT_4[16*i +: 16];
- memory[ 5*16 + i] <= INIT_5[16*i +: 16];
- memory[ 6*16 + i] <= INIT_6[16*i +: 16];
- memory[ 7*16 + i] <= INIT_7[16*i +: 16];
- memory[ 8*16 + i] <= INIT_8[16*i +: 16];
- memory[ 9*16 + i] <= INIT_9[16*i +: 16];
- memory[10*16 + i] <= INIT_A[16*i +: 16];
- memory[11*16 + i] <= INIT_B[16*i +: 16];
- memory[12*16 + i] <= INIT_C[16*i +: 16];
- memory[13*16 + i] <= INIT_D[16*i +: 16];
- memory[14*16 + i] <= INIT_E[16*i +: 16];
- memory[15*16 + i] <= INIT_F[16*i +: 16];
-`else
- memory[ 0*16 + i] = INIT_0[16*i +: 16];
- memory[ 1*16 + i] = INIT_1[16*i +: 16];
- memory[ 2*16 + i] = INIT_2[16*i +: 16];
- memory[ 3*16 + i] = INIT_3[16*i +: 16];
- memory[ 4*16 + i] = INIT_4[16*i +: 16];
- memory[ 5*16 + i] = INIT_5[16*i +: 16];
- memory[ 6*16 + i] = INIT_6[16*i +: 16];
- memory[ 7*16 + i] = INIT_7[16*i +: 16];
- memory[ 8*16 + i] = INIT_8[16*i +: 16];
- memory[ 9*16 + i] = INIT_9[16*i +: 16];
- memory[10*16 + i] = INIT_A[16*i +: 16];
- memory[11*16 + i] = INIT_B[16*i +: 16];
- memory[12*16 + i] = INIT_C[16*i +: 16];
- memory[13*16 + i] = INIT_D[16*i +: 16];
- memory[14*16 + i] = INIT_E[16*i +: 16];
- memory[15*16 + i] = INIT_F[16*i +: 16];
-`endif
- end
+ if (INIT_FILE != "")
+ $readmemh(INIT_FILE, memory);
+ else
+ for (i=0; i<16; i=i+1) begin
+ memory[ 0*16 + i] = INIT_0[16*i +: 16];
+ memory[ 1*16 + i] = INIT_1[16*i +: 16];
+ memory[ 2*16 + i] = INIT_2[16*i +: 16];
+ memory[ 3*16 + i] = INIT_3[16*i +: 16];
+ memory[ 4*16 + i] = INIT_4[16*i +: 16];
+ memory[ 5*16 + i] = INIT_5[16*i +: 16];
+ memory[ 6*16 + i] = INIT_6[16*i +: 16];
+ memory[ 7*16 + i] = INIT_7[16*i +: 16];
+ memory[ 8*16 + i] = INIT_8[16*i +: 16];
+ memory[ 9*16 + i] = INIT_9[16*i +: 16];
+ memory[10*16 + i] = INIT_A[16*i +: 16];
+ memory[11*16 + i] = INIT_B[16*i +: 16];
+ memory[12*16 + i] = INIT_C[16*i +: 16];
+ memory[13*16 + i] = INIT_D[16*i +: 16];
+ memory[14*16 + i] = INIT_E[16*i +: 16];
+ memory[15*16 + i] = INIT_F[16*i +: 16];
+ end
end
always @(posedge WCLK) begin
@@ -504,6 +499,8 @@ module SB_RAM40_4KNR (
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_FILE = "";
+
SB_RAM40_4K #(
.WRITE_MODE(WRITE_MODE),
.READ_MODE (READ_MODE ),
@@ -522,7 +519,8 @@ module SB_RAM40_4KNR (
.INIT_C (INIT_C ),
.INIT_D (INIT_D ),
.INIT_E (INIT_E ),
- .INIT_F (INIT_F )
+ .INIT_F (INIT_F ),
+ .INIT_FILE (INIT_FILE )
) RAM (
.RDATA(RDATA),
.RCLK (~RCLKN),
@@ -566,6 +564,8 @@ module SB_RAM40_4KNW (
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_FILE = "";
+
SB_RAM40_4K #(
.WRITE_MODE(WRITE_MODE),
.READ_MODE (READ_MODE ),
@@ -584,7 +584,8 @@ module SB_RAM40_4KNW (
.INIT_C (INIT_C ),
.INIT_D (INIT_D ),
.INIT_E (INIT_E ),
- .INIT_F (INIT_F )
+ .INIT_F (INIT_F ),
+ .INIT_FILE (INIT_FILE )
) RAM (
.RDATA(RDATA),
.RCLK (RCLK ),
@@ -628,6 +629,8 @@ module SB_RAM40_4KNRNW (
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_FILE = "";
+
SB_RAM40_4K #(
.WRITE_MODE(WRITE_MODE),
.READ_MODE (READ_MODE ),
@@ -646,7 +649,8 @@ module SB_RAM40_4KNRNW (
.INIT_C (INIT_C ),
.INIT_D (INIT_D ),
.INIT_E (INIT_E ),
- .INIT_F (INIT_F )
+ .INIT_F (INIT_F ),
+ .INIT_FILE (INIT_FILE )
) RAM (
.RDATA(RDATA),
.RCLK (~RCLKN),
@@ -926,10 +930,21 @@ endmodule
(* blackbox *)
module SB_HFOSC(
+ input TRIM0,
+ input TRIM1,
+ input TRIM2,
+ input TRIM3,
+ input TRIM4,
+ input TRIM5,
+ input TRIM6,
+ input TRIM7,
+ input TRIM8,
+ input TRIM9,
input CLKHFPU,
input CLKHFEN,
output CLKHF
);
+parameter TRIM_EN = "0b0";
parameter CLKHF_DIV = "0b00";
endmodule
@@ -959,6 +974,30 @@ parameter RGB2_CURRENT = "0b000000";
endmodule
(* blackbox *)
+module SB_LED_DRV_CUR(
+ input EN,
+ output LEDPU
+);
+endmodule
+
+(* blackbox *)
+module SB_RGB_DRV(
+ input RGBLEDEN,
+ input RGB0PWM,
+ input RGB1PWM,
+ input RGB2PWM,
+ input RGBPU,
+ output RGB0,
+ output RGB1,
+ output RGB2
+);
+parameter CURRENT_MODE = "0b0";
+parameter RGB0_CURRENT = "0b000000";
+parameter RGB1_CURRENT = "0b000000";
+parameter RGB2_CURRENT = "0b000000";
+endmodule
+
+(* blackbox *)
module SB_I2C(
input SBCLKI,
input SBRWI,
diff --git a/techlibs/ice40/ice40_braminit.cc b/techlibs/ice40/ice40_braminit.cc
new file mode 100644
index 000000000..4fa6b0792
--- /dev/null
+++ b/techlibs/ice40/ice40_braminit.cc
@@ -0,0 +1,159 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <bitset>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+static void run_ice40_braminit(Module *module)
+{
+ for (auto cell : module->selected_cells())
+ {
+ uint16_t mem[256];
+
+ /* Only consider cells we're interested in */
+ if (cell->type != "\\SB_RAM40_4K" &&
+ cell->type != "\\SB_RAM40_4KNR" &&
+ cell->type != "\\SB_RAM40_4KNW" &&
+ cell->type != "\\SB_RAM40_4KNRNW")
+ continue;
+ if (!cell->hasParam("\\INIT_FILE"))
+ continue;
+ std::string init_file = cell->getParam("\\INIT_FILE").decode_string();
+ cell->unsetParam("\\INIT_FILE");
+ if (init_file == "")
+ continue;
+
+ /* Open file */
+ log("Processing %s : %s\n", RTLIL::id2cstr(cell->name), init_file.c_str());
+
+ std::ifstream f;
+ f.open(init_file.c_str());
+ if (f.fail()) {
+ log("Can not open file `%s`.\n", init_file.c_str());
+ continue;
+ }
+
+ /* Defaults to 0 */
+ memset(mem, 0x00, sizeof(mem));
+
+ /* Process each line */
+ bool in_comment = false;
+ int cursor = 0;
+
+ while (!f.eof())
+ {
+ std::string line, token;
+ std::getline(f, line);
+
+ for (int i = 0; i < GetSize(line); i++)
+ {
+ if (in_comment && line.substr(i, 2) == "*/") {
+ line[i] = ' ';
+ line[i+1] = ' ';
+ in_comment = false;
+ continue;
+ }
+ if (!in_comment && line.substr(i, 2) == "/*")
+ in_comment = true;
+ if (in_comment)
+ line[i] = ' ';
+ }
+
+ while (1)
+ {
+ bool set_cursor = false;
+ long value;
+
+ token = next_token(line, " \t\r\n");
+ if (token.empty() || token.substr(0, 2) == "//")
+ break;
+
+ if (token[0] == '@') {
+ token = token.substr(1);
+ set_cursor = true;
+ }
+
+ const char *nptr = token.c_str();
+ char *endptr;
+ value = strtol(nptr, &endptr, 16);
+ if (!*nptr || *endptr) {
+ log("Can not parse %s `%s` for %s.\n",
+ set_cursor ? "address" : "value",
+ nptr, token.c_str()
+ );
+ continue;
+ }
+
+ if (set_cursor)
+ cursor = value;
+ else if (cursor >= 0 && cursor < 256)
+ mem[cursor++] = value;
+ else
+ log("Attempt to initialize non existent address %d\n", cursor);
+ }
+ }
+
+ /* Set attributes */
+ const char *hex = "0123456789ABCDEF";
+ for (int i=0; i<16; i++) {
+ std::string val = "";
+ for (int j=15; j>=0; j--)
+ val += std::bitset<16>(mem[i*16+j]).to_string();
+ cell->setParam("\\INIT_" + std::string(1, hex[i]), RTLIL::Const::from_string(val));
+ }
+ }
+}
+
+struct Ice40BRAMInitPass : public Pass {
+ Ice40BRAMInitPass() : Pass("ice40_braminit", "iCE40: perform SB_RAM40_4K initialization from file") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" ice40_braminit\n");
+ log("\n");
+ log("This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE\n");
+ log("parameter and converts it into the required INIT_x attributes\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing ICE40_BRAMINIT pass.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ // if (args[argidx] == "-???") {
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ run_ice40_braminit(module);
+ }
+} Ice40BRAMInitPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 34501b335..bb96d66d1 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -225,11 +225,13 @@ struct SynthIce40Pass : public ScriptPass
run("proc");
}
- if (flatten && check_label("flatten", "(unless -noflatten)"))
+ if (check_label("flatten", "(unless -noflatten)"))
{
- run("flatten");
- run("tribuf -logic");
- run("deminout");
+ if (flatten) {
+ run("flatten");
+ run("tribuf -logic");
+ run("deminout");
+ }
}
if (check_label("coarse"))
@@ -239,6 +241,8 @@ struct SynthIce40Pass : public ScriptPass
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");
@@ -257,6 +261,7 @@ struct SynthIce40Pass : public ScriptPass
{
run("memory_bram -rules +/ice40/brams.txt");
run("techmap -map +/ice40/brams_map.v");
+ run("ice40_braminit");
}
if (check_label("map"))
diff --git a/techlibs/intel/cycloneive/arith_map.v b/techlibs/intel/cycloneive/arith_map.v
index b3a11272b..49e36aa25 100644
--- a/techlibs/intel/cycloneive/arith_map.v
+++ b/techlibs/intel/cycloneive/arith_map.v
@@ -32,7 +32,7 @@ module fa
wire VCC;
assign VCC = 1'b1;
-
+
cycloneiv_lcell_comb gen_sum_0 (.combout(sum_x),
.dataa(a_c),
.datab(b_c),
@@ -40,7 +40,7 @@ module fa
.datad(VCC));
defparam syn__05_.lut_mask = 16'b1001011010010110;
defparam syn__05_.sum_lutc_input = "datac";
-
+
cycloneiv_lcell_comb gen_cout_0 (.combout(cout_t),
.dataa(cin_c),
.datab(b_c),
@@ -48,11 +48,11 @@ module fa
.datad(VCC));
defparam syn__06_.lut_mask = 16'b1110000011100000;
defparam syn__06_.sum_lutc_input = "datac";
-
+
endmodule // fa
module f_stage();
-
+
endmodule // f_stage
module f_end();
@@ -88,7 +88,7 @@ module _80_cycloneive_alu (A, B, CI, BI, X, Y, CO);
.cin_c(C[0]),
.cout_t(C0[1]),
.sum_x(Y[0]));
-
+
genvar i;
generate for (i = 1; i < Y_WIDTH; i = i + 1) begin:slice
cycloneive_lcell_comb #(.lut_mask(16'b0101_1010_0101_0000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(CO[i]), .dataa(BB[i]), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[i]));
diff --git a/techlibs/intel/cyclonev/cells_map.v b/techlibs/intel/cyclonev/cells_map.v
index bd60d4e17..f8d142bc9 100644
--- a/techlibs/intel/cyclonev/cells_map.v
+++ b/techlibs/intel/cyclonev/cells_map.v
@@ -76,7 +76,7 @@ module \$lut (A, Y);
wire VCC;
wire GND;
assign {VCC,GND} = {1'b1,1'b0};
-
+
generate
if (WIDTH == 1) begin
assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
@@ -151,7 +151,7 @@ module \$lut (A, Y);
TODO: There's not a just 7-input function on Cyclone V, see the following note:
**Extended LUT Mode**
Use extended LUT mode to implement a specific set of 7-input functions. The set must
- be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs.
+ be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs.
[source](Device Interfaces and Integration Basics for Cyclone V Devices).
end*/
else
diff --git a/techlibs/intel/cyclonev/cells_sim.v b/techlibs/intel/cyclonev/cells_sim.v
index fa27c2c8e..9b2a10e72 100644
--- a/techlibs/intel/cyclonev/cells_sim.v
+++ b/techlibs/intel/cyclonev/cells_sim.v
@@ -85,7 +85,7 @@ module cyclonev_lcell_comb
begin
upper_lut_value = lut4(mask[31:16], dataa, datab, datac, datad);
lower_lut_value = lut4(mask[15:0], dataa, datab, datac, datad);
- lut5 = (datae) ? upper_mask_value : lower_mask_value;
+ lut5 = (datae) ? upper_lut_value : lower_lut_value;
end
endfunction // lut5
@@ -95,15 +95,16 @@ module cyclonev_lcell_comb
input dataa, datab, datac, datad, datae, dataf;
reg upper_lut_value;
reg lower_lut_value;
+ reg out_0, out_1, out_2, out_3;
begin
upper_lut_value = lut5(mask[63:32], dataa, datab, datac, datad, datae);
lower_lut_value = lut5(mask[31:0], dataa, datab, datac, datad, datae);
- lut6 = (dataf) ? upper_mask_value : lower_mask_value;
+ lut6 = (dataf) ? upper_lut_value : lower_lut_value;
end
endfunction // lut6
assign {mask_a, mask_b, mask_c, mask_d} = {lut_mask[15:0], lut_mask[31:16], lut_mask[47:32], lut_mask[63:48]};
-
+`ifdef ADVANCED_ALM
always @(*) begin
if(extended_lut == "on")
shared_lut_alm = datag;
@@ -115,6 +116,11 @@ module cyclonev_lcell_comb
out_2 = lut4(mask_c, dataa, datab, datac, datad);
out_3 = lut4(mask_d, dataa, datab, shared_lut_alm, datad);
end
+`else
+ `ifdef DEBUG
+ initial $display("Advanced ALM lut combine is not implemented yet");
+ `endif
+`endif
endmodule // cyclonev_lcell_comb
diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc
index 0f1d7a7b5..639cba2c2 100644
--- a/techlibs/intel/synth_intel.cc
+++ b/techlibs/intel/synth_intel.cc
@@ -17,254 +17,243 @@
*
*/
-#include "kernel/register.h"
#include "kernel/celltypes.h"
-#include "kernel/rtlil.h"
#include "kernel/log.h"
+#include "kernel/register.h"
+#include "kernel/rtlil.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct SynthIntelPass : public ScriptPass {
- SynthIntelPass() : ScriptPass("synth_intel", "synthesis for Intel (Altera) FPGAs.") { }
+ SynthIntelPass() : ScriptPass("synth_intel", "synthesis for Intel (Altera) FPGAs.") {}
- void help() YS_OVERRIDE
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" synth_intel [options]\n");
- log("\n");
- log("This command runs synthesis for Intel FPGAs.\n");
- log("\n");
- log(" -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n");
- log(" generate the synthesis netlist for the specified family.\n");
- log(" MAX10 is the default target if not family argument specified.\n");
- log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n");
- log(" Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument.\n");
- log("\n");
- log(" -top <module>\n");
- log(" use the specified module as top module (default='top')\n");
- log("\n");
- log(" -vqm <file>\n");
- log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
- log(" output file is omitted if this parameter is not specified.\n");
- log("\n");
- log(" -vpr <file>\n");
- log(" write BLIF files for VPR flow experiments. The synthesized BLIF output file is not\n");
- log(" compatible with the Quartus flow. Writing of an\n");
- log(" output file is omitted if this parameter is not specified.\n");
- log("\n");
- log(" -run <from_label>:<to_label>\n");
- log(" only run the commands between the labels (see below). an empty\n");
- log(" from label is synonymous to 'begin', and empty to label is\n");
- log(" synonymous to the end of the command list.\n");
- log("\n");
- log(" -noiopads\n");
- log(" do not use altsyncram cells in output netlist\n");
- log("\n");
- log(" -nobram\n");
- log(" do not use altsyncram cells in output netlist\n");
- log("\n");
- log(" -noflatten\n");
- log(" do not flatten design before synthesis\n");
- log("\n");
- log(" -retime\n");
- log(" run 'abc' with -dff option\n");
- log("\n");
- log("The following commands are executed by this synthesis command:\n");
- help_script();
- log("\n");
- }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_intel [options]\n");
+ log("\n");
+ log("This command runs synthesis for Intel FPGAs.\n");
+ log("\n");
+ log(" -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n");
+ log(" generate the synthesis netlist for the specified family.\n");
+ log(" MAX10 is the default target if not family argument specified.\n");
+ log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n");
+ log(" Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module (default='top')\n");
+ log("\n");
+ log(" -vqm <file>\n");
+ log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
+ log(" output file is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -vpr <file>\n");
+ log(" write BLIF files for VPR flow experiments. The synthesized BLIF output file is not\n");
+ log(" compatible with the Quartus flow. Writing of an\n");
+ log(" output file is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -run <from_label>:<to_label>\n");
+ log(" only run the commands between the labels (see below). an empty\n");
+ log(" from label is synonymous to 'begin', and empty to label is\n");
+ log(" synonymous to the end of the command list.\n");
+ log("\n");
+ log(" -noiopads\n");
+ log(" do not use altsyncram cells in output netlist\n");
+ log("\n");
+ log(" -nobram\n");
+ log(" do not use altsyncram cells in output netlist\n");
+ log("\n");
+ log(" -noflatten\n");
+ log(" do not flatten design before synthesis\n");
+ log("\n");
+ log(" -retime\n");
+ log(" run 'abc' with -dff option\n");
+ log("\n");
+ log("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
- string top_opt, family_opt, vout_file, blif_file;
- bool retime, flatten, nobram, noiopads;
+ string top_opt, family_opt, vout_file, blif_file;
+ bool retime, flatten, nobram, noiopads;
- void clear_flags() YS_OVERRIDE
- {
- top_opt = "-auto-top";
- family_opt = "max10";
- vout_file = "";
- blif_file = "";
- retime = false;
- flatten = true;
- nobram = false;
- noiopads = false;
- }
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ family_opt = "max10";
+ vout_file = "";
+ blif_file = "";
+ retime = false;
+ flatten = true;
+ nobram = false;
+ noiopads = false;
+ }
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
- {
- string run_from, run_to;
- clear_flags();
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ string run_from, run_to;
+ clear_flags();
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++)
- {
- if (args[argidx] == "-family" && argidx+1 < args.size()) {
- family_opt = args[++argidx];
- continue;
- }
- if (args[argidx] == "-top" && argidx+1 < args.size()) {
- top_opt = "-top " + args[++argidx];
- continue;
- }
- if (args[argidx] == "-vqm" && argidx+1 < args.size()) {
- vout_file = args[++argidx];
- continue;
- }
- if (args[argidx] == "-vpr" && argidx+1 < args.size()) {
- blif_file = args[++argidx];
- continue;
- }
- if (args[argidx] == "-run" && argidx+1 < args.size()) {
- size_t pos = args[argidx+1].find(':');
- if (pos == std::string::npos)
- break;
- run_from = args[++argidx].substr(0, pos);
- run_to = args[argidx].substr(pos+1);
- continue;
- }
- if (args[argidx] == "-noiopads") {
- noiopads = true;
- continue;
- }
- if (args[argidx] == "-nobram") {
- nobram = true;
- continue;
- }
- if (args[argidx] == "-noflatten") {
- flatten = false;
- continue;
- }
- if (args[argidx] == "-retime") {
- retime = true;
- continue;
- }
- break;
- }
- extra_args(args, argidx, design);
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-family" && argidx + 1 < args.size()) {
+ family_opt = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-top" && argidx + 1 < args.size()) {
+ top_opt = "-top " + args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-vqm" && argidx + 1 < args.size()) {
+ vout_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-vpr" && argidx + 1 < args.size()) {
+ blif_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-run" && argidx + 1 < args.size()) {
+ size_t pos = args[argidx + 1].find(':');
+ if (pos == std::string::npos)
+ break;
+ run_from = args[++argidx].substr(0, pos);
+ run_to = args[argidx].substr(pos + 1);
+ continue;
+ }
+ if (args[argidx] == "-noiopads") {
+ noiopads = true;
+ continue;
+ }
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
+ if (args[argidx] == "-noflatten") {
+ flatten = false;
+ continue;
+ }
+ if (args[argidx] == "-retime") {
+ retime = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
- 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 != "cyclonev" && family_opt !="cycloneiv" && family_opt !="cycloneive" && family_opt != "cyclone10")
- log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str());
+ 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 != "cyclonev" && family_opt != "cycloneiv" &&
+ family_opt != "cycloneive" && family_opt != "cyclone10")
+ log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str());
- log_header(design, "Executing SYNTH_INTEL pass.\n");
- log_push();
+ log_header(design, "Executing SYNTH_INTEL pass.\n");
+ log_push();
- run_script(design, run_from, run_to);
+ run_script(design, run_from, run_to);
- log_pop();
- }
+ log_pop();
+ }
- void script() YS_OVERRIDE
- {
- if (check_label("begin"))
- {
- if(check_label("family") && family_opt=="max10")
- run("read_verilog -sv -lib +/intel/max10/cells_sim.v");
- else if(check_label("family") && family_opt=="a10gx")
- run("read_verilog -sv -lib +/intel/a10gx/cells_sim.v");
- else if(check_label("family") && family_opt=="cyclonev")
- run("read_verilog -sv -lib +/intel/cyclonev/cells_sim.v");
- else if(check_label("family") && family_opt=="cyclone10")
- run("read_verilog -sv -lib +/intel/cyclone10/cells_sim.v");
- else if(check_label("family") && family_opt=="cycloneiv")
- run("read_verilog -sv -lib +/intel/cycloneiv/cells_sim.v");
- else
- run("read_verilog -sv -lib +/intel/cycloneive/cells_sim.v");
- // Misc and common cells
- run("read_verilog -sv -lib +/intel/common/m9k_bb.v");
- run("read_verilog -sv -lib +/intel/common/altpll_bb.v");
- run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
- }
+ void script() YS_OVERRIDE
+ {
+ if (check_label("begin")) {
+ if (check_label("family") && family_opt == "max10")
+ run("read_verilog -sv -lib +/intel/max10/cells_sim.v");
+ else if (check_label("family") && family_opt == "a10gx")
+ run("read_verilog -sv -lib +/intel/a10gx/cells_sim.v");
+ else if (check_label("family") && family_opt == "cyclonev")
+ run("read_verilog -sv -lib +/intel/cyclonev/cells_sim.v");
+ else if (check_label("family") && family_opt == "cyclone10")
+ run("read_verilog -sv -lib +/intel/cyclone10/cells_sim.v");
+ else if (check_label("family") && family_opt == "cycloneiv")
+ run("read_verilog -sv -lib +/intel/cycloneiv/cells_sim.v");
+ else
+ run("read_verilog -sv -lib +/intel/cycloneive/cells_sim.v");
+ // Misc and common cells
+ run("read_verilog -sv -lib +/intel/common/m9k_bb.v");
+ run("read_verilog -sv -lib +/intel/common/altpll_bb.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ }
- if (flatten && check_label("flatten", "(unless -noflatten)"))
- {
- run("proc");
- run("flatten");
- run("tribuf -logic");
- run("deminout");
- }
+ if (flatten && check_label("flatten", "(unless -noflatten)")) {
+ run("proc");
+ run("flatten");
+ run("tribuf -logic");
+ run("deminout");
+ }
- if (check_label("coarse"))
- {
- run("synth -run coarse");
- }
+ if (check_label("coarse")) {
+ run("synth -run coarse");
+ }
- if (!nobram && check_label("bram", "(skip if -nobram)"))
- {
- run("memory_bram -rules +/intel/common/brams.txt");
- run("techmap -map +/intel/common/brams_map.v");
- }
+ if (!nobram && check_label("bram", "(skip if -nobram)")) {
+ run("memory_bram -rules +/intel/common/brams.txt");
+ run("techmap -map +/intel/common/brams_map.v");
+ }
- if (check_label("fine"))
- {
- run("opt -fast -mux_undef -undriven -fine -full");
- run("memory_map");
- run("opt -undriven -fine");
- run("dffsr2dff");
- run("dff2dffe -direct-match $_DFF_*");
- run("opt -fine");
- run("techmap -map +/techmap.v");
- run("opt -full");
- run("clean -purge");
- run("setundef -undriven -zero");
- if (retime || help_mode)
- run("abc -markgroups -dff", "(only if -retime)");
- }
+ if (check_label("fine")) {
+ run("opt -fast -mux_undef -undriven -fine -full");
+ run("memory_map");
+ run("opt -undriven -fine");
+ run("dffsr2dff");
+ run("dff2dffe -direct-match $_DFF_*");
+ run("opt -fine");
+ run("techmap -map +/techmap.v");
+ run("opt -full");
+ run("clean -purge");
+ run("setundef -undriven -zero");
+ if (retime || help_mode)
+ run("abc -markgroups -dff", "(only if -retime)");
+ }
- if (check_label("map_luts"))
- {
- if(family_opt=="a10gx" || family_opt=="cyclonev")
- run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));
- else
- run("abc -lut 4" + string(retime ? " -dff" : ""));
- run("clean");
- }
+ if (check_label("map_luts")) {
+ if (family_opt == "a10gx" || family_opt == "cyclonev")
+ run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));
+ else
+ run("abc -lut 4" + string(retime ? " -dff" : ""));
+ run("clean");
+ }
- if (check_label("map_cells"))
- {
- if (!noiopads)
- run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(unless -noiopads)");
- if(family_opt=="max10")
- run("techmap -map +/intel/max10/cells_map.v");
- else if(family_opt=="a10gx")
- run("techmap -map +/intel/a10gx/cells_map.v");
- else if(family_opt=="cyclonev")
- run("techmap -map +/intel/cyclonev/cells_map.v");
- else if(family_opt=="cyclone10")
- run("techmap -map +/intel/cyclone10/cells_map.v");
- else if(family_opt=="cycloneiv")
- run("techmap -map +/intel/cycloneiv/cells_map.v");
- else
- run("techmap -map +/intel/cycloneive/cells_map.v");
- run("dffinit -highlow -ff dffeas q power_up");
- run("clean -purge");
- }
+ if (check_label("map_cells")) {
+ if (!noiopads)
+ run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(unless -noiopads)");
+ if (family_opt == "max10")
+ run("techmap -map +/intel/max10/cells_map.v");
+ else if (family_opt == "a10gx")
+ run("techmap -map +/intel/a10gx/cells_map.v");
+ else if (family_opt == "cyclonev")
+ run("techmap -map +/intel/cyclonev/cells_map.v");
+ else if (family_opt == "cyclone10")
+ run("techmap -map +/intel/cyclone10/cells_map.v");
+ else if (family_opt == "cycloneiv")
+ run("techmap -map +/intel/cycloneiv/cells_map.v");
+ else
+ run("techmap -map +/intel/cycloneive/cells_map.v");
+ run("dffinit -highlow -ff dffeas q power_up");
+ run("clean -purge");
+ }
- if (check_label("check"))
- {
- run("hierarchy -check");
- run("stat");
- run("check -noinit");
- }
+ if (check_label("check")) {
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
- if (check_label("vqm"))
- {
- if (!vout_file.empty() || help_mode)
- run(stringf("write_verilog -attr2comment -defparam -nohex -decimal -renameprefix syn_ %s",
- help_mode ? "<file-name>" : vout_file.c_str()));
- }
+ if (check_label("vqm")) {
+ if (!vout_file.empty() || help_mode)
+ run(stringf("write_verilog -attr2comment -defparam -nohex -decimal -renameprefix syn_ %s",
+ help_mode ? "<file-name>" : vout_file.c_str()));
+ }
- if (check_label("vpr"))
- {
- if (!blif_file.empty() || help_mode)
- {
- run(stringf("opt_clean -purge"));
- run(stringf("write_blif %s", help_mode ? "<file-name>" : blif_file.c_str()));
- }
- }
- }
+ if (check_label("vpr")) {
+ if (!blif_file.empty() || help_mode) {
+ run(stringf("opt_clean -purge"));
+ run(stringf("write_blif %s", help_mode ? "<file-name>" : blif_file.c_str()));
+ }
+ }
+ }
} SynthIntelPass;
PRIVATE_NAMESPACE_END
diff --git a/techlibs/sf2/cells_map.v b/techlibs/sf2/cells_map.v
index 5b8888294..6ad7807d2 100644
--- a/techlibs/sf2/cells_map.v
+++ b/techlibs/sf2/cells_map.v
@@ -1,40 +1,54 @@
-// module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule
+module \$_DFF_N_ (input D, C, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+endmodule
module \$_DFF_P_ (input D, C, output Q);
- SLE _TECHMAP_REPLACE_ (
- .D(D),
- .CLK(C),
- .EN(1'b1),
- .ALn(1'b1),
- .ADn(1'b1),
- .SLn(1'b1),
- .SD(1'b0),
- .LAT(1'b0),
- .Q(Q)
- );
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+endmodule
+
+module \$_DFF_NN0_ (input D, C, R, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+endmodule
+
+module \$_DFF_NN1_ (input D, C, R, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+endmodule
+
+module \$_DFF_NP0_ (input D, C, R, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+endmodule
+
+module \$_DFF_NP1_ (input D, C, R, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+endmodule
+
+module \$_DFF_PN0_ (input D, C, R, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+endmodule
+
+module \$_DFF_PN1_ (input D, C, R, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+endmodule
+
+module \$_DFF_PP0_ (input D, C, R, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+endmodule
+
+module \$_DFF_PP1_ (input D, C, R, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
endmodule
// module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
// module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
-//
+//
// module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
// module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
-//
-// module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
-// module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
-// module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
-// module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
-//
-// module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
-// module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
-// module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
-// module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
-//
+//
// module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
// module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
// module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
// module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
-//
+//
// module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
// module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
// module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v
index f967068af..c62748b11 100644
--- a/techlibs/sf2/cells_sim.v
+++ b/techlibs/sf2/cells_sim.v
@@ -1,3 +1,114 @@
+// https://coredocs.s3.amazonaws.com/Libero/12_0_0/Tool/sf2_mlg.pdf
+
+module ADD2 (
+
+ input A, B,
+ output Y
+);
+ assign Y = A & B;
+endmodule
+
+module ADD3 (
+ input A, B, C,
+ output Y
+);
+ assign Y = A & B & C;
+endmodule
+
+module ADD4 (
+ input A, B, C, D,
+ output Y
+);
+ assign Y = A & B & C & D;
+endmodule
+
+module CFG1 (
+ output Y,
+ input A
+);
+ parameter [1:0] INIT = 2'h0;
+ assign Y = INIT >> A;
+endmodule
+
+module CFG2 (
+ output Y,
+ input A,
+ input B
+);
+ parameter [3:0] INIT = 4'h0;
+ assign Y = INIT >> {B, A};
+endmodule
+
+module CFG3 (
+ output Y,
+ input A,
+ input B,
+ input C
+);
+ parameter [7:0] INIT = 8'h0;
+ assign Y = INIT >> {C, B, A};
+endmodule
+
+module CFG4 (
+ output Y,
+ input A,
+ input B,
+ input C,
+ input D
+);
+ parameter [15:0] INIT = 16'h0;
+ assign Y = INIT >> {D, C, B, A};
+endmodule
+
+module BUFF (
+ input A,
+ output Y
+);
+ assign Y = A;
+endmodule
+
+module BUFD (
+ input A,
+ output Y
+);
+ assign Y = A;
+endmodule
+
+module CLKINT (
+ input A,
+ output Y
+);
+ assign Y = A;
+endmodule
+
+module CLKINT_PRESERVE (
+ input A,
+ output Y
+);
+ assign Y = A;
+endmodule
+
+module GCLKINT (
+ input A, EN,
+ output Y
+);
+ assign Y = A & EN;
+endmodule
+
+module RCLKINT (
+ input A,
+ output Y
+);
+ assign Y = A;
+endmodule
+
+module RGCLKINT (
+ input A, EN,
+ output Y
+);
+ assign Y = A & EN;
+endmodule
+
module SLE (
output Q,
input ADn,
@@ -36,44 +147,151 @@ module SLE (
assign Q = LAT ? q_latch : q_ff;
endmodule
-module CFG1 (
- output Y,
- input A
+// module AR1
+// module FCEND_BUFF
+// module FCINIT_BUFF
+// module FLASH_FREEZE
+// module OSCILLATOR
+// module SYSRESET
+// module SYSCTRL_RESET_STATUS
+// module LIVE_PROBE_FB
+// module GCLKBUF
+// module GCLKBUF_DIFF
+// module GCLKBIBUF
+// module DFN1
+// module DFN1C0
+// module DFN1E1
+// module DFN1E1C0
+// module DFN1E1P0
+// module DFN1P0
+// module DLN1
+// module DLN1C0
+// module DLN1P0
+
+module INV (
+ input A,
+ output Y
);
- parameter [1:0] INIT = 2'h0;
- assign Y = INIT >> A;
+ assign Y = !A;
endmodule
-module CFG2 (
- output Y,
+module INVD (
input A,
- input B
+ output Y
);
- parameter [3:0] INIT = 4'h0;
- assign Y = INIT >> {B, A};
+ assign Y = !A;
endmodule
-module CFG3 (
- output Y,
- input A,
- input B,
- input C
+module MX2 (
+ input A, B, S,
+ output Y
);
- parameter [7:0] INIT = 8'h0;
- assign Y = INIT >> {C, B, A};
+ assign Y = S ? B : A;
endmodule
-module CFG4 (
- output Y,
- input A,
- input B,
- input C,
- input D
+module MX4 (
+ input D0, D1, D2, D3, S0, S1,
+ output Y
);
- parameter [15:0] INIT = 16'h0;
- assign Y = INIT >> {D, C, B, A};
+ assign Y = S1 ? (S0 ? D3 : D2) : (S0 ? D1 : D0);
+endmodule
+
+module NAND2 (
+ input A, B,
+ output Y
+);
+ assign Y = !(A & B);
+endmodule
+
+module NAND3 (
+ input A, B, C,
+ output Y
+);
+ assign Y = !(A & B & C);
+endmodule
+
+module NAND4 (
+ input A, B, C, D,
+ output Y
+);
+ assign Y = !(A & B & C & D);
+endmodule
+
+module NOR2 (
+ input A, B,
+ output Y
+);
+ assign Y = !(A | B);
+endmodule
+
+module NOR3 (
+ input A, B, C,
+ output Y
+);
+ assign Y = !(A | B | C);
+endmodule
+
+module NOR4 (
+ input A, B, C, D,
+ output Y
+);
+ assign Y = !(A | B | C | D);
endmodule
+module OR2 (
+ input A, B,
+ output Y
+);
+ assign Y = A | B;
+endmodule
+
+module OR3 (
+ input A, B, C,
+ output Y
+);
+ assign Y = A | B | C;
+endmodule
+
+module OR4 (
+ input A, B, C, D,
+ output Y
+);
+ assign Y = A | B | C | D;
+endmodule
+
+module XOR2 (
+ input A, B,
+ output Y
+);
+ assign Y = A ^ B;
+endmodule
+
+module XOR3 (
+ input A, B, C,
+ output Y
+);
+ assign Y = A ^ B ^ C;
+endmodule
+
+module XOR4 (
+ input A, B, C, D,
+ output Y
+);
+ assign Y = A ^ B ^ C ^ D;
+endmodule
+
+module XOR8 (
+ input A, B, C, D, E, F, G, H,
+ output Y
+);
+ assign Y = A ^ B ^ C ^ D ^ E ^ F ^ G ^ H;
+endmodule
+
+// module UJTAG
+// module BIBUF
+// module BIBUF_DIFF
+// module CLKBIBUF
+
module CLKBUF (
input PAD,
output Y
@@ -81,6 +299,8 @@ module CLKBUF (
assign Y = PAD;
endmodule
+// module CLKBUF_DIFF
+
module INBUF (
input PAD,
output Y
@@ -88,9 +308,20 @@ module INBUF (
assign Y = PAD;
endmodule
+// module INBUF_DIFF
+
module OUTBUF (
input D,
output PAD
);
assign PAD = D;
endmodule
+
+// module OUTBUF_DIFF
+// module TRIBUFF
+// module TRIBUFF_DIFF
+// module DDR_IN
+// module DDR_OUT
+// module RAM1K18
+// module RAM64x18
+// module MACC
diff --git a/techlibs/sf2/sf2_iobs.cc b/techlibs/sf2/sf2_iobs.cc
index 27141430c..3d43332e2 100644
--- a/techlibs/sf2/sf2_iobs.cc
+++ b/techlibs/sf2/sf2_iobs.cc
@@ -23,6 +23,136 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+static void handle_iobufs(Module *module, bool clkbuf_mode)
+{
+ SigMap sigmap(module);
+
+ pool<SigBit> clk_bits;
+ pool<SigBit> handled_io_bits;
+ dict<SigBit, SigBit> rewrite_bits;
+ vector<pair<Cell*, SigBit>> pad_bits;
+
+ for (auto cell : module->cells())
+ {
+ if (clkbuf_mode && cell->type == "\\SLE") {
+ for (auto bit : sigmap(cell->getPort("\\CLK")))
+ clk_bits.insert(bit);
+ }
+ if (cell->type.in("\\INBUF", "\\OUTBUF", "\\TRIBUFF", "\\BIBUF", "\\CLKBUF", "\\CLKBIBUF",
+ "\\INBUF_DIFF", "\\OUTBUF_DIFF", "\\BIBUFF_DIFF", "\\TRIBUFF_DIFF", "\\CLKBUF_DIFF",
+ "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF")) {
+ for (auto bit : sigmap(cell->getPort("\\PAD")))
+ handled_io_bits.insert(bit);
+ }
+ }
+
+ for (auto wire : vector<Wire*>(module->wires()))
+ {
+ if (!wire->port_input && !wire->port_output)
+ continue;
+
+ for (int index = 0; index < GetSize(wire); index++)
+ {
+ SigBit bit(wire, index);
+ SigBit canonical_bit = sigmap(bit);
+
+ if (handled_io_bits.count(canonical_bit))
+ continue;
+
+ if (wire->port_input && wire->port_output)
+ log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit));
+
+ IdString buf_type, buf_port;
+
+ if (wire->port_output) {
+ buf_type = "\\OUTBUF";
+ buf_port = "\\D";
+ } else if (clkbuf_mode && clk_bits.count(canonical_bit)) {
+ buf_type = "\\CLKBUF";
+ buf_port = "\\Y";
+ } else {
+ buf_type = "\\INBUF";
+ buf_port = "\\Y";
+ }
+
+ Cell *c = module->addCell(NEW_ID, buf_type);
+ SigBit new_bit = module->addWire(NEW_ID);
+ c->setPort(buf_port, new_bit);
+ pad_bits.push_back(make_pair(c, bit));
+ rewrite_bits[canonical_bit] = new_bit;
+
+ log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
+ }
+ }
+
+ auto rewrite_function = [&](SigSpec &s) {
+ for (auto &bit : s) {
+ SigBit canonical_bit = sigmap(bit);
+ if (rewrite_bits.count(canonical_bit))
+ bit = rewrite_bits.at(canonical_bit);
+ }
+ };
+
+ module->rewrite_sigspecs(rewrite_function);
+
+ for (auto &it : pad_bits)
+ it.first->setPort("\\PAD", it.second);
+}
+
+static void handle_clkint(Module *module)
+{
+ SigMap sigmap(module);
+
+ pool<SigBit> clk_bits;
+ vector<SigBit> handled_clk_bits;
+
+ for (auto cell : module->cells())
+ {
+ if (cell->type == "\\SLE") {
+ for (auto bit : sigmap(cell->getPort("\\CLK")))
+ clk_bits.insert(bit);
+ }
+ if (cell->type.in("\\CLKBUF", "\\CLKBIBUF", "\\CLKBUF_DIFF", "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF",
+ "\\CLKINT", "\\CLKINT_PRESERVE", "\\GCLKINT", "\\RCLKINT", "\\RGCLKINT")) {
+ for (auto bit : sigmap(cell->getPort("\\Y")))
+ handled_clk_bits.push_back(bit);
+ }
+ }
+
+ for (auto bit : handled_clk_bits)
+ clk_bits.erase(bit);
+
+ for (auto cell : vector<Cell*>(module->cells()))
+ for (auto &conn : cell->connections())
+ {
+ if (!cell->output(conn.first))
+ continue;
+
+ SigSpec sig = conn.second;
+ bool did_something = false;
+
+ for (auto &bit : sig) {
+ SigBit canonical_bit = sigmap(bit);
+ if (clk_bits.count(canonical_bit)) {
+ Cell *c = module->addCell(NEW_ID, "\\CLKINT");
+ SigBit new_bit = module->addWire(NEW_ID);
+ c->setPort("\\A", new_bit);
+ c->setPort("\\Y", bit);
+ log("Added %s cell %s for clock signal %s.\n", log_id(c->type), log_id(c), log_signal(bit));
+ clk_bits.erase(canonical_bit);
+ did_something = true;
+ bit = new_bit;
+ }
+ }
+
+ if (did_something)
+ cell->setPort(conn.first, sig);
+ }
+
+ for (auto bit : clk_bits)
+ log_error("Failed to insert CLKINT for clock signal %s.\n", log_signal(bit));
+}
+
struct Sf2IobsPass : public Pass {
Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }
void help() YS_OVERRIDE
@@ -31,20 +161,25 @@ struct Sf2IobsPass : public Pass {
log("\n");
log(" sf2_iobs [options] [selection]\n");
log("\n");
- log("Add SF2 I/O buffers to top module IOs as needed.\n");
+ log("Add SF2 I/O buffers and global buffers to top module as needed.\n");
+ log("\n");
+ log(" -clkbuf\n");
+ log(" Insert PAD->global_net clock buffers\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
+ bool clkbuf_mode = false;
+
log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
- // if (args[argidx] == "-singleton") {
- // singleton_mode = true;
- // continue;
- // }
+ if (args[argidx] == "-clkbuf") {
+ clkbuf_mode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -54,76 +189,8 @@ struct Sf2IobsPass : public Pass {
if (module == nullptr)
log_cmd_error("No top module found.\n");
- SigMap sigmap(module);
-
- pool<SigBit> clk_bits;
- pool<SigBit> handled_io_bits;
- dict<SigBit, SigBit> rewrite_bits;
- vector<pair<Cell*, SigBit>> pad_bits;
-
- for (auto cell : module->cells())
- {
- if (cell->type == "\\SLE") {
- for (auto bit : sigmap(cell->getPort("\\CLK")))
- clk_bits.insert(bit);
- }
- if (cell->type.in("\\INBUF", "\\OUTBUF", "\\CLKBUF")) {
- for (auto bit : sigmap(cell->getPort("\\PAD")))
- handled_io_bits.insert(bit);
- }
- }
-
- for (auto wire : vector<Wire*>(module->wires()))
- {
- if (!wire->port_input && !wire->port_output)
- continue;
-
- for (int index = 0; index < GetSize(wire); index++)
- {
- SigBit bit(wire, index);
- SigBit canonical_bit = sigmap(bit);
-
- if (handled_io_bits.count(canonical_bit))
- continue;
-
- if (wire->port_input && wire->port_output)
- log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit));
-
- IdString buf_type, buf_port;
-
- if (wire->port_output) {
- buf_type = "\\OUTBUF";
- buf_port = "\\D";
- } else if (clk_bits.count(canonical_bit)) {
- buf_type = "\\CLKBUF";
- buf_port = "\\Y";
- } else {
- buf_type = "\\INBUF";
- buf_port = "\\Y";
- }
-
- Cell *c = module->addCell(NEW_ID, buf_type);
- SigBit new_bit = module->addWire(NEW_ID);
- c->setPort(buf_port, new_bit);
- pad_bits.push_back(make_pair(c, bit));
- rewrite_bits[canonical_bit] = new_bit;
-
- log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
- }
- }
-
- auto rewrite_function = [&](SigSpec &s) {
- for (auto &bit : s) {
- SigBit canonical_bit = sigmap(bit);
- if (rewrite_bits.count(canonical_bit))
- bit = rewrite_bits.at(canonical_bit);
- }
- };
-
- module->rewrite_sigspecs(rewrite_function);
-
- for (auto &it : pad_bits)
- it.first->setPort("\\PAD", it.second);
+ handle_iobufs(module, clkbuf_mode);
+ handle_clkint(module);
}
} Sf2IobsPass;
diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc
index bdc20456d..0924df7a6 100644
--- a/techlibs/sf2/synth_sf2.cc
+++ b/techlibs/sf2/synth_sf2.cc
@@ -63,6 +63,9 @@ struct SynthSf2Pass : public ScriptPass
log(" -noiobs\n");
log(" run synthesis in \"block mode\", i.e. do not insert IO buffers\n");
log("\n");
+ log(" -clkbuf\n");
+ log(" insert direct PAD->global_net buffers\n");
+ log("\n");
log(" -retime\n");
log(" run 'abc' with -dff option\n");
log("\n");
@@ -73,7 +76,7 @@ struct SynthSf2Pass : public ScriptPass
}
string top_opt, edif_file, vlog_file, json_file;
- bool flatten, retime, iobs;
+ bool flatten, retime, iobs, clkbuf;
void clear_flags() YS_OVERRIDE
{
@@ -84,6 +87,7 @@ struct SynthSf2Pass : public ScriptPass
flatten = true;
retime = false;
iobs = true;
+ clkbuf = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -130,6 +134,10 @@ struct SynthSf2Pass : public ScriptPass
iobs = false;
continue;
}
+ if (args[argidx] == "-clkbuf") {
+ clkbuf = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -201,8 +209,10 @@ struct SynthSf2Pass : public ScriptPass
if (check_label("map_iobs"))
{
- if (iobs || help_mode)
- run("sf2_iobs", "(unless -noiobs)");
+ if (help_mode)
+ run("sf2_iobs [-clkbuf]", "(unless -noiobs)");
+ else if (iobs)
+ run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs");
run("clean");
}
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index 887ea27d9..d68f03bb4 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -28,7 +28,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_bb.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut2lut.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh))
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh))
diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v
index 03719659b..09a5f07e8 100644
--- a/techlibs/xilinx/arith_map.v
+++ b/techlibs/xilinx/arith_map.v
@@ -17,6 +17,9 @@
*
*/
+// ============================================================================
+// LCU
+
(* techmap_celltype = "$lcu" *)
module _80_xilinx_lcu (P, G, CI, CO);
parameter WIDTH = 2;
@@ -28,10 +31,78 @@ module _80_xilinx_lcu (P, G, CI, CO);
wire _TECHMAP_FAIL_ = WIDTH <= 2;
+ genvar i;
+
+`ifdef _CLB_CARRY
+
+ localparam CARRY4_COUNT = (WIDTH + 3) / 4;
+ localparam MAX_WIDTH = CARRY4_COUNT * 4;
+ localparam PAD_WIDTH = MAX_WIDTH - WIDTH;
+
+ wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, P & ~G};
+ wire [MAX_WIDTH-1:0] C = CO;
+
+ generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice
+
+ // Partially occupied CARRY4
+ if ((i+1)*4 > WIDTH) begin
+
+ // First one
+ if (i == 0) begin
+ CARRY4 carry4_1st_part
+ (
+ .CYINIT(CI),
+ .CI (1'd0),
+ .DI (G [(Y_WIDTH - 1):i*4]),
+ .S (S [(Y_WIDTH - 1):i*4]),
+ .CO (CO[(Y_WIDTH - 1):i*4]),
+ );
+ // Another one
+ end else begin
+ CARRY4 carry4_part
+ (
+ .CYINIT(1'd0),
+ .CI (C [i*4 - 1]),
+ .DI (G [(Y_WIDTH - 1):i*4]),
+ .S (S [(Y_WIDTH - 1):i*4]),
+ .CO (CO[(Y_WIDTH - 1):i*4]),
+ );
+ end
+
+ // Fully occupied CARRY4
+ end else begin
+
+ // First one
+ if (i == 0) begin
+ CARRY4 carry4_1st_full
+ (
+ .CYINIT(CI),
+ .CI (1'd0),
+ .DI (G [((i+1)*4 - 1):i*4]),
+ .S (S [((i+1)*4 - 1):i*4]),
+ .CO (CO[((i+1)*4 - 1):i*4]),
+ );
+ // Another one
+ end else begin
+ CARRY4 carry4_full
+ (
+ .CYINIT(1'd0),
+ .CI (C [i*4 - 1]),
+ .DI (G [((i+1)*4 - 1):i*4]),
+ .S (S [((i+1)*4 - 1):i*4]),
+ .CO (CO[((i+1)*4 - 1):i*4]),
+ );
+ end
+
+ end
+
+ end endgenerate
+
+`elsif _EXPLICIT_CARRY
+
wire [WIDTH-1:0] C = {CO, CI};
wire [WIDTH-1:0] S = P & ~G;
- genvar i;
generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
MUXCY muxcy (
.CI(C[i]),
@@ -40,8 +111,28 @@ module _80_xilinx_lcu (P, G, CI, CO);
.O(CO[i])
);
end endgenerate
+
+`else
+
+ wire [WIDTH-1:0] C = {CO, CI};
+ wire [WIDTH-1:0] S = P & ~G;
+
+ generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
+ MUXCY muxcy (
+ .CI(C[i]),
+ .DI(G[i]),
+ .S(S[i]),
+ .O(CO[i])
+ );
+ end endgenerate
+`endif
+
endmodule
+
+// ============================================================================
+// ALU
+
(* techmap_celltype = "$alu" *)
module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
parameter A_SIGNED = 0;
@@ -49,6 +140,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
+ parameter _TECHMAP_CONSTVAL_CI_ = 0;
+ parameter _TECHMAP_CONSTMSK_CI_ = 0;
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
@@ -66,16 +159,189 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
wire [Y_WIDTH-1:0] AA = A_buf;
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
- wire [Y_WIDTH-1:0] P = AA ^ BB;
- wire [Y_WIDTH-1:0] G = AA & BB;
- wire [Y_WIDTH-1:0] C = {CO, CI};
- wire [Y_WIDTH-1:0] S = P & ~G;
+ genvar i;
+
+`ifdef _CLB_CARRY
+
+ localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4;
+ localparam MAX_WIDTH = CARRY4_COUNT * 4;
+ localparam PAD_WIDTH = MAX_WIDTH - Y_WIDTH;
+
+ wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, AA ^ BB};
+ wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA & BB};
+
+ wire [MAX_WIDTH-1:0] C = CO;
genvar i;
+ generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice
+
+ // Partially occupied CARRY4
+ if ((i+1)*4 > Y_WIDTH) begin
+
+ // First one
+ if (i == 0) begin
+ CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_part
+ (
+ .CYINIT(CI),
+ .CI (1'd0),
+ .DI (DI[(Y_WIDTH - 1):i*4]),
+ .S (S [(Y_WIDTH - 1):i*4]),
+ .O (Y [(Y_WIDTH - 1):i*4]),
+ .CO (CO[(Y_WIDTH - 1):i*4])
+ );
+ // Another one
+ end else begin
+ CARRY4 carry4_part
+ (
+ .CYINIT(1'd0),
+ .CI (C [i*4 - 1]),
+ .DI (DI[(Y_WIDTH - 1):i*4]),
+ .S (S [(Y_WIDTH - 1):i*4]),
+ .O (Y [(Y_WIDTH - 1):i*4]),
+ .CO (CO[(Y_WIDTH - 1):i*4])
+ );
+ end
+
+ // Fully occupied CARRY4
+ end else begin
+
+ // First one
+ if (i == 0) begin
+ CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_full
+ (
+ .CYINIT(CI),
+ .CI (1'd0),
+ .DI (DI[((i+1)*4 - 1):i*4]),
+ .S (S [((i+1)*4 - 1):i*4]),
+ .O (Y [((i+1)*4 - 1):i*4]),
+ .CO (CO[((i+1)*4 - 1):i*4])
+ );
+ // Another one
+ end else begin
+ CARRY4 carry4_full
+ (
+ .CYINIT(1'd0),
+ .CI (C [i*4 - 1]),
+ .DI (DI[((i+1)*4 - 1):i*4]),
+ .S (S [((i+1)*4 - 1):i*4]),
+ .O (Y [((i+1)*4 - 1):i*4]),
+ .CO (CO[((i+1)*4 - 1):i*4])
+ );
+ end
+
+ end
+
+ end endgenerate
+
+`elsif _EXPLICIT_CARRY
+
+ wire [Y_WIDTH-1:0] S = AA ^ BB;
+ wire [Y_WIDTH-1:0] DI = AA & BB;
+
+ wire CINIT;
+ // Carry chain.
+ //
+ // VPR requires that the carry chain never hit the fabric. The CO input
+ // to this techmap is the carry outputs for synthesis, e.g. might hit the
+ // fabric.
+ //
+ // So we maintain two wire sets, CO_CHAIN is the carry that is for VPR,
+ // e.g. off fabric dedicated chain. CO is the carry outputs that are
+ // available to the fabric.
+ wire [Y_WIDTH-1:0] CO_CHAIN;
+ wire [Y_WIDTH-1:0] C = {CO_CHAIN, CINIT};
+
+ // If carry chain is being initialized to a constant, techmap the constant
+ // source. Otherwise techmap the fabric source.
+ generate for (i = 0; i < 1; i = i + 1) begin:slice
+ CARRY0 #(.CYINIT_FABRIC(1)) carry(
+ .CI_INIT(CI),
+ .DI(DI[0]),
+ .S(S[0]),
+ .CO_CHAIN(CO_CHAIN[0]),
+ .CO_FABRIC(CO[0]),
+ .O(Y[0])
+ );
+ end endgenerate
+
+ generate for (i = 1; i < Y_WIDTH-1; i = i + 1) begin:slice
+ if(i % 4 == 0) begin
+ CARRY0 carry (
+ .CI(C[i]),
+ .DI(DI[i]),
+ .S(S[i]),
+ .CO_CHAIN(CO_CHAIN[i]),
+ .CO_FABRIC(CO[i]),
+ .O(Y[i])
+ );
+ end
+ else
+ begin
+ CARRY carry (
+ .CI(C[i]),
+ .DI(DI[i]),
+ .S(S[i]),
+ .CO_CHAIN(CO_CHAIN[i]),
+ .CO_FABRIC(CO[i]),
+ .O(Y[i])
+ );
+ end
+ end endgenerate
+
+ generate for (i = Y_WIDTH-1; i < Y_WIDTH; i = i + 1) begin:slice
+ if(i % 4 == 0) begin
+ CARRY0 top_of_carry (
+ .CI(C[i]),
+ .DI(DI[i]),
+ .S(S[i]),
+ .CO_CHAIN(CO_CHAIN[i]),
+ .O(Y[i])
+ );
+ end
+ else
+ begin
+ CARRY top_of_carry (
+ .CI(C[i]),
+ .DI(DI[i]),
+ .S(S[i]),
+ .CO_CHAIN(CO_CHAIN[i]),
+ .O(Y[i])
+ );
+ end
+ // Turns out CO_FABRIC and O both use [ABCD]MUX, so provide
+ // a non-congested path to output the top of the carry chain.
+ // Registering the output of the CARRY block would solve this, but not
+ // all designs do that.
+ if((i+1) % 4 == 0) begin
+ CARRY0 carry_output (
+ .CI(CO_CHAIN[i]),
+ .DI(0),
+ .S(0),
+ .O(CO[i])
+ );
+ end
+ else
+ begin
+ CARRY carry_output (
+ .CI(CO_CHAIN[i]),
+ .DI(0),
+ .S(0),
+ .O(CO[i])
+ );
+ end
+ end endgenerate
+
+`else
+
+ wire [Y_WIDTH-1:0] S = AA ^ BB;
+ wire [Y_WIDTH-1:0] DI = AA & BB;
+
+ wire [Y_WIDTH-1:0] C = {CO, CI};
+
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
MUXCY muxcy (
.CI(C[i]),
- .DI(G[i]),
+ .DI(DI[i]),
.S(S[i]),
.O(CO[i])
);
@@ -86,6 +352,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
);
end endgenerate
- assign X = P;
+`endif
+
+ assign X = S;
endmodule
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
index 0771be0b9..40789ddbe 100644
--- a/techlibs/xilinx/cells_map.v
+++ b/techlibs/xilinx/cells_map.v
@@ -1,86 +1,156 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
-module \$_DFF_N_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule
-module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule
+// Convert negative-polarity reset to positive-polarity
+(* techmap_celltype = "$_DFF_NN0_" *)
+module _90_dff_nn0_to_np0 (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
+(* techmap_celltype = "$_DFF_PN0_" *)
+module _90_dff_pn0_to_pp0 (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
+(* techmap_celltype = "$_DFF_NN1_" *)
+module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
+(* techmap_celltype = "$_DFF_PN1_" *)
+module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-module \$_DFFE_NP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
-module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
+module \$__SHREG_ (input C, input D, input E, output Q);
+ parameter DEPTH = 0;
+ parameter [DEPTH-1:0] INIT = 0;
+ parameter CLKPOL = 1;
+ parameter ENPOL = 2;
-module \$_DFF_NN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
-module \$_DFF_NP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
-module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
-module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
+ \$__XILINX_SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(DEPTH-1), .E(E), .Q(Q));
+endmodule
-module \$_DFF_NN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
-module \$_DFF_NP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
-module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
-module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
+module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, output SO);
+ parameter DEPTH = 0;
+ parameter [DEPTH-1:0] INIT = 0;
+ parameter CLKPOL = 1;
+ parameter ENPOL = 2;
-`ifndef NO_LUT
-module \$lut (A, Y);
- parameter WIDTH = 0;
- parameter LUT = 0;
+ // shregmap's INIT parameter shifts out LSB first;
+ // however Xilinx expects MSB first
+ function [DEPTH-1:0] brev;
+ input [DEPTH-1:0] din;
+ integer i;
+ begin
+ for (i = 0; i < DEPTH; i=i+1)
+ brev[i] = din[DEPTH-1-i];
+ end
+ endfunction
+ localparam [DEPTH-1:0] INIT_R = brev(INIT);
- input [WIDTH-1:0] A;
- output Y;
+ parameter _TECHMAP_CONSTMSK_L_ = 0;
+ parameter _TECHMAP_CONSTVAL_L_ = 0;
+ wire CE;
generate
- if (WIDTH == 1) begin
- LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]));
- end else
- if (WIDTH == 2) begin
- LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]));
- end else
- if (WIDTH == 3) begin
- LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]));
+ if (ENPOL == 0)
+ assign CE = ~E;
+ else if (ENPOL == 1)
+ assign CE = E;
+ else
+ assign CE = 1'b1;
+ if (DEPTH == 1) begin
+ if (CLKPOL)
+ FDRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0));
+ else
+ FDRE_1 #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0));
end else
- if (WIDTH == 4) begin
- LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]));
+ if (DEPTH <= 16) begin
+ SRL16E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(L[0]), .A1(L[1]), .A2(L[2]), .A3(L[3]), .CE(CE), .CLK(C), .D(D), .Q(Q));
end else
- if (WIDTH == 5) begin
- LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]), .I4(A[4]));
+ if (DEPTH > 17 && DEPTH <= 32) begin
+ SRLC32E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(Q));
end else
- if (WIDTH == 6) begin
- LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ if (DEPTH > 33 && DEPTH <= 64) begin
+ wire T0, T1, T2;
+ SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1));
+ \$__XILINX_SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-32-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L), .E(E), .Q(T2));
+ if (&_TECHMAP_CONSTMSK_L_)
+ assign Q = T2;
+ else
+ MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(L[5]));
end else
- if (WIDTH == 7) begin
- wire T0, T1;
- LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]), .I4(A[4]), .I5(A[5]));
- LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]), .I4(A[4]), .I5(A[5]));
- MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6]));
+ if (DEPTH > 65 && DEPTH <= 96) begin
+ wire T0, T1, T2, T3, T4, T5, T6;
+ SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1));
+ SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3));
+ \$__XILINX_SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .L(L[4:0]), .E(E), .Q(T4));
+ if (&_TECHMAP_CONSTMSK_L_)
+ assign Q = T4;
+ else begin
+ MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(L[5]));
+ MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(L[5]));
+ MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(L[6]));
+ end
end else
- if (WIDTH == 8) begin
- wire T0, T1, T2, T3, T4, T5;
- LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]), .I4(A[4]), .I5(A[5]));
- LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]), .I4(A[4]), .I5(A[5]));
- LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]), .I4(A[4]), .I5(A[5]));
- LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3),
- .I0(A[0]), .I1(A[1]), .I2(A[2]),
- .I3(A[3]), .I4(A[4]), .I5(A[5]));
- MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6]));
- MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6]));
- MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7]));
- end else begin
- wire _TECHMAP_FAIL_ = 1;
+ if (DEPTH > 97 && DEPTH < 128) begin
+ wire T0, T1, T2, T3, T4, T5, T6, T7, T8;
+ SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1));
+ SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3));
+ SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5));
+ \$__XILINX_SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .L(L[4:0]), .E(E), .Q(T6));
+ if (&_TECHMAP_CONSTMSK_L_)
+ assign Q = T6;
+ else begin
+ MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5]));
+ MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5]));
+ MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6]));
+ end
+ end
+ else if (DEPTH == 128) begin
+ wire T0, T1, T2, T3, T4, T5, T6;
+ SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1));
+ SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3));
+ SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5));
+ SRLC32E #(.INIT(INIT_R[128-1:96]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_3 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T5), .Q(T6), .Q31(SO));
+ if (&_TECHMAP_CONSTMSK_L_)
+ assign Q = T6;
+ else begin
+ wire T7, T8;
+ MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5]));
+ MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5]));
+ MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6]));
+ end
+ end
+ else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin
+ // Handle cases where fixed-length depth is
+ // just 1 over a convenient value
+ \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q));
+ end
+ else begin
+ localparam lower_clog2 = $clog2((DEPTH+1)/2);
+ localparam lower_depth = 2 ** lower_clog2;
+ wire T0, T1, T2, T3;
+ if (&_TECHMAP_CONSTMSK_L_) begin
+ \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(lower_depth-1), .E(E), .Q(T0));
+ \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(DEPTH-lower_depth-1), .E(E), .Q(Q), .SO(T3));
+ end
+ else begin
+ \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1));
+ \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2), .SO(T3));
+ assign Q = L[lower_clog2] ? T2 : T0;
+ end
+ if (DEPTH == 2 * lower_depth)
+ assign SO = T3;
end
endgenerate
endmodule
+
+`ifndef SRL_ONLY
`endif
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index eba17ac9c..3a4540b83 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -1,3 +1,21 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
// See Xilinx UG953 and UG474 for a description of the cell types below.
// http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf
@@ -12,10 +30,15 @@ module GND(output G);
endmodule
module IBUF(output O, input I);
+ parameter IOSTANDARD = "default";
+ parameter IBUF_LOW_PWR = 0;
assign O = I;
endmodule
module OBUF(output O, input I);
+ parameter IOSTANDARD = "default";
+ parameter DRIVE = 12;
+ parameter SLEW = "SLOW";
assign O = I;
endmodule
@@ -23,6 +46,42 @@ module BUFG(output O, input I);
assign O = I;
endmodule
+module BUFGCTRL(
+ output O,
+ input I0, input I1,
+ input S0, input S1,
+ input CE0, input CE1,
+ input IGNORE0, input IGNORE1);
+
+parameter [0:0] INIT_OUT = 1'b0;
+parameter PRESELECT_I0 = "FALSE";
+parameter PRESELECT_I1 = "FALSE";
+parameter [0:0] IS_CE0_INVERTED = 1'b0;
+parameter [0:0] IS_CE1_INVERTED = 1'b0;
+parameter [0:0] IS_S0_INVERTED = 1'b0;
+parameter [0:0] IS_S1_INVERTED = 1'b0;
+parameter [0:0] IS_IGNORE0_INVERTED = 1'b0;
+parameter [0:0] IS_IGNORE1_INVERTED = 1'b0;
+
+wire I0_internal = ((CE0 ^ IS_CE0_INVERTED) ? I0 : INIT_OUT);
+wire I1_internal = ((CE1 ^ IS_CE1_INVERTED) ? I1 : INIT_OUT);
+wire S0_true = (S0 ^ IS_S0_INVERTED);
+wire S1_true = (S1 ^ IS_S1_INVERTED);
+
+assign O = S0_true ? I0_internal : (S1_true ? I1_internal : INIT_OUT);
+
+endmodule
+
+module BUFHCE(output O, input I, input CE);
+
+parameter [0:0] INIT_OUT = 1'b0;
+parameter CE_TYPE = "SYNC";
+parameter [0:0] IS_CE_INVERTED = 1'b0;
+
+assign O = ((CE ^ IS_CE_INVERTED) ? I : INIT_OUT);
+
+endmodule
+
// module OBUFT(output O, input I, T);
// assign O = T ? 1'bz : I;
// endmodule
@@ -80,6 +139,22 @@ module LUT6(output O, input I0, I1, I2, I3, I4, I5);
assign O = I0 ? s1[1] : s1[0];
endmodule
+module LUT6_2(output O6, output O5, input I0, I1, I2, I3, I4, I5);
+ parameter [63:0] INIT = 0;
+ wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0];
+ wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0];
+ wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
+ wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
+ wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
+ assign O6 = I0 ? s1[1] : s1[0];
+
+ wire [15: 0] s5_4 = I4 ? INIT[31:16] : INIT[15: 0];
+ wire [ 7: 0] s5_3 = I3 ? s5_4[15: 8] : s5_4[ 7: 0];
+ wire [ 3: 0] s5_2 = I2 ? s5_3[ 7: 4] : s5_3[ 3: 0];
+ wire [ 1: 0] s5_1 = I1 ? s5_2[ 3: 2] : s5_2[ 1: 0];
+ assign O5 = I0 ? s5_1[1] : s5_1[0];
+endmodule
+
module MUXCY(output O, input CI, DI, S);
assign O = S ? CI : DI;
endmodule
@@ -104,6 +179,29 @@ module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
assign CO[3] = S[3] ? CO[2] : DI[3];
endmodule
+`ifdef _EXPLICIT_CARRY
+
+module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S);
+ parameter CYINIT_FABRIC = 0;
+ wire CI_COMBINE;
+ if(CYINIT_FABRIC) begin
+ assign CI_COMBINE = CI_INIT;
+ end else begin
+ assign CI_COMBINE = CI;
+ end
+ assign CO_CHAIN = S ? CI_COMBINE : DI;
+ assign CO_FABRIC = S ? CI_COMBINE : DI;
+ assign O = S ^ CI_COMBINE;
+endmodule
+
+module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S);
+ assign CO_CHAIN = S ? CI : DI;
+ assign CO_FABRIC = S ? CI : DI;
+ assign O = S ^ CI;
+endmodule
+
+`endif
+
module FDRE (output reg Q, input C, CE, D, R);
parameter [0:0] INIT = 1'b0;
parameter [0:0] IS_C_INVERTED = 1'b0;
@@ -156,6 +254,30 @@ module FDPE (output reg Q, input C, CE, D, PRE);
endcase endgenerate
endmodule
+module FDRE_1 (output reg Q, input C, CE, D, R);
+ parameter [0:0] INIT = 1'b0;
+ initial Q <= INIT;
+ always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
+endmodule
+
+module FDSE_1 (output reg Q, input C, CE, D, S);
+ parameter [0:0] INIT = 1'b1;
+ initial Q <= INIT;
+ always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
+endmodule
+
+module FDCE_1 (output reg Q, input C, CE, D, CLR);
+ parameter [0:0] INIT = 1'b0;
+ initial Q <= INIT;
+ always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
+endmodule
+
+module FDPE_1 (output reg Q, input C, CE, D, PRE);
+ parameter [0:0] INIT = 1'b1;
+ initial Q <= INIT;
+ always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
+endmodule
+
module RAM64X1D (
output DPO, SPO,
input D, WCLK, WE,
@@ -186,3 +308,42 @@ module RAM128X1D (
wire clk = WCLK ^ IS_WCLK_INVERTED;
always @(posedge clk) if (WE) mem[A] <= D;
endmodule
+
+module SRL16E (
+ output Q,
+ input A0, A1, A2, A3, CE, CLK, D
+);
+ parameter [15:0] INIT = 16'h0000;
+ parameter [0:0] IS_CLK_INVERTED = 1'b0;
+
+ reg [15:0] r = INIT;
+ assign Q = r[{A3,A2,A1,A0}];
+ generate
+ if (IS_CLK_INVERTED) begin
+ always @(negedge CLK) if (CE) r <= { r[14:0], D };
+ end
+ else
+ always @(posedge CLK) if (CE) r <= { r[14:0], D };
+ endgenerate
+endmodule
+
+module SRLC32E (
+ output Q,
+ output Q31,
+ input [4:0] A,
+ input CE, CLK, D
+);
+ parameter [31:0] INIT = 32'h00000000;
+ parameter [0:0] IS_CLK_INVERTED = 1'b0;
+
+ reg [31:0] r = INIT;
+ assign Q31 = r[31];
+ assign Q = r[A];
+ generate
+ if (IS_CLK_INVERTED) begin
+ always @(negedge CLK) if (CE) r <= { r[30:0], D };
+ end
+ else
+ always @(posedge CLK) if (CE) r <= { r[30:0], D };
+ endgenerate
+endmodule
diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh
index 0480410f5..8e39b440d 100644
--- a/techlibs/xilinx/cells_xtra.sh
+++ b/techlibs/xilinx/cells_xtra.sh
@@ -7,6 +7,7 @@ function xtract_cell_decl()
{
for dir in $libdir/xeclib $libdir/retarget; do
[ -f $dir/$1.v ] || continue
+ [ -z "$2" ] || echo $2
egrep '^\s*((end)?module|parameter|input|inout|output|(end)?function|(end)?task)' $dir/$1.v |
sed -re '/UNPLACED/ d; /^\s*function/,/endfunction/ d; /^\s*task/,/endtask/ d;
s,//.*,,; s/#?\(.*/(...);/; s/^(input|output|parameter)/ \1/;
@@ -27,20 +28,20 @@ function xtract_cell_decl()
# xtract_cell_decl BUFG
xtract_cell_decl BUFGCE
xtract_cell_decl BUFGCE_1
- xtract_cell_decl BUFGCTRL
+ #xtract_cell_decl BUFGCTRL
xtract_cell_decl BUFGMUX
xtract_cell_decl BUFGMUX_1
xtract_cell_decl BUFGMUX_CTRL
xtract_cell_decl BUFH
- xtract_cell_decl BUFHCE
+ #xtract_cell_decl BUFHCE
xtract_cell_decl BUFIO
xtract_cell_decl BUFMR
xtract_cell_decl BUFMRCE
xtract_cell_decl BUFR
- xtract_cell_decl CAPTUREE2
+ xtract_cell_decl CAPTUREE2 "(* keep *)"
# xtract_cell_decl CARRY4
xtract_cell_decl CFGLUT5
- xtract_cell_decl DCIRESET
+ xtract_cell_decl DCIRESET "(* keep *)"
xtract_cell_decl DNA_PORT
xtract_cell_decl DSP48E1
xtract_cell_decl EFUSE_USR
@@ -67,10 +68,10 @@ function xtract_cell_decl()
xtract_cell_decl IBUFDS_GTE2
xtract_cell_decl IBUFDS_IBUFDISABLE
xtract_cell_decl IBUFDS_INTERMDISABLE
- xtract_cell_decl ICAPE2
+ xtract_cell_decl ICAPE2 "(* keep *)"
xtract_cell_decl IDDR
xtract_cell_decl IDDR_2CLK
- xtract_cell_decl IDELAYCTRL
+ xtract_cell_decl IDELAYCTRL "(* keep *)"
xtract_cell_decl IDELAYE2
xtract_cell_decl IN_FIFO
xtract_cell_decl IOBUF
@@ -91,7 +92,7 @@ function xtract_cell_decl()
# xtract_cell_decl LUT4
# xtract_cell_decl LUT5
# xtract_cell_decl LUT6
- xtract_cell_decl LUT6_2
+ #xtract_cell_decl LUT6_2
xtract_cell_decl MMCME2_ADV
xtract_cell_decl MMCME2_BASE
# xtract_cell_decl MUXF7
@@ -112,10 +113,10 @@ function xtract_cell_decl()
xtract_cell_decl PHY_CONTROL
xtract_cell_decl PLLE2_ADV
xtract_cell_decl PLLE2_BASE
- xtract_cell_decl PS7
+ xtract_cell_decl PS7 "(* keep *)"
xtract_cell_decl PULLDOWN
xtract_cell_decl PULLUP
- # xtract_cell_decl RAM128X1D
+ xtract_cell_decl RAM128X1D
xtract_cell_decl RAM128X1S
xtract_cell_decl RAM256X1S
xtract_cell_decl RAM32M
@@ -124,7 +125,7 @@ function xtract_cell_decl()
xtract_cell_decl RAM32X1S_1
xtract_cell_decl RAM32X2S
xtract_cell_decl RAM64M
- # xtract_cell_decl RAM64X1D
+ xtract_cell_decl RAM64X1D
xtract_cell_decl RAM64X1S
xtract_cell_decl RAM64X1S_1
xtract_cell_decl RAM64X2S
@@ -134,9 +135,9 @@ function xtract_cell_decl()
xtract_cell_decl ROM256X1
xtract_cell_decl ROM32X1
xtract_cell_decl ROM64X1
- xtract_cell_decl SRL16E
- xtract_cell_decl SRLC32E
- xtract_cell_decl STARTUPE2
+ #xtract_cell_decl SRL16E
+ #xtract_cell_decl SRLC32E
+ xtract_cell_decl STARTUPE2 "(* keep *)"
xtract_cell_decl USR_ACCESSE2
xtract_cell_decl XADC
} > cells_xtra.new
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 8d8b91ddc..fbcc74682 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -30,29 +30,6 @@ module BUFGCE_1 (...);
input CE, I;
endmodule
-module BUFGCTRL (...);
- output O;
- input CE0;
- input CE1;
- input I0;
- input I1;
- input IGNORE0;
- input IGNORE1;
- input S0;
- input S1;
- parameter integer INIT_OUT = 0;
- parameter PRESELECT_I0 = "FALSE";
- parameter PRESELECT_I1 = "FALSE";
- parameter [0:0] IS_CE0_INVERTED = 1'b0;
- parameter [0:0] IS_CE1_INVERTED = 1'b0;
- parameter [0:0] IS_I0_INVERTED = 1'b0;
- parameter [0:0] IS_I1_INVERTED = 1'b0;
- parameter [0:0] IS_IGNORE0_INVERTED = 1'b0;
- parameter [0:0] IS_IGNORE1_INVERTED = 1'b0;
- parameter [0:0] IS_S0_INVERTED = 1'b0;
- parameter [0:0] IS_S1_INVERTED = 1'b0;
-endmodule
-
module BUFGMUX (...);
parameter CLK_SEL_TYPE = "SYNC";
output O;
@@ -77,15 +54,6 @@ module BUFH (...);
input I;
endmodule
-module BUFHCE (...);
- parameter CE_TYPE = "SYNC";
- parameter integer INIT_OUT = 0;
- parameter [0:0] IS_CE_INVERTED = 1'b0;
- output O;
- input CE;
- input I;
-endmodule
-
module BUFIO (...);
output O;
input I;
@@ -114,6 +82,7 @@ module BUFR (...);
parameter SIM_DEVICE = "7SERIES";
endmodule
+(* keep *)
module CAPTUREE2 (...);
parameter ONESHOT = "TRUE";
input CAP;
@@ -130,6 +99,7 @@ module CFGLUT5 (...);
input CDI, CE, CLK;
endmodule
+(* keep *)
module DCIRESET (...);
output LOCKED;
input RST;
@@ -2102,6 +2072,7 @@ module IBUFDS_INTERMDISABLE (...);
input INTERMDISABLE;
endmodule
+(* keep *)
module ICAPE2 (...);
parameter [31:0] DEVICE_ID = 32'h04244093;
parameter ICAP_WIDTH = "X32";
@@ -2149,6 +2120,7 @@ module IDDR_2CLK (...);
input S;
endmodule
+(* keep *)
module IDELAYCTRL (...);
parameter SIM_DEVICE = "7SERIES";
output RDY;
@@ -2416,12 +2388,6 @@ module LDPE (...);
input D, G, GE, PRE;
endmodule
-module LUT6_2 (...);
- parameter [63:0] INIT = 64'h0000000000000000;
- input I0, I1, I2, I3, I4, I5;
- output O5, O6;
-endmodule
-
module MMCME2_ADV (...);
parameter BANDWIDTH = "OPTIMIZED";
parameter real CLKFBOUT_MULT_F = 5.000;
@@ -3057,6 +3023,7 @@ module PLLE2_BASE (...);
input RST;
endmodule
+(* keep *)
module PS7 (...);
output DMA0DAVALID;
output DMA0DRREADY;
@@ -3688,6 +3655,17 @@ module PULLUP (...);
output O;
endmodule
+module RAM128X1D (...);
+ parameter [127:0] INIT = 128'h00000000000000000000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ output DPO, SPO;
+ input [6:0] A;
+ input [6:0] DPRA;
+ input D;
+ input WCLK;
+ input WE;
+endmodule
+
module RAM128X1S (...);
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
@@ -3778,6 +3756,13 @@ module RAM64M (...);
input WE;
endmodule
+module RAM64X1D (...);
+ parameter [63:0] INIT = 64'h0000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ output DPO, SPO;
+ input A0, A1, A2, A3, A4, A5, D, DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5, WCLK, WE;
+endmodule
+
module RAM64X1S (...);
parameter [63:0] INIT = 64'h0000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
@@ -3824,22 +3809,7 @@ module ROM64X1 (...);
input A0, A1, A2, A3, A4, A5;
endmodule
-module SRL16E (...);
- parameter [15:0] INIT = 16'h0000;
- parameter [0:0] IS_CLK_INVERTED = 1'b0;
- output Q;
- input A0, A1, A2, A3, CE, CLK, D;
-endmodule
-
-module SRLC32E (...);
- parameter [31:0] INIT = 32'h00000000;
- parameter [0:0] IS_CLK_INVERTED = 1'b0;
- output Q;
- output Q31;
- input [4:0] A;
- input CE, CLK, D;
-endmodule
-
+(* keep *)
module STARTUPE2 (...);
parameter PROG_USR = "FALSE";
parameter real SIM_CCLK_FREQ = 0.0;
diff --git a/techlibs/xilinx/drams.txt b/techlibs/xilinx/drams.txt
index e6635d0e2..91632bcee 100644
--- a/techlibs/xilinx/drams.txt
+++ b/techlibs/xilinx/drams.txt
@@ -26,11 +26,15 @@ bram $__XILINX_RAM128X1D
endbram
match $__XILINX_RAM64X1D
+ min bits 5
+ min wports 1
make_outreg
or_next_if_better
endmatch
match $__XILINX_RAM128X1D
+ min bits 9
+ min wports 1
make_outreg
endmatch
diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v
new file mode 100644
index 000000000..13beaa6ae
--- /dev/null
+++ b/techlibs/xilinx/ff_map.v
@@ -0,0 +1,42 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+// ============================================================================
+// FF mapping
+
+`ifndef _NO_FFS
+
+module \$_DFF_N_ (input D, C, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule
+module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule
+
+module \$_DFFE_NP_ (input D, C, E, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
+module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
+
+module \$_DFF_NN0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule
+module \$_DFF_NP0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule
+module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule
+module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule
+
+module \$_DFF_NN1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule
+module \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule
+module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule
+module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule
+
+`endif
+
diff --git a/techlibs/xilinx/lut2lut.v b/techlibs/xilinx/lut2lut.v
deleted file mode 100644
index 061ad2041..000000000
--- a/techlibs/xilinx/lut2lut.v
+++ /dev/null
@@ -1,65 +0,0 @@
-module LUT1(output O, input I0);
- parameter [1:0] INIT = 0;
- \$lut #(
- .WIDTH(1),
- .LUT(INIT)
- ) _TECHMAP_REPLACE_ (
- .A(I0),
- .Y(O)
- );
-endmodule
-
-module LUT2(output O, input I0, I1);
- parameter [3:0] INIT = 0;
- \$lut #(
- .WIDTH(2),
- .LUT(INIT)
- ) _TECHMAP_REPLACE_ (
- .A({I1, I0}),
- .Y(O)
- );
-endmodule
-
-module LUT3(output O, input I0, I1, I2);
- parameter [7:0] INIT = 0;
- \$lut #(
- .WIDTH(3),
- .LUT(INIT)
- ) _TECHMAP_REPLACE_ (
- .A({I2, I1, I0}),
- .Y(O)
- );
-endmodule
-
-module LUT4(output O, input I0, I1, I2, I3);
- parameter [15:0] INIT = 0;
- \$lut #(
- .WIDTH(4),
- .LUT(INIT)
- ) _TECHMAP_REPLACE_ (
- .A({I3, I2, I1, I0}),
- .Y(O)
- );
-endmodule
-
-module LUT5(output O, input I0, I1, I2, I3, I4);
- parameter [31:0] INIT = 0;
- \$lut #(
- .WIDTH(5),
- .LUT(INIT)
- ) _TECHMAP_REPLACE_ (
- .A({I4, I3, I2, I1, I0}),
- .Y(O)
- );
-endmodule
-
-module LUT6(output O, input I0, I1, I2, I3, I4, I5);
- parameter [63:0] INIT = 0;
- \$lut #(
- .WIDTH(6),
- .LUT(INIT)
- ) _TECHMAP_REPLACE_ (
- .A({I5, I4, I3, I2, I1, I0}),
- .Y(O)
- );
-endmodule
diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v
new file mode 100644
index 000000000..d07c59dee
--- /dev/null
+++ b/techlibs/xilinx/lut_map.v
@@ -0,0 +1,94 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+// ============================================================================
+// LUT mapping
+
+`ifndef _NO_LUTS
+
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]));
+ end else
+ if (WIDTH == 2) begin
+ LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]), .I1(A[1]));
+ end else
+ if (WIDTH == 3) begin
+ LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]));
+ end else
+ if (WIDTH == 4) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]));
+ end else
+ if (WIDTH == 5) begin
+ LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]));
+ end else
+ if (WIDTH == 6) begin
+ LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ end else
+ if (WIDTH == 7) begin
+ wire T0, T1;
+ LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6]));
+ end else
+ if (WIDTH == 8) begin
+ wire T0, T1, T2, T3, T4, T5;
+ LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]),
+ .I3(A[3]), .I4(A[4]), .I5(A[5]));
+ MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6]));
+ MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6]));
+ MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7]));
+ end else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
+endmodule
+
+`endif
+
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index 6c11d885d..a293081f1 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -25,18 +25,9 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-bool check_label(bool &active, std::string run_from, std::string run_to, std::string label)
+struct SynthXilinxPass : public ScriptPass
{
- if (label == run_from)
- active = true;
- if (label == run_to)
- active = false;
- return active;
-}
-
-struct SynthXilinxPass : public Pass
-{
- SynthXilinxPass() : Pass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
+ SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
void help() YS_OVERRIDE
{
@@ -51,6 +42,10 @@ struct SynthXilinxPass : public Pass
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
+ log(" -arch {xcup|xcu|xc7|xc6s}\n");
+ log(" run synthesis for the specified Xilinx architecture\n");
+ log(" default: xc7\n");
+ log("\n");
log(" -edif <file>\n");
log(" write the design to the specified edif file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
@@ -63,6 +58,15 @@ struct SynthXilinxPass : public Pass
log(" generate an output netlist (and BLIF file) suitable for VPR\n");
log(" (this feature is experimental and incomplete)\n");
log("\n");
+ log(" -nobram\n");
+ log(" disable inference of block rams\n");
+ log("\n");
+ log(" -nodram\n");
+ log(" disable inference of distributed rams\n");
+ log("\n");
+ log(" -nosrl\n");
+ log(" disable inference of shift registers\n");
+ log("\n");
log(" -run <from_label>:<to_label>\n");
log(" only run the commands between the labels (see below). an empty\n");
log(" from label is synonymous to 'begin', and empty to label is\n");
@@ -76,67 +80,31 @@ struct SynthXilinxPass : public Pass
log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
- log("\n");
- log(" begin:\n");
- log(" read_verilog -lib +/xilinx/cells_sim.v\n");
- log(" read_verilog -lib +/xilinx/cells_xtra.v\n");
- log(" read_verilog -lib +/xilinx/brams_bb.v\n");
- log(" hierarchy -check -top <top>\n");
- log("\n");
- log(" flatten: (only if -flatten)\n");
- log(" proc\n");
- log(" flatten\n");
- log("\n");
- log(" coarse:\n");
- log(" synth -run coarse\n");
- log("\n");
- log(" bram:\n");
- log(" memory_bram -rules +/xilinx/brams.txt\n");
- log(" techmap -map +/xilinx/brams_map.v\n");
- log("\n");
- log(" dram:\n");
- log(" memory_bram -rules +/xilinx/drams.txt\n");
- log(" techmap -map +/xilinx/drams_map.v\n");
- log("\n");
- log(" fine:\n");
- log(" opt -fast -full\n");
- log(" memory_map\n");
- log(" dffsr2dff\n");
- log(" dff2dffe\n");
- log(" opt -full\n");
- log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n");
- log(" opt -fast\n");
- log("\n");
- log(" map_luts:\n");
- log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n");
- log(" clean\n");
- log("\n");
- log(" map_cells:\n");
- log(" techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)\n");
- log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT\n");
- log(" clean\n");
- log("\n");
- log(" check:\n");
- log(" hierarchy -check\n");
- log(" stat\n");
- log(" check -noinit\n");
- log("\n");
- log(" edif: (only if -edif)\n");
- log(" write_edif <file-name>\n");
- log("\n");
- log(" blif: (only if -blif)\n");
- log(" write_blif <file-name>\n");
+ help_script();
log("\n");
}
+
+ std::string top_opt, edif_file, blif_file, arch;
+ bool flatten, retime, vpr, nobram, nodram, nosrl;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ edif_file.clear();
+ blif_file.clear();
+ flatten = false;
+ retime = false;
+ vpr = false;
+ nobram = false;
+ nodram = false;
+ nosrl = false;
+ arch = "xc7";
+ }
+
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- std::string top_opt = "-auto-top";
- std::string edif_file;
- std::string blif_file;
std::string run_from, run_to;
- bool flatten = false;
- bool retime = false;
- bool vpr = false;
+ clear_flags();
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -145,6 +113,10 @@ struct SynthXilinxPass : public Pass
top_opt = "-top " + args[++argidx];
continue;
}
+ if (args[argidx] == "-arch" && argidx+1 < args.size()) {
+ arch = args[++argidx];
+ continue;
+ }
if (args[argidx] == "-edif" && argidx+1 < args.size()) {
edif_file = args[++argidx];
continue;
@@ -173,94 +145,142 @@ struct SynthXilinxPass : public Pass
vpr = true;
continue;
}
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
+ if (args[argidx] == "-nodram") {
+ nodram = true;
+ continue;
+ }
+ if (args[argidx] == "-nosrl") {
+ nosrl = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
+ if (arch != "xcup" && arch != "xcu" && arch != "xc7" && arch != "xc6s")
+ log_cmd_error("Invalid Xilinx -arch setting: %s\n", arch.c_str());
+
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
- bool active = run_from.empty();
-
log_header(design, "Executing SYNTH_XILINX pass.\n");
log_push();
- if (check_label(active, run_from, run_to, "begin"))
- {
- Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v");
- Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v");
- Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v");
- Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
- }
+ run_script(design, run_from, run_to);
- if (flatten && check_label(active, run_from, run_to, "flatten"))
- {
- Pass::call(design, "proc");
- Pass::call(design, "flatten");
+ log_pop();
+ }
+
+ void script() YS_OVERRIDE
+ {
+ if (check_label("begin")) {
+ if (vpr)
+ run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
+ else
+ run("read_verilog -lib +/xilinx/cells_sim.v");
+
+ run("read_verilog -lib +/xilinx/cells_xtra.v");
+
+ if (!nobram || help_mode)
+ run("read_verilog -lib +/xilinx/brams_bb.v", "(skip if '-nobram')");
+
+ run(stringf("hierarchy -check %s", top_opt.c_str()));
}
- if (check_label(active, run_from, run_to, "coarse"))
- {
- Pass::call(design, "synth -run coarse");
+ if (check_label("flatten", "(with '-flatten' only)")) {
+ if (flatten || help_mode) {
+ run("proc");
+ run("flatten");
+ }
}
- if (check_label(active, run_from, run_to, "bram"))
- {
- Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
- Pass::call(design, "techmap -map +/xilinx/brams_map.v");
+ if (check_label("coarse")) {
+ run("synth -run coarse");
}
- if (check_label(active, run_from, run_to, "dram"))
- {
- Pass::call(design, "memory_bram -rules +/xilinx/drams.txt");
- Pass::call(design, "techmap -map +/xilinx/drams_map.v");
+ if (check_label("bram", "(skip if '-nobram')")) {
+ if (!nobram || help_mode) {
+ run("memory_bram -rules +/xilinx/brams.txt");
+ run("techmap -map +/xilinx/brams_map.v");
+ }
}
- if (check_label(active, run_from, run_to, "fine"))
- {
- Pass::call(design, "opt -fast -full");
- Pass::call(design, "memory_map");
- Pass::call(design, "dffsr2dff");
- Pass::call(design, "dff2dffe");
- Pass::call(design, "opt -full");
- Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v");
- Pass::call(design, "opt -fast");
+ if (check_label("dram", "(skip if '-nodram')")) {
+ if (!nodram || help_mode) {
+ run("memory_bram -rules +/xilinx/drams.txt");
+ run("techmap -map +/xilinx/drams_map.v");
+ }
}
- if (check_label(active, run_from, run_to, "map_luts"))
- {
- Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
- Pass::call(design, "clean");
+ if (check_label("fine")) {
+ // shregmap -tech xilinx can cope with $shiftx and $mux
+ // cells for identifiying variable-length shift registers,
+ // so attempt to convert $pmux-es to the former
+ if (!nosrl || help_mode)
+ run("pmux2shiftx", "(skip if '-nosrl')");
+
+ run("opt -fast -full");
+ run("memory_map");
+ run("dffsr2dff");
+ run("dff2dffe");
+ run("opt -full");
+
+ if (!nosrl || help_mode) {
+ // shregmap operates on bit-level flops, not word-level,
+ // so break those down here
+ run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')");
+ // shregmap with '-tech xilinx' infers variable length shift regs
+ run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')");
+ }
+
+ if (!vpr || help_mode)
+ run("techmap -map +/techmap.v -map +/xilinx/arith_map.v");
+ else
+ run("techmap -map +/techmap.v +/xilinx/arith_map.v -D _EXPLICIT_CARRY");
+
+ run("opt -fast");
}
- if (check_label(active, run_from, run_to, "map_cells"))
- {
- Pass::call(design, "techmap -map +/xilinx/cells_map.v");
- if (vpr)
- Pass::call(design, "techmap -map +/xilinx/lut2lut.v");
- Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT");
- Pass::call(design, "clean");
+ if (check_label("map_cells")) {
+ run("techmap -map +/techmap.v -map +/xilinx/cells_map.v");
+ run("clean");
}
- if (check_label(active, run_from, run_to, "check"))
- {
- Pass::call(design, "hierarchy -check");
- Pass::call(design, "stat");
- Pass::call(design, "check -noinit");
+ if (check_label("map_luts")) {
+ if (help_mode)
+ run("abc -luts 2:2,3,6:5,10,20 [-dff]");
+ else
+ run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
+ run("clean");
+ // This shregmap call infers fixed length shift registers after abc
+ // has performed any necessary retiming
+ if (!nosrl || help_mode)
+ run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')");
+ run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
+ run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
+ "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
+ run("clean");
}
- if (check_label(active, run_from, run_to, "edif"))
- {
- if (!edif_file.empty())
- Pass::call(design, stringf("write_edif %s", edif_file.c_str()));
+ if (check_label("check")) {
+ run("hierarchy -check");
+ run("stat -tech xilinx");
+ run("check -noinit");
}
- if (check_label(active, run_from, run_to, "blif"))
- {
- if (!blif_file.empty())
- Pass::call(design, stringf("write_blif %s", edif_file.c_str()));
+
+ if (check_label("edif")) {
+ if (!edif_file.empty() || help_mode)
+ run(stringf("write_edif -pvector bra %s", edif_file.c_str()));
}
- log_pop();
+ if (check_label("blif")) {
+ if (!blif_file.empty() || help_mode)
+ run(stringf("write_blif %s", edif_file.c_str()));
+ }
}
} SynthXilinxPass;