aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs')
-rw-r--r--techlibs/anlogic/Makefile.inc2
-rw-r--r--techlibs/anlogic/anlogic_determine_init.cc72
-rw-r--r--techlibs/anlogic/anlogic_eqn.cc4
-rw-r--r--techlibs/anlogic/anlogic_fixcarry.cc130
-rw-r--r--techlibs/anlogic/arith_map.v52
-rw-r--r--techlibs/anlogic/synth_anlogic.cc7
-rw-r--r--techlibs/common/cmp2lut.v2
-rw-r--r--techlibs/common/simcells.v19
-rw-r--r--techlibs/common/simlib.v44
-rw-r--r--techlibs/common/synth.cc21
-rw-r--r--techlibs/coolrunner2/coolrunner2_sop.cc22
-rw-r--r--techlibs/ecp5/Makefile.inc8
-rw-r--r--techlibs/ecp5/abc_5g.box43
-rw-r--r--techlibs/ecp5/abc_5g.lut25
-rw-r--r--techlibs/ecp5/abc_5g_nowide.lut12
-rw-r--r--techlibs/ecp5/arith_map.v9
-rw-r--r--techlibs/ecp5/cells_map.v171
-rw-r--r--techlibs/ecp5/cells_sim.v482
-rw-r--r--techlibs/ecp5/lutram.txt (renamed from techlibs/ecp5/dram.txt)0
-rw-r--r--techlibs/ecp5/lutrams_map.v (renamed from techlibs/ecp5/drams_map.v)0
-rw-r--r--techlibs/ecp5/synth_ecp5.cc66
-rw-r--r--techlibs/efinix/Makefile.inc10
-rw-r--r--techlibs/efinix/arith_map.v79
-rw-r--r--techlibs/efinix/bram.txt32
-rw-r--r--techlibs/efinix/brams_map.v65
-rw-r--r--techlibs/efinix/cells_map.v45
-rw-r--r--techlibs/efinix/cells_sim.v107
-rw-r--r--techlibs/efinix/efinix_fixcarry.cc122
-rw-r--r--techlibs/efinix/efinix_gbuf.cc119
-rw-r--r--techlibs/efinix/synth_efinix.cc219
-rw-r--r--techlibs/gowin/determine_init.cc4
-rw-r--r--techlibs/ice40/Makefile.inc7
-rw-r--r--techlibs/ice40/abc_hx.box13
-rw-r--r--techlibs/ice40/abc_hx.lut6
-rw-r--r--techlibs/ice40/abc_lp.box13
-rw-r--r--techlibs/ice40/abc_lp.lut6
-rw-r--r--techlibs/ice40/abc_u.box13
-rw-r--r--techlibs/ice40/abc_u.lut6
-rw-r--r--techlibs/ice40/arith_map.v24
-rw-r--r--techlibs/ice40/cells_map.v39
-rw-r--r--techlibs/ice40/cells_sim.v49
-rw-r--r--techlibs/ice40/ice40_braminit.cc6
-rw-r--r--techlibs/ice40/ice40_opt.cc45
-rw-r--r--techlibs/ice40/ice40_unlut.cc106
-rw-r--r--techlibs/ice40/synth_ice40.cc71
-rw-r--r--techlibs/ice40/tests/test_arith.ys9
-rw-r--r--techlibs/ice40/tests/test_dsp_model.sh9
-rw-r--r--techlibs/ice40/tests/test_dsp_model.v225
-rw-r--r--techlibs/intel/Makefile.inc24
-rw-r--r--techlibs/intel/common/brams_m9k.txt (renamed from techlibs/intel/common/brams.txt)0
-rw-r--r--techlibs/intel/common/brams_map_m9k.v (renamed from techlibs/intel/common/brams_map.v)0
-rw-r--r--techlibs/intel/synth_intel.cc78
-rw-r--r--techlibs/xilinx/Makefile.inc24
-rw-r--r--techlibs/xilinx/abc_xc7.box58
-rw-r--r--techlibs/xilinx/abc_xc7.lut15
-rw-r--r--techlibs/xilinx/abc_xc7_nowide.lut10
-rw-r--r--techlibs/xilinx/arith_map.v4
-rw-r--r--techlibs/xilinx/brams_init.py16
-rw-r--r--techlibs/xilinx/cells_map.v295
-rw-r--r--techlibs/xilinx/cells_sim.v61
-rw-r--r--techlibs/xilinx/cells_xtra.sh6
-rw-r--r--techlibs/xilinx/cells_xtra.v25
-rw-r--r--techlibs/xilinx/ff_map.v8
-rw-r--r--techlibs/xilinx/lut_map.v97
-rw-r--r--techlibs/xilinx/lutrams.txt (renamed from techlibs/xilinx/drams.txt)20
-rw-r--r--techlibs/xilinx/lutrams_map.v (renamed from techlibs/xilinx/drams_map.v)34
-rw-r--r--techlibs/xilinx/mux_map.v71
-rw-r--r--techlibs/xilinx/synth_xilinx.cc259
-rw-r--r--techlibs/xilinx/xc6s_brams.txt84
-rw-r--r--techlibs/xilinx/xc6s_brams_bb.v211
-rw-r--r--techlibs/xilinx/xc6s_brams_map.v255
-rw-r--r--techlibs/xilinx/xc7_brams.txt (renamed from techlibs/xilinx/brams.txt)0
-rw-r--r--techlibs/xilinx/xc7_brams_bb.v (renamed from techlibs/xilinx/brams_bb.v)0
-rw-r--r--techlibs/xilinx/xc7_brams_map.v (renamed from techlibs/xilinx/brams_map.v)0
74 files changed, 3529 insertions, 766 deletions
diff --git a/techlibs/anlogic/Makefile.inc b/techlibs/anlogic/Makefile.inc
index 67cf9cf10..9426b5ca5 100644
--- a/techlibs/anlogic/Makefile.inc
+++ b/techlibs/anlogic/Makefile.inc
@@ -1,7 +1,7 @@
OBJS += techlibs/anlogic/synth_anlogic.o
OBJS += techlibs/anlogic/anlogic_eqn.o
-OBJS += techlibs/anlogic/anlogic_determine_init.o
+OBJS += techlibs/anlogic/anlogic_fixcarry.o
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
diff --git a/techlibs/anlogic/anlogic_determine_init.cc b/techlibs/anlogic/anlogic_determine_init.cc
deleted file mode 100644
index 34b1d4f8a..000000000
--- a/techlibs/anlogic/anlogic_determine_init.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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 AnlogicDetermineInitPass : public Pass {
- AnlogicDetermineInitPass() : Pass("anlogic_determine_init", "Anlogic: Determine the init value of cells") { }
- void help() YS_OVERRIDE
- {
- log("\n");
- log(" anlogic_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 ANLOGIC_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 == "\\EG_LOGIC_DRAM16X4")
- {
- cell->setParam("\\INIT_D0", determine_init(cell->getParam("\\INIT_D0")));
- cell->setParam("\\INIT_D1", determine_init(cell->getParam("\\INIT_D1")));
- cell->setParam("\\INIT_D2", determine_init(cell->getParam("\\INIT_D2")));
- cell->setParam("\\INIT_D3", determine_init(cell->getParam("\\INIT_D3")));
- cnt++;
- }
- }
- }
- log_header(design, "Updated %lu cells with determined init value.\n", cnt);
- }
-} AnlogicDetermineInitPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/anlogic/anlogic_eqn.cc b/techlibs/anlogic/anlogic_eqn.cc
index 741bf04cc..070d39a20 100644
--- a/techlibs/anlogic/anlogic_eqn.cc
+++ b/techlibs/anlogic/anlogic_eqn.cc
@@ -69,7 +69,7 @@ struct AnlogicEqnPass : public Pass {
extra_args(args, args.size(), design);
- size_t cnt = 0;
+ int cnt = 0;
for (auto module : design->selected_modules())
{
for (auto cell : module->selected_cells())
@@ -106,7 +106,7 @@ struct AnlogicEqnPass : public Pass {
}
}
}
- log_header(design, "Updated %lu of AL_MAP_LUT* elements with equation.\n", cnt);
+ log_header(design, "Updated %d of AL_MAP_LUT* elements with equation.\n", cnt);
}
} AnlogicEqnPass;
diff --git a/techlibs/anlogic/anlogic_fixcarry.cc b/techlibs/anlogic/anlogic_fixcarry.cc
new file mode 100644
index 000000000..87164d375
--- /dev/null
+++ b/techlibs/anlogic/anlogic_fixcarry.cc
@@ -0,0 +1,130 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2019 Miodrag Milanovic <miodrag@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
+
+static SigBit get_bit_or_zero(const SigSpec &sig)
+{
+ if (GetSize(sig) == 0)
+ return State::S0;
+ return sig[0];
+}
+
+static void fix_carry_chain(Module *module)
+{
+ SigMap sigmap(module);
+
+ pool<SigBit> ci_bits;
+ dict<SigBit, SigBit> mapping_bits;
+
+ for (auto cell : module->cells())
+ {
+ if (cell->type == "\\AL_MAP_ADDER") {
+ if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
+ SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
+ SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));
+ if (bit_i0 == State::S0 && bit_i1== State::S0) {
+ SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
+ SigSpec o = cell->getPort("\\o");
+ if (GetSize(o) == 2) {
+ SigBit bit_o = o[0];
+ ci_bits.insert(bit_ci);
+ mapping_bits[bit_ci] = bit_o;
+ }
+ }
+ }
+ }
+ vector<Cell*> adders_to_fix_cells;
+ for (auto cell : module->cells())
+ {
+ if (cell->type == "\\AL_MAP_ADDER") {
+ if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
+ SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
+ SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
+ SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));
+ SigBit canonical_bit = sigmap(bit_ci);
+ if (!ci_bits.count(canonical_bit))
+ continue;
+ if (bit_i0 == State::S0 && bit_i1== State::S0)
+ continue;
+
+ adders_to_fix_cells.push_back(cell);
+ log("Found %s cell named %s with invalid 'c' signal.\n", log_id(cell->type), log_id(cell));
+ }
+ }
+
+ for (auto cell : adders_to_fix_cells)
+ {
+ SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
+ SigBit canonical_bit = sigmap(bit_ci);
+ auto bit = mapping_bits.at(canonical_bit);
+ log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
+ Cell *c = module->addCell(NEW_ID, "\\AL_MAP_ADDER");
+ SigBit new_bit = module->addWire(NEW_ID);
+ SigBit dummy_bit = module->addWire(NEW_ID);
+ SigSpec bits;
+ bits.append(dummy_bit);
+ bits.append(new_bit);
+ c->setParam("\\ALUTYPE", Const("ADD_CARRY"));
+ c->setPort("\\a", bit);
+ c->setPort("\\b", State::S0);
+ c->setPort("\\c", State::S0);
+ c->setPort("\\o", bits);
+
+ cell->setPort("\\c", new_bit);
+ }
+
+}
+
+struct AnlogicCarryFixPass : public Pass {
+ AnlogicCarryFixPass() : Pass("anlogic_fixcarry", "Anlogic: fix carry chain") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" anlogic_fixcarry [options] [selection]\n");
+ log("\n");
+ log("Add Anlogic adders to fix carry chain if needed.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing anlogic_fixcarry pass (fix invalid carry chain).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ Module *module = design->top_module();
+
+ if (module == nullptr)
+ log_cmd_error("No top module found.\n");
+
+ fix_carry_chain(module);
+ }
+} AnlogicCarryFixPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/anlogic/arith_map.v b/techlibs/anlogic/arith_map.v
index 11cd140ec..1186543da 100644
--- a/techlibs/anlogic/arith_map.v
+++ b/techlibs/anlogic/arith_map.v
@@ -31,7 +31,10 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
output [Y_WIDTH-1:0] X, Y;
input CI, BI;
- output CO;
+ output [Y_WIDTH-1:0] CO;
+
+ wire CIx;
+ wire [Y_WIDTH-1:0] COx;
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
@@ -41,44 +44,41 @@ module _80_anlogic_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] COx;
- wire [Y_WIDTH+1:0] C = {COx, CI};
+ wire [Y_WIDTH-1:0] C = { COx, CIx };
wire dummy;
- (* keep *)
AL_MAP_ADDER #(
.ALUTYPE("ADD_CARRY"))
adder_cin (
- .a(C[0]),
- .o({COx[0], dummy})
+ .a(CI),
+ .b(1'b0),
+ .c(1'b0),
+ .o({CIx, dummy})
);
genvar i;
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
- if(i==Y_WIDTH-1) begin
- (* keep *)
- AL_MAP_ADDER #(
- .ALUTYPE("ADD"))
- adder_cout (
- .c(C[Y_WIDTH]),
- .o(COx[Y_WIDTH])
- );
- assign CO = COx[Y_WIDTH];
- end
- else
- begin
- (* keep *)
AL_MAP_ADDER #(
.ALUTYPE("ADD")
) adder_i (
.a(AA[i]),
.b(BB[i]),
- .c(C[i+1]),
- .o({COx[i+1],Y[i]})
+ .c(C[i]),
+ .o({COx[i],Y[i]})
);
- end
- end: slice
+
+ wire cout;
+ AL_MAP_ADDER #(
+ .ALUTYPE("ADD"))
+ adder_cout (
+ .a(1'b0),
+ .b(1'b0),
+ .c(COx[i]),
+ .o({cout, CO[i]})
+ );
+ end: slice
endgenerate
- /* End implementation */
- assign X = AA ^ BB;
-endmodule \ No newline at end of file
+
+ /* End implementation */
+ assign X = AA ^ BB;
+endmodule
diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc
index 620bf3965..b87fc8566 100644
--- a/techlibs/anlogic/synth_anlogic.cc
+++ b/techlibs/anlogic/synth_anlogic.cc
@@ -154,7 +154,7 @@ struct SynthAnlogicPass : public ScriptPass
{
run("memory_bram -rules +/anlogic/drams.txt");
run("techmap -map +/anlogic/drams_map.v");
- run("anlogic_determine_init");
+ run("setundef -zero -params t:EG_LOGIC_DRAM16X4");
}
if (check_label("fine"))
@@ -186,6 +186,11 @@ struct SynthAnlogicPass : public ScriptPass
{
run("techmap -map +/anlogic/cells_map.v");
run("clean");
+ }
+
+ if (check_label("map_anlogic"))
+ {
+ run("anlogic_fixcarry");
run("anlogic_eqn");
}
diff --git a/techlibs/common/cmp2lut.v b/techlibs/common/cmp2lut.v
index 8aa1eb957..0d0757767 100644
--- a/techlibs/common/cmp2lut.v
+++ b/techlibs/common/cmp2lut.v
@@ -27,7 +27,7 @@ parameter _TECHMAP_CONSTVAL_A_ = 0;
parameter _TECHMAP_CONSTMSK_B_ = 0;
parameter _TECHMAP_CONSTVAL_B_ = 0;
-function automatic integer gen_lut;
+function automatic [(1 << `LUT_WIDTH)-1:0] gen_lut;
input integer width;
input integer operation;
input integer swap;
diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v
index 289673e82..64720e598 100644
--- a/techlibs/common/simcells.v
+++ b/techlibs/common/simcells.v
@@ -230,6 +230,25 @@ endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
+//- $_NMUX_ (A, B, S, Y)
+//-
+//- A 2-input inverting MUX gate.
+//-
+//- Truth table: A B S | Y
+//- -------+---
+//- 0 - 0 | 1
+//- 1 - 0 | 0
+//- - 0 1 | 1
+//- - 1 1 | 0
+//-
+module \$_NMUX_ (A, B, S, Y);
+input A, B, S;
+output Y;
+assign Y = S ? !B : !A;
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
//- $_MUX4_ (A, B, C, D, S, T, Y)
//-
//- A 4-input MUX gate.
diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v
index a424d3089..7845a3fed 100644
--- a/techlibs/common/simlib.v
+++ b/techlibs/common/simlib.v
@@ -532,14 +532,26 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $lcu (P, G, CI, CO)
+//-
+//- Lookahead carry unit
+//- A building block dedicated to fast computation of carry-bits used in binary
+//- arithmetic operations. By replacing the ripple carry structure used in full-adder
+//- blocks, the more significant bits of the sum can be expected to be computed more
+//- quickly.
+//- Typically created during `techmap` of $alu cells (see the "_90_alu" rule in
+//- +/techmap.v).
module \$lcu (P, G, CI, CO);
parameter WIDTH = 1;
-input [WIDTH-1:0] P, G;
-input CI;
+input [WIDTH-1:0] P; // Propagate
+input [WIDTH-1:0] G; // Generate
+input CI; // Carry-in
-output reg [WIDTH-1:0] CO;
+output reg [WIDTH-1:0] CO; // Carry-out
integer i;
always @* begin
@@ -555,6 +567,17 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $alu (A, B, CI, BI, X, Y, CO)
+//-
+//- Arithmetic logic unit.
+//- A building block supporting both binary addition/subtraction operations, and
+//- indirectly, comparison operations.
+//- Typically created by the `alumacc` pass, which transforms:
+//- $add, $sub, $lt, $le, $ge, $gt, $eq, $eqx, $ne, $nex
+//- cells into this $alu cell.
+//-
module \$alu (A, B, CI, BI, X, Y, CO);
parameter A_SIGNED = 0;
@@ -563,12 +586,16 @@ 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 [A_WIDTH-1:0] A; // Input operand
+input [B_WIDTH-1:0] B; // Input operand
+output [Y_WIDTH-1:0] X; // A xor B (sign-extended, optional B inversion,
+ // used in combination with
+ // reduction-AND for $eq/$ne ops)
+output [Y_WIDTH-1:0] Y; // Sum
-input CI, BI;
-output [Y_WIDTH-1:0] CO;
+input CI; // Carry-in (set for $sub)
+input BI; // Invert-B (set for $sub)
+output [Y_WIDTH-1:0] CO; // Carry-out
wire [Y_WIDTH-1:0] AA, BB;
@@ -584,6 +611,7 @@ endgenerate
wire y_co_undef = ^{A, A, B, B, CI, CI, BI, BI};
assign X = AA ^ BB;
+// Full adder
assign Y = (AA + BB + CI) ^ {Y_WIDTH{y_co_undef}};
function get_carry;
diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc
index e41c0fe97..a176357a7 100644
--- a/techlibs/common/synth.cc
+++ b/techlibs/common/synth.cc
@@ -75,13 +75,16 @@ struct SynthPass : 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(" -abc9\n");
+ log(" use new ABC9 flow (EXPERIMENTAL)\n");
+ log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
- string top_module, fsm_opts, memory_opts;
+ string top_module, fsm_opts, memory_opts, abc;
bool autotop, flatten, noalumacc, nofsm, noabc, noshare;
int lut;
@@ -98,6 +101,7 @@ struct SynthPass : public ScriptPass
nofsm = false;
noabc = false;
noshare = false;
+ abc = "abc";
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -159,6 +163,10 @@ struct SynthPass : public ScriptPass
noshare = true;
continue;
}
+ if (args[argidx] == "-abc9") {
+ abc = "abc9";
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -166,6 +174,9 @@ struct SynthPass : public ScriptPass
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
+ if (abc == "abc9" && !lut)
+ log_cmd_error("ABC9 flow only supported for FPGA synthesis (using '-lut' option)\n");
+
log_header(design, "Executing SYNTH pass.\n");
log_push();
@@ -241,15 +252,15 @@ struct SynthPass : public ScriptPass
#ifdef YOSYS_ENABLE_ABC
if (help_mode)
{
- run("abc -fast", " (unless -noabc, unless -lut)");
- run("abc -fast -lut k", "(unless -noabc, if -lut)");
+ run(abc + " -fast", " (unless -noabc, unless -lut)");
+ run(abc + " -fast -lut k", "(unless -noabc, if -lut)");
}
else
{
if (lut)
- run(stringf("abc -fast -lut %d", lut));
+ run(stringf("%s -fast -lut %d", abc.c_str(), lut));
else
- run("abc -fast");
+ run(abc + " -fast");
}
run("opt -fast", " (unless -noabc)");
#endif
diff --git a/techlibs/coolrunner2/coolrunner2_sop.cc b/techlibs/coolrunner2/coolrunner2_sop.cc
index 48da0d8ad..de0cbb29d 100644
--- a/techlibs/coolrunner2/coolrunner2_sop.cc
+++ b/techlibs/coolrunner2/coolrunner2_sop.cc
@@ -60,10 +60,8 @@ struct Coolrunner2SopPass : public Pass {
dict<SigBit, pool<tuple<Cell*, std::string>>> special_pterms_inv;
for (auto cell : module->selected_cells())
{
- if (cell->type == "\\FDCP" || cell->type == "\\FDCP_N" || cell->type == "\\FDDCP" ||
- cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP" ||
- cell->type == "\\FDCPE" || cell->type == "\\FDCPE_N" || cell->type == "\\FDDCPE" ||
- cell->type == "\\LDCP" || cell->type == "\\LDCP_N")
+ if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\FTCP", "\\FTCP_N", "\\FTDCP",
+ "\\FDCPE", "\\FDCPE_N", "\\FDDCPE", "\\LDCP", "\\LDCP_N"))
{
if (cell->hasPort("\\PRE"))
special_pterms_no_inv[sigmap(cell->getPort("\\PRE")[0])].insert(
@@ -257,10 +255,8 @@ struct Coolrunner2SopPass : public Pass {
pool<SigBit> sig_fed_by_ff;
for (auto cell : module->selected_cells())
{
- if (cell->type == "\\FDCP" || cell->type == "\\FDCP_N" || cell->type == "\\FDDCP" ||
- cell->type == "\\LDCP" || cell->type == "\\LDCP_N" ||
- cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP" ||
- cell->type == "\\FDCPE" || cell->type == "\\FDCPE_N" || cell->type == "\\FDDCPE")
+ if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N",
+ "\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE"))
{
auto output = sigmap(cell->getPort("\\Q")[0]);
sig_fed_by_ff.insert(output);
@@ -270,13 +266,11 @@ struct Coolrunner2SopPass : public Pass {
// Look at all the FF inputs
for (auto cell : module->selected_cells())
{
- if (cell->type == "\\FDCP" || cell->type == "\\FDCP_N" || cell->type == "\\FDDCP" ||
- cell->type == "\\LDCP" || cell->type == "\\LDCP_N" ||
- cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP" ||
- cell->type == "\\FDCPE" || cell->type == "\\FDCPE_N" || cell->type == "\\FDDCPE")
+ if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N",
+ "\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE"))
{
SigBit input;
- if (cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP")
+ if (cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP"))
input = sigmap(cell->getPort("\\T")[0]);
else
input = sigmap(cell->getPort("\\D")[0]);
@@ -300,7 +294,7 @@ struct Coolrunner2SopPass : public Pass {
xor_cell->setPort("\\IN_PTC", and_to_xor_wire);
xor_cell->setPort("\\OUT", xor_to_ff_wire);
- if (cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP")
+ if (cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP"))
cell->setPort("\\T", xor_to_ff_wire);
else
cell->setPort("\\D", xor_to_ff_wire);
diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc
index 4db087e87..73e18112f 100644
--- a/techlibs/ecp5/Makefile.inc
+++ b/techlibs/ecp5/Makefile.inc
@@ -4,13 +4,17 @@ 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))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_bb.v))
-$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/drams_map.v))
-$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dram.txt))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutrams_map.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutram.txt))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.box))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.lut))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g_nowide.lut))
+
EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
.SECONDARY: techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
diff --git a/techlibs/ecp5/abc_5g.box b/techlibs/ecp5/abc_5g.box
new file mode 100644
index 000000000..c757d137d
--- /dev/null
+++ b/techlibs/ecp5/abc_5g.box
@@ -0,0 +1,43 @@
+# NB: Inputs/Outputs must be ordered alphabetically
+# (with exceptions for carry in/out)
+
+# Box 1 : CCU2C (2xCARRY + 2xLUT4)
+# Outputs: S0, S1, COUT
+# (NB: carry chain input/output must be last
+# input/output and bus has been moved
+# there overriding the otherwise
+# alphabetical ordering)
+# name ID w/b ins outs
+CCU2C 1 1 9 3
+
+#A0 A1 B0 B1 C0 C1 D0 D1 CIN
+379 - 379 - 275 - 141 - 257
+630 379 630 379 526 275 392 141 273
+516 516 516 516 412 412 278 278 43
+
+# Box 2 : TRELLIS_DPR16X4 (16x4 dist ram)
+# Outputs: DO0, DO1, DO2, DO3
+# name ID w/b ins outs
+TRELLIS_DPR16X4 2 0 14 4
+
+#DI0 DI1 DI2 DI3 RAD0 RAD1 RAD2 RAD3 WAD0 WAD1 WAD2 WAD3 WCK WRE
+- - - - 141 379 275 379 - - - - - -
+- - - - 141 379 275 379 - - - - - -
+- - - - 141 379 275 379 - - - - - -
+- - - - 141 379 275 379 - - - - - -
+
+# Box 3 : PFUMX (MUX2)
+# Outputs: Z
+# name ID w/b ins outs
+PFUMX 3 1 3 1
+
+#ALUT BLUT C0
+98 98 151
+
+# Box 4 : L6MUX21 (MUX2)
+# Outputs: Z
+# name ID w/b ins outs
+L6MUX21 4 1 3 1
+
+#D0 D1 SD
+140 141 148
diff --git a/techlibs/ecp5/abc_5g.lut b/techlibs/ecp5/abc_5g.lut
new file mode 100644
index 000000000..e8aa9b35d
--- /dev/null
+++ b/techlibs/ecp5/abc_5g.lut
@@ -0,0 +1,25 @@
+# ECP5-5G LUT library for ABC
+# Note that ECP5 architecture assigns difference
+# in LUT input delay to interconnect, so this is
+# considered too
+
+
+# Simple LUTs
+# area D C B A
+1 1 141
+2 1 141 275
+3 1 141 275 379
+4 1 141 275 379 379
+
+# LUT5 = 2x LUT4 + PFUMX
+# area M0 D C B A
+5 2 151 239 373 477 477
+
+# LUT6 = 2x LUT5 + MUX2
+# area M1 M0 D C B A
+6 4 148 292 380 514 618 618
+
+# LUT7 = 2x LUT6 + MUX2
+# area M2 M1 M0 D C B A
+7 8 148 289 433 521 655 759 759
+
diff --git a/techlibs/ecp5/abc_5g_nowide.lut b/techlibs/ecp5/abc_5g_nowide.lut
new file mode 100644
index 000000000..60352d892
--- /dev/null
+++ b/techlibs/ecp5/abc_5g_nowide.lut
@@ -0,0 +1,12 @@
+# ECP5-5G LUT library for ABC
+# Note that ECP5 architecture assigns difference
+# in LUT input delay to interconnect, so this is
+# considered too
+
+
+# Simple LUTs
+# area D C B A
+1 1 141
+2 1 141 275
+3 1 141 275 379
+4 1 141 275 379 379
diff --git a/techlibs/ecp5/arith_map.v b/techlibs/ecp5/arith_map.v
index eb7947601..17bde0497 100644
--- a/techlibs/ecp5/arith_map.v
+++ b/techlibs/ecp5/arith_map.v
@@ -50,20 +50,21 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO);
wire [Y_WIDTH2-1:0] AA = A_buf;
wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;
+ wire [Y_WIDTH2-1:0] BX = B_buf;
wire [Y_WIDTH2-1:0] C = {CO, CI};
wire [Y_WIDTH2-1:0] FCO, Y1;
genvar i;
generate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice
CCU2C #(
- .INIT0(16'b0110011010101010),
- .INIT1(16'b0110011010101010),
+ .INIT0(16'b1001011010101010),
+ .INIT1(16'b1001011010101010),
.INJECT1_0("NO"),
.INJECT1_1("NO")
) ccu2c_i (
.CIN(C[i]),
- .A0(AA[i]), .B0(BB[i]), .C0(1'b0), .D0(1'b1),
- .A1(AA[i+1]), .B1(BB[i+1]), .C1(1'b0), .D1(1'b1),
+ .A0(AA[i]), .B0(BX[i]), .C0(BI), .D0(1'b1),
+ .A1(AA[i+1]), .B1(BX[i+1]), .C1(BI), .D1(1'b1),
.S0(Y[i]), .S1(Y1[i]),
.COUT(FCO[i])
);
diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v
index f6c71a03d..6985fbbc8 100644
--- a/techlibs/ecp5/cells_map.v
+++ b/techlibs/ecp5/cells_map.v
@@ -47,6 +47,28 @@ 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
+// TODO: Diamond flip-flops
+// module FD1P3AX(); endmodule
+// module FD1P3AY(); endmodule
+// module FD1P3BX(); endmodule
+// module FD1P3DX(); endmodule
+// module FD1P3IX(); endmodule
+// module FD1P3JX(); endmodule
+// module FD1S3AX(); endmodule
+// module FD1S3AY(); endmodule
+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
+module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
+module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
+module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
+// module FL1P3AY(); endmodule
+// module FL1P3AZ(); endmodule
+// module FL1P3BX(); endmodule
+// module FL1P3DX(); endmodule
+// module FL1P3IY(); endmodule
+// module FL1P3JY(); endmodule
+// module FL1S3AX(); endmodule
+// module FL1S3AY(); 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
@@ -62,8 +84,22 @@ module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(
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
+// Diamond I/O registers
+module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
+
+module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
+
+// TODO: Diamond I/O latches
+// module IFS1S1B(input PD, D, SCLK, output Q); endmodule
+// module IFS1S1D(input CD, D, SCLK, output Q); endmodule
+// module IFS1S1I(input PD, D, SCLK, output Q); endmodule
+// module IFS1S1J(input CD, D, SCLK, output Q); endmodule
`ifndef NO_LUT
module \$lut (A, Y);
@@ -73,77 +109,102 @@ module \$lut (A, Y);
input [WIDTH-1:0] A;
output Y;
+ // Need to swap input ordering, and fix init accordingly,
+ // to match ABC's expectation of LUT inputs in non-decreasing
+ // delay order
+ localparam P_WIDTH = WIDTH < 4 ? 4 : WIDTH;
+ function [P_WIDTH-1:0] permute_index;
+ input [P_WIDTH-1:0] i;
+ integer j;
+ begin
+ permute_index = 0;
+ for (j = 0; j < P_WIDTH; j = j + 1)
+ permute_index[P_WIDTH-1 - j] = i[j];
+ end
+ endfunction
+
+ function [2**P_WIDTH-1:0] permute_init;
+ integer i;
+ begin
+ permute_init = 0;
+ for (i = 0; i < 2**P_WIDTH; i = i + 1)
+ permute_init[i] = LUT[permute_index(i)];
+ end
+ endfunction
+
+ parameter [2**P_WIDTH-1:0] P_LUT = permute_init();
+
generate
if (WIDTH == 1) begin
- LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
- .A(A[0]), .B(1'b0), .C(1'b0), .D(1'b0));
+ LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(1'b0), .B(1'b0), .C(1'b0), .D(A[0]));
end else
if (WIDTH == 2) begin
- LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
- .A(A[0]), .B(A[1]), .C(1'b0), .D(1'b0));
+ LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(1'b0), .B(1'b0), .C(A[1]), .D(A[0]));
end else
if (WIDTH == 3) begin
- LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(1'b0));
+ LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(1'b0), .B(A[2]), .C(A[1]), .D(A[0]));
end else
if (WIDTH == 4) begin
- LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[3]), .B(A[2]), .C(A[1]), .D(A[0]));
`ifndef NO_PFUMUX
end else
if (WIDTH == 5) begin
wire f0, f1;
- LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
- LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
- PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(Y));
+ LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0),
+ .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1]));
+ LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1),
+ .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1]));
+ PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[0]), .Z(Y));
end else
if (WIDTH == 6) begin
wire f0, f1, f2, f3, g0, g1;
- LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
- LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
-
- LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
- LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
-
- PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0));
- PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1));
- L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[5]), .Z(Y));
+ LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0),
+ .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2]));
+ LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1),
+ .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2]));
+
+ LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2),
+ .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2]));
+ LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3),
+ .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2]));
+
+ PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[1]), .Z(g0));
+ PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[1]), .Z(g1));
+ L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[0]), .Z(Y));
end else
if (WIDTH == 7) begin
wire f0, f1, f2, f3, f4, f5, f6, f7, g0, g1, g2, g3, h0, h1;
- LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
- LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
-
- LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
- LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
-
- LUT4 #(.INIT(LUT[79:64])) lut4 (.Z(f4),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
- LUT4 #(.INIT(LUT[95:80])) lut5 (.Z(f5),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
-
- LUT4 #(.INIT(LUT[111: 96])) lut6 (.Z(f6),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
- LUT4 #(.INIT(LUT[127:112])) lut7 (.Z(f7),
- .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
-
- PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0));
- PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1));
- PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[4]), .Z(g2));
- PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[4]), .Z(g3));
- L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[5]), .Z(h0));
- L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[5]), .Z(h1));
- L6MUX21 mux7 (.D0(h0), .D1(h1), .SD(A[6]), .Z(Y));
+ LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0),
+ .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
+ LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1),
+ .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
+
+ LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2),
+ .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
+ LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3),
+ .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
+
+ LUT4 #(.INIT(P_LUT[79:64])) lut4 (.Z(f4),
+ .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
+ LUT4 #(.INIT(P_LUT[95:80])) lut5 (.Z(f5),
+ .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
+
+ LUT4 #(.INIT(P_LUT[111: 96])) lut6 (.Z(f6),
+ .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
+ LUT4 #(.INIT(P_LUT[127:112])) lut7 (.Z(f7),
+ .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
+
+ PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[2]), .Z(g0));
+ PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[2]), .Z(g1));
+ PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[2]), .Z(g2));
+ PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[2]), .Z(g3));
+ L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[1]), .Z(h0));
+ L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[1]), .Z(h1));
+ L6MUX21 mux7 (.D0(h0), .D1(h1), .SD(A[0]), .Z(Y));
`endif
end else begin
wire _TECHMAP_FAIL_ = 1;
diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v
index 1e4002ee0..dc8334acb 100644
--- a/techlibs/ecp5/cells_sim.v
+++ b/techlibs/ecp5/cells_sim.v
@@ -9,16 +9,21 @@ module LUT4(input A, B, C, D, output Z);
endmodule
// ---------------------------------------
-
+(* abc_box_id=4, lib_whitebox *)
module L6MUX21 (input D0, D1, SD, output Z);
assign Z = SD ? D1 : D0;
endmodule
// ---------------------------------------
-
-module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1,
- output S0, S1, COUT);
-
+(* abc_box_id=1, lib_whitebox *)
+module CCU2C(
+ (* abc_carry *)
+ input CIN,
+ input A0, B0, C0, D0, A1, B1, C1, D1,
+ output S0, S1,
+ (* abc_carry *)
+ output COUT
+);
parameter [15:0] INIT0 = 16'h0000;
parameter [15:0] INIT1 = 16'h0000;
parameter INJECT1_0 = "YES";
@@ -26,9 +31,13 @@ module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1,
// First half
wire LUT4_0, LUT2_0;
+`ifdef _ABC
+ assign LUT4_0 = INIT0[{D0, C0, B0, A0}];
+ assign LUT2_0 = INIT0[{2'b00, B0, A0}];
+`else
LUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0));
LUT2 #(.INIT(INIT0[3:0])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0));
-
+`endif
wire gated_cin_0 = (INJECT1_0 == "YES") ? 1'b0 : CIN;
assign S0 = LUT4_0 ^ gated_cin_0;
@@ -37,9 +46,13 @@ module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1,
// Second half
wire LUT4_1, LUT2_1;
+`ifdef _ABC
+ assign LUT4_1 = INIT1[{D1, C1, B1, A1}];
+ assign LUT2_1 = INIT1[{2'b00, B1, A1}];
+`else
LUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1));
LUT2 #(.INIT(INIT1[3:0])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1));
-
+`endif
wire gated_cin_1 = (INJECT1_1 == "YES") ? 1'b0 : cout_0;
assign S1 = LUT4_1 ^ gated_cin_1;
@@ -90,18 +103,22 @@ module TRELLIS_RAM16X2 (
endmodule
// ---------------------------------------
-
+(* abc_box_id=3, lib_whitebox *)
module PFUMX (input ALUT, BLUT, C0, output Z);
assign Z = C0 ? ALUT : BLUT;
endmodule
// ---------------------------------------
-
+//(* abc_box_id=2 *)
module TRELLIS_DPR16X4 (
- input [3:0] DI,
- input [3:0] WAD,
- input WRE, WCK,
- input [3:0] RAD,
+ (* abc_scc_break *)
+ input [3:0] DI,
+ (* abc_scc_break *)
+ input [3:0] WAD,
+ (* abc_scc_break *)
+ input WRE,
+ input WCK,
+ input [3:0] RAD,
output [3:0] DO
);
parameter WCKMUX = "WCK";
@@ -251,18 +268,6 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
endmodule
// ---------------------------------------
-
-module OBZ(input I, T, output O);
-assign O = T ? 1'bz : I;
-endmodule
-
-// ---------------------------------------
-
-module IB(input I, output O);
-assign O = I;
-endmodule
-
-// ---------------------------------------
(* keep *)
module TRELLIS_IO(
inout B,
@@ -293,19 +298,6 @@ endmodule
// ---------------------------------------
-module OB(input I, output O);
-assign O = I;
-endmodule
-
-// ---------------------------------------
-
-module BB(input I, T, output O, inout B);
-assign B = T ? 1'bz : I;
-assign O = B;
-endmodule
-
-// ---------------------------------------
-
module INV(input A, output Z);
assign Z = !A;
endmodule
@@ -350,6 +342,31 @@ module TRELLIS_SLICE(
parameter [127:0] CCU2_INJECT1_0 = "NO";
parameter [127:0] CCU2_INJECT1_1 = "NO";
parameter WREMUX = "WRE";
+ parameter WCKMUX = "WCK";
+
+ parameter A0MUX = "A0";
+ parameter A1MUX = "A1";
+ parameter B0MUX = "B0";
+ parameter B1MUX = "B1";
+ parameter C0MUX = "C0";
+ parameter C1MUX = "C1";
+ parameter D0MUX = "D0";
+ parameter D1MUX = "D1";
+
+ wire A0m, B0m, C0m, D0m;
+ wire A1m, B1m, C1m, D1m;
+
+ generate
+ if (A0MUX == "1") assign A0m = 1'b1; else assign A0m = A0;
+ if (B0MUX == "1") assign B0m = 1'b1; else assign B0m = B0;
+ if (C0MUX == "1") assign C0m = 1'b1; else assign C0m = C0;
+ if (D0MUX == "1") assign D0m = 1'b1; else assign D0m = D0;
+ if (A1MUX == "1") assign A1m = 1'b1; else assign A1m = A1;
+ if (B1MUX == "1") assign B1m = 1'b1; else assign B1m = B1;
+ if (C1MUX == "1") assign C1m = 1'b1; else assign C1m = C1;
+ if (D1MUX == "1") assign D1m = 1'b1; else assign D1m = D1;
+
+ endgenerate
function [15:0] permute_initval;
input [15:0] initval;
@@ -367,13 +384,13 @@ module TRELLIS_SLICE(
LUT4 #(
.INIT(LUT0_INITVAL)
) lut4_0 (
- .A(A0), .B(B0), .C(C0), .D(D0),
+ .A(A0m), .B(B0m), .C(C0m), .D(D0m),
.Z(F0)
);
LUT4 #(
.INIT(LUT1_INITVAL)
) lut4_1 (
- .A(A1), .B(B1), .C(C1), .D(D1),
+ .A(A1m), .B(B1m), .C(C1m), .D(D1m),
.Z(F1)
);
// LUT expansion muxes
@@ -387,20 +404,20 @@ module TRELLIS_SLICE(
.INJECT1_1(CCU2_INJECT1_1)
) ccu2c_i (
.CIN(FCI),
- .A0(A0), .B0(B0), .C0(C0), .D0(D0),
- .A1(A1), .B1(B1), .C1(C1), .D1(D1),
+ .A0(A0m), .B0(B0m), .C0(C0m), .D0(D0m),
+ .A1(A1m), .B1(B1m), .C1(C1m), .D1(D1m),
.S0(F0), .S1(F1),
.COUT(FCO)
);
end else if (MODE == "RAMW") begin
- assign WDO0 = C1;
- assign WDO1 = A1;
- assign WDO2 = D1;
- assign WDO3 = B1;
- assign WADO0 = D0;
- assign WADO1 = B0;
- assign WADO2 = C0;
- assign WADO3 = A0;
+ assign WDO0 = C1m;
+ assign WDO1 = A1m;
+ assign WDO2 = D1m;
+ assign WDO3 = B1m;
+ assign WADO0 = D0m;
+ assign WADO1 = B0m;
+ assign WADO2 = C0m;
+ assign WADO3 = A0m;
end else if (MODE == "DPRAM") begin
TRELLIS_RAM16X2 #(
.INITVAL_0(permute_initval(LUT0_INITVAL)),
@@ -410,17 +427,19 @@ module TRELLIS_SLICE(
.DI0(WD0), .DI1(WD1),
.WAD0(WAD0), .WAD1(WAD1), .WAD2(WAD2), .WAD3(WAD3),
.WRE(WRE), .WCK(WCK),
- .RAD0(D0), .RAD1(B0), .RAD2(C0), .RAD3(A0),
+ .RAD0(D0m), .RAD1(B0m), .RAD2(C0m), .RAD3(A0m),
.DO0(F0), .DO1(F1)
);
// TODO: confirm RAD and INITVAL ordering
// DPRAM mode contract?
+`ifdef FORMAL
always @(*) begin
- assert(A0==A1);
- assert(B0==B1);
- assert(C0==C1);
- assert(D0==D1);
+ assert(A0m==A1m);
+ assert(B0m==B1m);
+ assert(C0m==C1m);
+ assert(D0m==D1m);
end
+`endif
end else begin
ERROR_UNKNOWN_SLICE_MODE error();
end
@@ -472,105 +491,258 @@ module DP16KD(
input CSB2, CSB1, CSB0,
output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0
);
- parameter DATA_WIDTH_A = 18;
- parameter DATA_WIDTH_B = 18;
-
- parameter REGMODE_A = "NOREG";
- parameter REGMODE_B = "NOREG";
-
- parameter RESETMODE = "SYNC";
- parameter ASYNC_RESET_RELEASE = "SYNC";
-
- parameter CSDECODE_A = "0b000";
- parameter CSDECODE_B = "0b000";
-
- parameter WRITEMODE_A = "NORMAL";
- parameter WRITEMODE_B = "NORMAL";
-
- parameter CLKAMUX = "CLKA";
- parameter CLKBMUX = "CLKB";
-
- parameter GSR = "ENABLED";
-
- parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
- parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
-endmodule
+ parameter DATA_WIDTH_A = 18;
+ parameter DATA_WIDTH_B = 18;
+
+ parameter REGMODE_A = "NOREG";
+ parameter REGMODE_B = "NOREG";
+
+ parameter RESETMODE = "SYNC";
+ parameter ASYNC_RESET_RELEASE = "SYNC";
+
+ parameter CSDECODE_A = "0b000";
+ parameter CSDECODE_B = "0b000";
+
+ parameter WRITEMODE_A = "NORMAL";
+ parameter WRITEMODE_B = "NORMAL";
+
+ parameter DIA17MUX = "DIA17";
+ parameter DIA16MUX = "DIA16";
+ parameter DIA15MUX = "DIA15";
+ parameter DIA14MUX = "DIA14";
+ parameter DIA13MUX = "DIA13";
+ parameter DIA12MUX = "DIA12";
+ parameter DIA11MUX = "DIA11";
+ parameter DIA10MUX = "DIA10";
+ parameter DIA9MUX = "DIA9";
+ parameter DIA8MUX = "DIA8";
+ parameter DIA7MUX = "DIA7";
+ parameter DIA6MUX = "DIA6";
+ parameter DIA5MUX = "DIA5";
+ parameter DIA4MUX = "DIA4";
+ parameter DIA3MUX = "DIA3";
+ parameter DIA2MUX = "DIA2";
+ parameter DIA1MUX = "DIA1";
+ parameter DIA0MUX = "DIA0";
+ parameter ADA13MUX = "ADA13";
+ parameter ADA12MUX = "ADA12";
+ parameter ADA11MUX = "ADA11";
+ parameter ADA10MUX = "ADA10";
+ parameter ADA9MUX = "ADA9";
+ parameter ADA8MUX = "ADA8";
+ parameter ADA7MUX = "ADA7";
+ parameter ADA6MUX = "ADA6";
+ parameter ADA5MUX = "ADA5";
+ parameter ADA4MUX = "ADA4";
+ parameter ADA3MUX = "ADA3";
+ parameter ADA2MUX = "ADA2";
+ parameter ADA1MUX = "ADA1";
+ parameter ADA0MUX = "ADA0";
+ parameter CEAMUX = "CEA";
+ parameter OCEAMUX = "OCEA";
+ parameter CLKAMUX = "CLKA";
+ parameter WEAMUX = "WEA";
+ parameter RSTAMUX = "RSTA";
+ parameter CSA2MUX = "CSA2";
+ parameter CSA1MUX = "CSA1";
+ parameter CSA0MUX = "CSA0";
+ parameter DOA17MUX = "DOA17";
+ parameter DOA16MUX = "DOA16";
+ parameter DOA15MUX = "DOA15";
+ parameter DOA14MUX = "DOA14";
+ parameter DOA13MUX = "DOA13";
+ parameter DOA12MUX = "DOA12";
+ parameter DOA11MUX = "DOA11";
+ parameter DOA10MUX = "DOA10";
+ parameter DOA9MUX = "DOA9";
+ parameter DOA8MUX = "DOA8";
+ parameter DOA7MUX = "DOA7";
+ parameter DOA6MUX = "DOA6";
+ parameter DOA5MUX = "DOA5";
+ parameter DOA4MUX = "DOA4";
+ parameter DOA3MUX = "DOA3";
+ parameter DOA2MUX = "DOA2";
+ parameter DOA1MUX = "DOA1";
+ parameter DOA0MUX = "DOA0";
+ parameter DIB17MUX = "DIB17";
+ parameter DIB16MUX = "DIB16";
+ parameter DIB15MUX = "DIB15";
+ parameter DIB14MUX = "DIB14";
+ parameter DIB13MUX = "DIB13";
+ parameter DIB12MUX = "DIB12";
+ parameter DIB11MUX = "DIB11";
+ parameter DIB10MUX = "DIB10";
+ parameter DIB9MUX = "DIB9";
+ parameter DIB8MUX = "DIB8";
+ parameter DIB7MUX = "DIB7";
+ parameter DIB6MUX = "DIB6";
+ parameter DIB5MUX = "DIB5";
+ parameter DIB4MUX = "DIB4";
+ parameter DIB3MUX = "DIB3";
+ parameter DIB2MUX = "DIB2";
+ parameter DIB1MUX = "DIB1";
+ parameter DIB0MUX = "DIB0";
+ parameter ADB13MUX = "ADB13";
+ parameter ADB12MUX = "ADB12";
+ parameter ADB11MUX = "ADB11";
+ parameter ADB10MUX = "ADB10";
+ parameter ADB9MUX = "ADB9";
+ parameter ADB8MUX = "ADB8";
+ parameter ADB7MUX = "ADB7";
+ parameter ADB6MUX = "ADB6";
+ parameter ADB5MUX = "ADB5";
+ parameter ADB4MUX = "ADB4";
+ parameter ADB3MUX = "ADB3";
+ parameter ADB2MUX = "ADB2";
+ parameter ADB1MUX = "ADB1";
+ parameter ADB0MUX = "ADB0";
+ parameter CEBMUX = "CEB";
+ parameter OCEBMUX = "OCEB";
+ parameter CLKBMUX = "CLKB";
+ parameter WEBMUX = "WEB";
+ parameter RSTBMUX = "RSTB";
+ parameter CSB2MUX = "CSB2";
+ parameter CSB1MUX = "CSB1";
+ parameter CSB0MUX = "CSB0";
+ parameter DOB17MUX = "DOB17";
+ parameter DOB16MUX = "DOB16";
+ parameter DOB15MUX = "DOB15";
+ parameter DOB14MUX = "DOB14";
+ parameter DOB13MUX = "DOB13";
+ parameter DOB12MUX = "DOB12";
+ parameter DOB11MUX = "DOB11";
+ parameter DOB10MUX = "DOB10";
+ parameter DOB9MUX = "DOB9";
+ parameter DOB8MUX = "DOB8";
+ parameter DOB7MUX = "DOB7";
+ parameter DOB6MUX = "DOB6";
+ parameter DOB5MUX = "DOB5";
+ parameter DOB4MUX = "DOB4";
+ parameter DOB3MUX = "DOB3";
+ parameter DOB2MUX = "DOB2";
+ parameter DOB1MUX = "DOB1";
+ parameter DOB0MUX = "DOB0";
+
+ parameter WID = 0;
-// 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)
- );
+ parameter GSR = "ENABLED";
+
+ parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
endmodule
+
+// TODO: Diamond flip-flops
+// module FD1P3AX(); endmodule
+// module FD1P3AY(); endmodule
+// module FD1P3BX(); endmodule
+// module FD1P3DX(); endmodule
+// module FD1P3IX(); endmodule
+// module FD1P3JX(); endmodule
+// module FD1S3AX(); endmodule
+// module FD1S3AY(); endmodule
+module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
+module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
+module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
+module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
+// module FL1P3AY(); endmodule
+// module FL1P3AZ(); endmodule
+// module FL1P3BX(); endmodule
+// module FL1P3DX(); endmodule
+// module FL1P3IY(); endmodule
+// module FL1P3JY(); endmodule
+// module FL1S3AX(); endmodule
+// module FL1S3AY(); endmodule
+
+// Diamond I/O buffers
+module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule
+module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule
+module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule
+module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I)); endmodule
+module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule
+module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule
+module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule
+module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule
+module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule
+module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule
+module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule
+module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT")) tio (.B(A), .O(Z)); endmodule
+module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(Z), .I(A)); endmodule
+
+// Diamond I/O registers
+module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
+
+module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
+module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
+
+// TODO: Diamond I/O latches
+// module IFS1S1B(input PD, D, SCLK, output Q); endmodule
+// module IFS1S1D(input CD, D, SCLK, output Q); endmodule
+// module IFS1S1I(input PD, D, SCLK, output Q); endmodule
+// module IFS1S1J(input CD, D, SCLK, output Q); endmodule
diff --git a/techlibs/ecp5/dram.txt b/techlibs/ecp5/lutram.txt
index b94357429..b94357429 100644
--- a/techlibs/ecp5/dram.txt
+++ b/techlibs/ecp5/lutram.txt
diff --git a/techlibs/ecp5/drams_map.v b/techlibs/ecp5/lutrams_map.v
index 3b3de831f..3b3de831f 100644
--- a/techlibs/ecp5/drams_map.v
+++ b/techlibs/ecp5/lutrams_map.v
diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc
index c6e12248e..143d1f95c 100644
--- a/techlibs/ecp5/synth_ecp5.cc
+++ b/techlibs/ecp5/synth_ecp5.cc
@@ -2,7 +2,7 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2018 Clifford Wolf <dave@ds0.me>
+ * Copyright (C) 2018 David Shah <dave@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -71,17 +71,20 @@ struct SynthEcp5Pass : public ScriptPass
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(" do not use block RAM cells in output netlist\n");
log("\n");
- log(" -nodram\n");
- log(" do not use distributed RAM cells in output netlist\n");
+ log(" -nolutram\n");
+ log(" do not use LUT RAM cells in output netlist\n");
log("\n");
- log(" -nomux\n");
+ log(" -nowidelut\n");
log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
log("\n");
log(" -abc2\n");
log(" run two passes of 'abc' for slightly improved logic density\n");
log("\n");
+ log(" -abc9\n");
+ log(" use new ABC9 flow (EXPERIMENTAL)\n");
+ log("\n");
log(" -vpr\n");
log(" generate an output netlist (and BLIF file) suitable for VPR\n");
log(" (this feature is experimental and incomplete)\n");
@@ -93,7 +96,7 @@ struct SynthEcp5Pass : public ScriptPass
}
string top_opt, blif_file, edif_file, json_file;
- bool noccu2, nodffe, nobram, nodram, nomux, flatten, retime, abc2, vpr;
+ bool noccu2, nodffe, nobram, nolutram, nowidelut, flatten, retime, abc2, abc9, vpr;
void clear_flags() YS_OVERRIDE
{
@@ -104,12 +107,13 @@ struct SynthEcp5Pass : public ScriptPass
noccu2 = false;
nodffe = false;
nobram = false;
- nodram = false;
- nomux = false;
+ nolutram = false;
+ nowidelut = false;
flatten = true;
retime = false;
abc2 = false;
vpr = false;
+ abc9 = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -168,12 +172,12 @@ struct SynthEcp5Pass : public ScriptPass
nobram = true;
continue;
}
- if (args[argidx] == "-nodram") {
- nodram = true;
+ if (args[argidx] == "-nolutram" || /*deprecated alias*/ args[argidx] == "-nodram") {
+ nolutram = true;
continue;
}
- if (args[argidx] == "-nomux") {
- nomux = true;
+ if (args[argidx] == "-nowidelut" || /*deprecated alias*/ args[argidx] == "-nomux") {
+ nowidelut = true;
continue;
}
if (args[argidx] == "-abc2") {
@@ -184,6 +188,10 @@ struct SynthEcp5Pass : public ScriptPass
vpr = true;
continue;
}
+ if (args[argidx] == "-abc9") {
+ abc9 = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -191,6 +199,9 @@ struct SynthEcp5Pass : public ScriptPass
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
+ if (abc9 && retime)
+ log_cmd_error("-retime option not currently compatible with -abc9!\n");
+
log_header(design, "Executing SYNTH_ECP5 pass.\n");
log_push();
@@ -203,7 +214,7 @@ struct SynthEcp5Pass : public ScriptPass
{
if (check_label("begin"))
{
- run("read_verilog -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v");
+ run("read_verilog -D_ABC -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
}
@@ -220,23 +231,27 @@ struct SynthEcp5Pass : public ScriptPass
run("synth -run coarse");
}
- if (!nobram && check_label("bram", "(skip if -nobram)"))
+ if (!nobram && check_label("map_bram", "(skip if -nobram)"))
{
run("memory_bram -rules +/ecp5/bram.txt");
run("techmap -map +/ecp5/brams_map.v");
}
- if (!nodram && check_label("dram", "(skip if -nodram)"))
+ if (!nolutram && check_label("map_lutram", "(skip if -nolutram)"))
{
- run("memory_bram -rules +/ecp5/dram.txt");
- run("techmap -map +/ecp5/drams_map.v");
+ run("memory_bram -rules +/ecp5/lutram.txt");
+ run("techmap -map +/ecp5/lutrams_map.v");
}
- if (check_label("fine"))
+ if (check_label("map_ffram"))
{
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
run("opt -undriven -fine");
+ }
+
+ if (check_label("map_gates"))
+ {
if (noccu2)
run("techmap");
else
@@ -264,10 +279,17 @@ struct SynthEcp5Pass : public ScriptPass
run("abc", " (only if -abc2)");
}
run("techmap -map +/ecp5/latches_map.v");
- if (nomux)
- run("abc -lut 4 -dress");
- else
- run("abc -lut 4:7 -dress");
+ if (abc9) {
+ if (nowidelut)
+ run("abc9 -lut +/ecp5/abc_5g_nowide.lut -box +/ecp5/abc_5g.box -W 200");
+ else
+ run("abc9 -lut +/ecp5/abc_5g.lut -box +/ecp5/abc_5g.box -W 200");
+ } else {
+ if (nowidelut)
+ run("abc -lut 4 -dress");
+ else
+ run("abc -lut 4:7 -dress");
+ }
run("clean");
}
diff --git a/techlibs/efinix/Makefile.inc b/techlibs/efinix/Makefile.inc
new file mode 100644
index 000000000..5013f7fc1
--- /dev/null
+++ b/techlibs/efinix/Makefile.inc
@@ -0,0 +1,10 @@
+
+OBJS += techlibs/efinix/synth_efinix.o
+OBJS += techlibs/efinix/efinix_gbuf.o
+OBJS += techlibs/efinix/efinix_fixcarry.o
+
+$(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v))
+$(eval $(call add_share_file,share/efinix,techlibs/efinix/arith_map.v))
+$(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_sim.v))
+$(eval $(call add_share_file,share/efinix,techlibs/efinix/brams_map.v))
+$(eval $(call add_share_file,share/efinix,techlibs/efinix/bram.txt))
diff --git a/techlibs/efinix/arith_map.v b/techlibs/efinix/arith_map.v
new file mode 100644
index 000000000..178f57bc5
--- /dev/null
+++ b/techlibs/efinix/arith_map.v
@@ -0,0 +1,79 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
+ * 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.
+ *
+ */
+
+(* techmap_celltype = "$alu" *)
+module _80_efinix_alu (A, B, CI, BI, X, Y, CO);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ 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 CIx;
+ wire [Y_WIDTH-1:0] COx;
+
+ 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 = { COx, CIx };
+
+ EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1))
+ adder_cin (
+ .I0(CI),
+ .I1(1'b1),
+ .CI(1'b0),
+ .CO(CIx)
+ );
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
+ EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1))
+ adder_i (
+ .I0(AA[i]),
+ .I1(BB[i]),
+ .CI(C[i]),
+ .O(Y[i]),
+ .CO(COx[i])
+ );
+ EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1))
+ adder_cout (
+ .I0(1'b0),
+ .I1(1'b0),
+ .CI(COx[i]),
+ .O(CO[i])
+ );
+ end: slice
+ endgenerate
+
+ /* End implementation */
+ assign X = AA ^ BB;
+endmodule \ No newline at end of file
diff --git a/techlibs/efinix/bram.txt b/techlibs/efinix/bram.txt
new file mode 100644
index 000000000..0b3fd9308
--- /dev/null
+++ b/techlibs/efinix/bram.txt
@@ -0,0 +1,32 @@
+bram $__EFINIX_5K
+ init 1
+
+ abits 8 @a8d16
+ dbits 16 @a8d16
+ abits 9 @a9d8
+ dbits 8 @a9d8
+ abits 10 @a10d4
+ dbits 4 @a10d4
+ abits 11 @a11d2
+ dbits 2 @a11d2
+ abits 12 @a12d1
+ dbits 1 @a12d1
+ abits 8 @a8d20
+ dbits 20 @a8d20
+ abits 9 @a9d10
+ dbits 10 @a9d10
+
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 1 1
+ transp 0 2
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__EFINIX_5K
+ min bits 256
+ min efficiency 5
+ shuffle_enable B
+endmatch
diff --git a/techlibs/efinix/brams_map.v b/techlibs/efinix/brams_map.v
new file mode 100644
index 000000000..6786ae769
--- /dev/null
+++ b/techlibs/efinix/brams_map.v
@@ -0,0 +1,65 @@
+module \$__EFINIX_5K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 8;
+ parameter CFG_DBITS = 20;
+ parameter CFG_ENABLE_A = 1;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [5119:0] INIT = 5119'bx;
+ parameter TRANSP2 = 0;
+
+ 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;
+
+ localparam WRITEMODE_A = TRANSP2 ? "WRITE_FIRST" : "READ_FIRST";
+
+ EFX_RAM_5K #(
+ .READ_WIDTH(CFG_DBITS),
+ .WRITE_WIDTH(CFG_DBITS),
+ .OUTPUT_REG(1'b0),
+ .RCLK_POLARITY(1'b1),
+ .RE_POLARITY(1'b1),
+ .WCLK_POLARITY(1'b1),
+ .WE_POLARITY(1'b1),
+ .WCLKE_POLARITY(1'b1),
+ .WRITE_MODE(WRITEMODE_A),
+ .INIT_0(INIT[ 0*256 +: 256]),
+ .INIT_1(INIT[ 1*256 +: 256]),
+ .INIT_2(INIT[ 2*256 +: 256]),
+ .INIT_3(INIT[ 3*256 +: 256]),
+ .INIT_4(INIT[ 4*256 +: 256]),
+ .INIT_5(INIT[ 5*256 +: 256]),
+ .INIT_6(INIT[ 6*256 +: 256]),
+ .INIT_7(INIT[ 7*256 +: 256]),
+ .INIT_8(INIT[ 8*256 +: 256]),
+ .INIT_9(INIT[ 9*256 +: 256]),
+ .INIT_A(INIT[10*256 +: 256]),
+ .INIT_B(INIT[11*256 +: 256]),
+ .INIT_C(INIT[12*256 +: 256]),
+ .INIT_D(INIT[13*256 +: 256]),
+ .INIT_E(INIT[14*256 +: 256]),
+ .INIT_F(INIT[15*256 +: 256]),
+ .INIT_10(INIT[16*256 +: 256]),
+ .INIT_11(INIT[17*256 +: 256]),
+ .INIT_12(INIT[18*256 +: 256]),
+ .INIT_13(INIT[19*256 +: 256])
+ ) _TECHMAP_REPLACE_ (
+ .WDATA(A1DATA),
+ .WADDR(A1ADDR),
+ .WE(A1EN),
+ .WCLK(CLK2),
+ .WCLKE(1'b1),
+ .RDATA(B1DATA),
+ .RADDR(B1ADDR),
+ .RE(B1EN),
+ .RCLK(CLK3)
+ );
+endmodule
diff --git a/techlibs/efinix/cells_map.v b/techlibs/efinix/cells_map.v
new file mode 100644
index 000000000..0aeab1902
--- /dev/null
+++ b/techlibs/efinix/cells_map.v
@@ -0,0 +1,45 @@
+module \$_DFF_N_ (input D, C, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
+module \$_DFF_P_ (input D, C, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
+
+module \$_DFFE_NN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b0), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
+module \$_DFFE_NP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
+
+module \$_DFFE_PN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b0), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
+module \$_DFFE_PP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
+
+module \$_DFF_NN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
+module \$_DFF_NN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
+module \$_DFF_PN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
+module \$_DFF_PN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
+
+module \$_DFF_NP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
+module \$_DFF_NP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
+module \$_DFF_PP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
+module \$_DFF_PP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
+
+`ifndef NO_LUT
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0));
+ end else
+ if (WIDTH == 2) begin
+ EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(1'b0), .I3(1'b0));
+ end else
+ if (WIDTH == 3) begin
+ EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(1'b0));
+ end else
+ if (WIDTH == 4) begin
+ EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
+ end else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
+endmodule
+`endif
diff --git a/techlibs/efinix/cells_sim.v b/techlibs/efinix/cells_sim.v
new file mode 100644
index 000000000..8c8f6afaa
--- /dev/null
+++ b/techlibs/efinix/cells_sim.v
@@ -0,0 +1,107 @@
+module EFX_LUT4(
+ output O,
+ input I0,
+ input I1,
+ input I2,
+ input I3
+);
+ parameter LUTMASK = 16'h0000;
+endmodule
+
+module EFX_ADD(
+ output O,
+ output CO,
+ input I0,
+ input I1,
+ input CI
+);
+ parameter I0_POLARITY = 1;
+ parameter I1_POLARITY = 1;
+endmodule
+
+module EFX_FF(
+ output Q,
+ input D,
+ input CE,
+ input CLK,
+ input SR
+);
+ parameter CLK_POLARITY = 1;
+ parameter CE_POLARITY = 1;
+ parameter SR_POLARITY = 1;
+ parameter SR_SYNC = 0;
+ parameter SR_VALUE = 0;
+ parameter SR_SYNC_PRIORITY = 0;
+ parameter D_POLARITY = 1;
+endmodule
+
+module EFX_GBUFCE(
+ input CE,
+ input I,
+ output O
+);
+ parameter CE_POLARITY = 1'b1;
+endmodule
+
+module EFX_RAM_5K(
+ input [WRITE_WIDTH-1:0] WDATA,
+ input [WRITE_ADDR_WIDTH-1:0] WADDR,
+ input WE,
+ input WCLK,
+ input WCLKE,
+ output [READ_WIDTH-1:0] RDATA,
+ input [READ_ADDR_WIDTH-1:0] RADDR,
+ input RE,
+ input RCLK
+);
+ parameter READ_WIDTH = 20;
+ parameter WRITE_WIDTH = 20;
+ parameter OUTPUT_REG = 1'b0;
+ parameter RCLK_POLARITY = 1'b1;
+ parameter RE_POLARITY = 1'b1;
+ parameter WCLK_POLARITY = 1'b1;
+ parameter WE_POLARITY = 1'b1;
+ parameter WCLKE_POLARITY = 1'b1;
+ parameter WRITE_MODE = "READ_FIRST";
+ parameter INIT_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_8 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_9 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+ localparam READ_ADDR_WIDTH =
+ (READ_WIDTH == 16) ? 8 : // 256x16
+ (READ_WIDTH == 8) ? 9 : // 512x8
+ (READ_WIDTH == 4) ? 10 : // 1024x4
+ (READ_WIDTH == 2) ? 11 : // 2048x2
+ (READ_WIDTH == 1) ? 12 : // 4096x1
+ (READ_WIDTH == 20) ? 8 : // 256x20
+ (READ_WIDTH == 10) ? 9 : // 512x10
+ (READ_WIDTH == 5) ? 10 : -1; // 1024x5
+
+ localparam WRITE_ADDR_WIDTH =
+ (WRITE_WIDTH == 16) ? 8 : // 256x16
+ (WRITE_WIDTH == 8) ? 9 : // 512x8
+ (WRITE_WIDTH == 4) ? 10 : // 1024x4
+ (WRITE_WIDTH == 2) ? 11 : // 2048x2
+ (WRITE_WIDTH == 1) ? 12 : // 4096x1
+ (WRITE_WIDTH == 20) ? 8 : // 256x20
+ (WRITE_WIDTH == 10) ? 9 : // 512x10
+ (WRITE_WIDTH == 5) ? 10 : -1; // 1024x5
+
+endmodule \ No newline at end of file
diff --git a/techlibs/efinix/efinix_fixcarry.cc b/techlibs/efinix/efinix_fixcarry.cc
new file mode 100644
index 000000000..b7cd995b8
--- /dev/null
+++ b/techlibs/efinix/efinix_fixcarry.cc
@@ -0,0 +1,122 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2019 Miodrag Milanovic <miodrag@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
+
+static SigBit get_bit_or_zero(const SigSpec &sig)
+{
+ if (GetSize(sig) == 0)
+ return State::S0;
+ return sig[0];
+}
+
+static void fix_carry_chain(Module *module)
+{
+ SigMap sigmap(module);
+
+ pool<SigBit> ci_bits;
+ dict<SigBit, SigBit> mapping_bits;
+
+ for (auto cell : module->cells())
+ {
+ if (cell->type == "\\EFX_ADD") {
+ SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0"));
+ SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1"));
+ if (bit_i0 == State::S0 && bit_i1== State::S0) {
+ SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
+ SigBit bit_o = sigmap(cell->getPort("\\O"));
+ ci_bits.insert(bit_ci);
+ mapping_bits[bit_ci] = bit_o;
+ }
+ }
+ }
+
+ vector<Cell*> adders_to_fix_cells;
+ for (auto cell : module->cells())
+ {
+ if (cell->type == "\\EFX_ADD") {
+ SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
+ SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0"));
+ SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1"));
+ SigBit canonical_bit = sigmap(bit_ci);
+ if (!ci_bits.count(canonical_bit))
+ continue;
+ if (bit_i0 == State::S0 && bit_i1== State::S0)
+ continue;
+
+ adders_to_fix_cells.push_back(cell);
+ log("Found %s cell named %s with invalid CI signal.\n", log_id(cell->type), log_id(cell));
+ }
+ }
+
+ for (auto cell : adders_to_fix_cells)
+ {
+ SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
+ SigBit canonical_bit = sigmap(bit_ci);
+ auto bit = mapping_bits.at(canonical_bit);
+ log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
+ Cell *c = module->addCell(NEW_ID, "\\EFX_ADD");
+ SigBit new_bit = module->addWire(NEW_ID);
+ c->setParam("\\I0_POLARITY", State::S1);
+ c->setParam("\\I1_POLARITY", State::S1);
+ c->setPort("\\I0", bit);
+ c->setPort("\\I1", State::S1);
+ c->setPort("\\CI", State::S0);
+ c->setPort("\\CO", new_bit);
+
+ cell->setPort("\\CI", new_bit);
+ }
+}
+
+struct EfinixCarryFixPass : public Pass {
+ EfinixCarryFixPass() : Pass("efinix_fixcarry", "Efinix: fix carry chain") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" efinix_fixcarry [options] [selection]\n");
+ log("\n");
+ log("Add Efinix adders to fix carry chain if needed.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing efinix_fixcarry pass (fix invalid carry chain).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ Module *module = design->top_module();
+
+ if (module == nullptr)
+ log_cmd_error("No top module found.\n");
+
+ fix_carry_chain(module);
+ }
+} EfinixCarryFixPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/efinix/efinix_gbuf.cc b/techlibs/efinix/efinix_gbuf.cc
new file mode 100644
index 000000000..e75fb3f4d
--- /dev/null
+++ b/techlibs/efinix/efinix_gbuf.cc
@@ -0,0 +1,119 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
+ * 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"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+static void handle_gbufs(Module *module)
+{
+ SigMap sigmap(module);
+
+ pool<SigBit> clk_bits;
+ dict<SigBit, SigBit> rewrite_bits;
+ vector<pair<Cell*, SigBit>> pad_bits;
+
+ for (auto cell : module->cells())
+ {
+ if (cell->type == "\\EFX_FF") {
+ for (auto bit : sigmap(cell->getPort("\\CLK")))
+ clk_bits.insert(bit);
+ }
+ if (cell->type == "\\EFX_RAM_5K") {
+ for (auto bit : sigmap(cell->getPort("\\RCLK")))
+ clk_bits.insert(bit);
+ for (auto bit : sigmap(cell->getPort("\\WCLK")))
+ clk_bits.insert(bit);
+ }
+ }
+
+ for (auto wire : vector<Wire*>(module->wires()))
+ {
+ if (!wire->port_input)
+ continue;
+
+ for (int index = 0; index < GetSize(wire); index++)
+ {
+ SigBit bit(wire, index);
+ SigBit canonical_bit = sigmap(bit);
+
+ if (!clk_bits.count(canonical_bit))
+ continue;
+
+ Cell *c = module->addCell(NEW_ID, "\\EFX_GBUFCE");
+ SigBit new_bit = module->addWire(NEW_ID);
+ c->setParam("\\CE_POLARITY", State::S1);
+ c->setPort("\\O", new_bit);
+ c->setPort("\\CE", State::S1);
+ 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("\\I", it.second);
+}
+
+struct EfinixGbufPass : public Pass {
+ EfinixGbufPass() : Pass("efinix_gbuf", "Efinix: insert global clock buffers") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" efinix_gbuf [options] [selection]\n");
+ log("\n");
+ log("Add Efinix global clock buffers to top module as needed.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing efinix_gbuf pass (insert global clock buffers).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ Module *module = design->top_module();
+
+ if (module == nullptr)
+ log_cmd_error("No top module found.\n");
+
+ handle_gbufs(module);
+ }
+} EfinixGbufPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc
new file mode 100644
index 000000000..26a8d4eda
--- /dev/null
+++ b/techlibs/efinix/synth_efinix.cc
@@ -0,0 +1,219 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
+ * Copyright (C) 2019 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/register.h"
+#include "kernel/celltypes.h"
+#include "kernel/rtlil.h"
+#include "kernel/log.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct SynthEfinixPass : public ScriptPass
+{
+ SynthEfinixPass() : ScriptPass("synth_efinix", "synthesis for Efinix FPGAs") { }
+
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_efinix [options]\n");
+ log("\n");
+ log("This command runs synthesis for Efinix FPGAs.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module\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");
+ log("\n");
+ log(" -json <file>\n");
+ log(" write the design to the specified JSON file. writing of an output file\n");
+ log(" 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(" -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("\n");
+ log("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
+
+ string top_opt, edif_file, json_file;
+ bool flatten, retime;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ edif_file = "";
+ json_file = "";
+ flatten = true;
+ retime = false;
+ }
+
+ 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] == "-top" && argidx+1 < args.size()) {
+ top_opt = "-top " + args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-edif" && argidx+1 < args.size()) {
+ edif_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-json" && argidx+1 < args.size()) {
+ json_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] == "-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");
+
+ log_header(design, "Executing SYNTH_EFINIX pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() YS_OVERRIDE
+ {
+ if (check_label("begin"))
+ {
+ run("read_verilog -lib +/efinix/cells_sim.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 (check_label("coarse"))
+ {
+ run("synth -run coarse");
+ }
+
+ if (check_label("map_bram", "(skip if -nobram)"))
+ {
+ run("memory_bram -rules +/efinix/bram.txt");
+ run("techmap -map +/efinix/brams_map.v");
+ run("setundef -zero -params t:EFX_RAM_5K");
+ }
+
+ if (check_label("fine"))
+ {
+ run("opt -fast -mux_undef -undriven -fine");
+ run("memory_map");
+ run("opt -undriven -fine");
+ run("techmap -map +/techmap.v -map +/efinix/arith_map.v");
+ if (retime || help_mode)
+ run("abc -dff", "(only if -retime)");
+ }
+
+ if (check_label("map_ffs"))
+ {
+ run("dffsr2dff");
+ run("techmap -D NO_LUT -map +/efinix/cells_map.v");
+ run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit");
+ run("opt_expr -mux_undef");
+ run("simplemap");
+ }
+
+ if (check_label("map_luts"))
+ {
+ run("abc -lut 4");
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ run("techmap -map +/efinix/cells_map.v");
+ run("clean");
+ }
+
+ if (check_label("map_gbuf"))
+ {
+ run("efinix_gbuf");
+ run("efinix_fixcarry");
+ run("clean");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
+
+ if (check_label("edif"))
+ {
+ if (!edif_file.empty() || help_mode)
+ run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
+ }
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode)
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
+ }
+} SynthEfinixPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/gowin/determine_init.cc b/techlibs/gowin/determine_init.cc
index 991e5245a..d9a0880f6 100644
--- a/techlibs/gowin/determine_init.cc
+++ b/techlibs/gowin/determine_init.cc
@@ -50,7 +50,7 @@ struct DetermineInitPass : public Pass {
extra_args(args, args.size(), design);
- size_t cnt = 0;
+ int cnt = 0;
for (auto module : design->selected_modules())
{
for (auto cell : module->selected_cells())
@@ -65,7 +65,7 @@ struct DetermineInitPass : public Pass {
}
}
}
- log_header(design, "Updated %lu cells with determined init value.\n", cnt);
+ log_header(design, "Updated %d cells with determined init value.\n", cnt);
}
} DetermineInitPass;
diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc
index 723b59d6f..76a89b107 100644
--- a/techlibs/ice40/Makefile.inc
+++ b/techlibs/ice40/Makefile.inc
@@ -4,7 +4,6 @@ OBJS += techlibs/ice40/ice40_braminit.o
OBJS += techlibs/ice40/ice40_ffssr.o
OBJS += techlibs/ice40/ice40_ffinit.o
OBJS += techlibs/ice40/ice40_opt.o
-OBJS += techlibs/ice40/ice40_unlut.o
GENFILES += techlibs/ice40/brams_init1.vh
GENFILES += techlibs/ice40/brams_init2.vh
@@ -28,6 +27,12 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.box))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.lut))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.box))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.lut))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.box))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.lut))
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh))
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh))
diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box
new file mode 100644
index 000000000..c0ea742e2
--- /dev/null
+++ b/techlibs/ice40/abc_hx.box
@@ -0,0 +1,13 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt
+
+# NB: Inputs/Outputs must be ordered alphabetically
+# (with exceptions for carry in/out)
+
+# Inputs: A B CI
+# Outputs: O CO
+# (NB: carry chain input/output must be last
+# input/output and have been moved there
+# overriding the alphabetical ordering)
+$__ICE40_FULL_ADDER 1 1 3 2
+400 379 316
+259 231 126
diff --git a/techlibs/ice40/abc_hx.lut b/techlibs/ice40/abc_hx.lut
new file mode 100644
index 000000000..3b3bb11e2
--- /dev/null
+++ b/techlibs/ice40/abc_hx.lut
@@ -0,0 +1,6 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt
+# I3 I2 I1 I0
+1 1 316
+2 1 316 379
+3 1 316 379 400
+4 1 316 379 400 449
diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc_lp.box
new file mode 100644
index 000000000..d73b6d649
--- /dev/null
+++ b/techlibs/ice40/abc_lp.box
@@ -0,0 +1,13 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt
+
+# NB: Inputs/Outputs must be ordered alphabetically
+# (with exceptions for carry in/out)
+
+# Inputs: A B CI
+# Outputs: O CO
+# (NB: carry chain input/output must be last
+# input/output and have been moved there
+# overriding the alphabetical ordering)
+$__ICE40_FULL_ADDER 1 1 3 2
+589 558 465
+675 609 186
diff --git a/techlibs/ice40/abc_lp.lut b/techlibs/ice40/abc_lp.lut
new file mode 100644
index 000000000..e72f760a2
--- /dev/null
+++ b/techlibs/ice40/abc_lp.lut
@@ -0,0 +1,6 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt
+# I3 I2 I1 I0
+1 1 465
+2 1 465 558
+3 1 465 558 589
+4 1 465 558 589 661
diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc_u.box
new file mode 100644
index 000000000..42d666051
--- /dev/null
+++ b/techlibs/ice40/abc_u.box
@@ -0,0 +1,13 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt
+
+# NB: Inputs/Outputs must be ordered alphabetically
+# (with exceptions for carry in/out)
+
+# Inputs: A B CI
+# Outputs: O CO
+# (NB: carry chain input/output must be last
+# input/output and have been moved there
+# overriding the alphabetical ordering)
+$__ICE40_FULL_ADDER 1 1 3 2
+1231 1205 874
+675 609 278
diff --git a/techlibs/ice40/abc_u.lut b/techlibs/ice40/abc_u.lut
new file mode 100644
index 000000000..1e4fcadb6
--- /dev/null
+++ b/techlibs/ice40/abc_u.lut
@@ -0,0 +1,6 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt
+# I3 I2 I1 I0
+1 1 874
+2 1 874 1205
+3 1 874 1205 1231
+4 1 874 1205 1231 1285
diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v
index 4449fdc1b..26b24db9e 100644
--- a/techlibs/ice40/arith_map.v
+++ b/techlibs/ice40/arith_map.v
@@ -44,23 +44,19 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);
genvar i;
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
- SB_CARRY carry (
- .I0(AA[i]),
- .I1(BB[i]),
+ \$__ICE40_CARRY_WRAPPER #(
+ // A[0]: 1010 1010 1010 1010
+ // A[1]: 1100 1100 1100 1100
+ // A[2]: 1111 0000 1111 0000
+ // A[3]: 1111 1111 0000 0000
+ .LUT(16'b 0110_1001_1001_0110)
+ ) fadd (
+ .A(AA[i]),
+ .B(BB[i]),
.CI(C[i]),
- .CO(CO[i])
- );
- SB_LUT4 #(
- // I0: 1010 1010 1010 1010
- // I1: 1100 1100 1100 1100
- // I2: 1111 0000 1111 0000
- // I3: 1111 1111 0000 0000
- .LUT_INIT(16'b 0110_1001_1001_0110)
- ) adder (
.I0(1'b0),
- .I1(AA[i]),
- .I2(BB[i]),
.I3(C[i]),
+ .CO(CO[i]),
.O(Y[i])
);
end endgenerate
diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v
index d0ddfd02e..662423f0a 100644
--- a/techlibs/ice40/cells_map.v
+++ b/techlibs/ice40/cells_map.v
@@ -37,23 +37,46 @@ module \$lut (A, Y);
generate
if (WIDTH == 1) begin
- SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0));
+ localparam [15:0] INIT = {{8{LUT[1]}}, {8{LUT[0]}}};
+ SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(1'b0), .I1(1'b0), .I2(1'b0), .I3(A[0]));
end else
if (WIDTH == 2) begin
- SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(1'b0), .I3(1'b0));
+ localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[1]}}, {4{LUT[2]}}, {4{LUT[0]}}};
+ SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(1'b0), .I1(1'b0), .I2(A[1]), .I3(A[0]));
end else
if (WIDTH == 3) begin
- SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(1'b0));
+ localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[3]}}, {2{LUT[5]}}, {2{LUT[1]}}, {2{LUT[6]}}, {2{LUT[2]}}, {2{LUT[4]}}, {2{LUT[0]}}};
+ SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(1'b0), .I1(A[2]), .I2(A[1]), .I3(A[0]));
end else
if (WIDTH == 4) begin
- SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
+ localparam [15:0] INIT = {LUT[15], LUT[7], LUT[11], LUT[3], LUT[13], LUT[5], LUT[9], LUT[1], LUT[14], LUT[6], LUT[10], LUT[2], LUT[12], LUT[4], LUT[8], LUT[0]};
+ SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0]));
end else begin
wire _TECHMAP_FAIL_ = 1;
end
endgenerate
endmodule
`endif
+
+`ifndef NO_ADDER
+module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3);
+ parameter LUT = 0;
+ SB_CARRY carry (
+ .I0(A),
+ .I1(B),
+ .CI(CI),
+ .CO(CO)
+ );
+ \$lut #(
+ .WIDTH(4),
+ .LUT(LUT)
+ ) lut (
+ .A({I0,A,B,I3}),
+ .Y(O)
+ );
+endmodule
+`endif
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index f9945b2b5..c7f3bdad2 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -127,6 +127,7 @@ endmodule
// SiliconBlue Logic Cells
+(* lib_whitebox *)
module SB_LUT4 (output O, input I0, I1, I2, I3);
parameter [15:0] LUT_INIT = 0;
wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
@@ -135,10 +136,42 @@ module SB_LUT4 (output O, input I0, I1, I2, I3);
assign O = I0 ? s1[1] : s1[0];
endmodule
+(* lib_whitebox *)
module SB_CARRY (output CO, input I0, I1, CI);
assign CO = (I0 && I1) || ((I0 || I1) && CI);
endmodule
+(* abc_box_id = 1, lib_whitebox *)
+module \$__ICE40_FULL_ADDER (
+ (* abc_carry *)
+ output CO,
+ output O,
+ input A,
+ input B,
+ (* abc_carry *)
+ input CI
+);
+ SB_CARRY carry (
+ .I0(A),
+ .I1(B),
+ .CI(CI),
+ .CO(CO)
+ );
+ SB_LUT4 #(
+ // I0: 1010 1010 1010 1010
+ // I1: 1100 1100 1100 1100
+ // I2: 1111 0000 1111 0000
+ // I3: 1111 1111 0000 0000
+ .LUT_INIT(16'b 0110_1001_1001_0110)
+ ) adder (
+ .I0(1'b0),
+ .I1(A),
+ .I2(B),
+ .I3(CI),
+ .O(O)
+ );
+endmodule
+
// Positive Edge SiliconBlue FF Cells
module SB_DFF (output `SB_DFF_REG, input C, D);
@@ -1338,13 +1371,13 @@ module SB_MAC16 (
wire [15:0] p_Ah_Bh, p_Al_Bh, p_Ah_Bl, p_Al_Bl;
wire [15:0] Ah, Al, Bh, Bl;
assign Ah = {A_SIGNED ? {8{iA[15]}} : 8'b0, iA[15: 8]};
- assign Al = {A_SIGNED ? {8{iA[ 7]}} : 8'b0, iA[ 7: 0]};
+ assign Al = {A_SIGNED && MODE_8x8 ? {8{iA[ 7]}} : 8'b0, iA[ 7: 0]};
assign Bh = {B_SIGNED ? {8{iB[15]}} : 8'b0, iB[15: 8]};
- assign Bl = {B_SIGNED ? {8{iB[ 7]}} : 8'b0, iB[ 7: 0]};
- assign p_Ah_Bh = Ah * Bh;
- assign p_Al_Bh = Al * Bh;
- assign p_Ah_Bl = Ah * Bl;
- assign p_Al_Bl = Al * Bl;
+ assign Bl = {B_SIGNED && MODE_8x8 ? {8{iB[ 7]}} : 8'b0, iB[ 7: 0]};
+ assign p_Ah_Bh = Ah * Bh; // F
+ assign p_Al_Bh = {8'b0, Al[7:0]} * Bh; // J
+ assign p_Ah_Bl = Ah * {8'b0, Bl[7:0]}; // K
+ assign p_Al_Bl = Al * Bl; // G
// Regs F and J
reg [15:0] rF, rJ;
@@ -1375,7 +1408,9 @@ module SB_MAC16 (
assign iG = BOT_8x8_MULT_REG ? rG : p_Al_Bl;
// Adder Stage
- assign iL = iG + (iK << 8) + (iJ << 8) + (iF << 16);
+ wire [23:0] iK_e = {A_SIGNED ? {8{iK[15]}} : 8'b0, iK};
+ wire [23:0] iJ_e = {B_SIGNED ? {8{iJ[15]}} : 8'b0, iJ};
+ assign iL = iG + (iK_e << 8) + (iJ_e << 8) + (iF << 16);
// Reg H
reg [31:0] rH;
diff --git a/techlibs/ice40/ice40_braminit.cc b/techlibs/ice40/ice40_braminit.cc
index 4fa6b0792..1a139ffea 100644
--- a/techlibs/ice40/ice40_braminit.cc
+++ b/techlibs/ice40/ice40_braminit.cc
@@ -69,13 +69,13 @@ static void run_ice40_braminit(Module *module)
for (int i = 0; i < GetSize(line); i++)
{
- if (in_comment && line.substr(i, 2) == "*/") {
+ if (in_comment && line.compare(i, 2, "*/") == 0) {
line[i] = ' ';
line[i+1] = ' ';
in_comment = false;
continue;
}
- if (!in_comment && line.substr(i, 2) == "/*")
+ if (!in_comment && line.compare(i, 2, "/*") == 0)
in_comment = true;
if (in_comment)
line[i] = ' ';
@@ -87,7 +87,7 @@ static void run_ice40_braminit(Module *module)
long value;
token = next_token(line, " \t\r\n");
- if (token.empty() || token.substr(0, 2) == "//")
+ if (token.empty() || token.compare(0, 2, "//") == 0)
break;
if (token[0] == '@') {
diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index f528607d6..d5106b805 100644
--- a/techlibs/ice40/ice40_opt.cc
+++ b/techlibs/ice40/ice40_opt.cc
@@ -83,6 +83,51 @@ static void run_ice40_opts(Module *module)
}
continue;
}
+
+ if (cell->type == "$__ICE40_FULL_ADDER")
+ {
+ SigSpec non_const_inputs, replacement_output;
+ int count_zeros = 0, count_ones = 0;
+
+ SigBit inbit[3] = {
+ cell->getPort("\\A"),
+ cell->getPort("\\B"),
+ cell->getPort("\\CI")
+ };
+ for (int i = 0; i < 3; i++)
+ if (inbit[i].wire == nullptr) {
+ if (inbit[i] == State::S1)
+ count_ones++;
+ else
+ count_zeros++;
+ } else
+ non_const_inputs.append(inbit[i]);
+
+ if (count_zeros >= 2)
+ replacement_output = State::S0;
+ else if (count_ones >= 2)
+ replacement_output = State::S1;
+ else if (GetSize(non_const_inputs) == 1)
+ replacement_output = non_const_inputs;
+
+ if (GetSize(replacement_output)) {
+ optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
+ module->connect(cell->getPort("\\CO")[0], replacement_output);
+ module->design->scratchpad_set_bool("opt.did_something", true);
+ log("Optimized $__ICE40_FULL_ADDER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",
+ log_id(module), log_id(cell), log_signal(replacement_output));
+ cell->type = "$lut";
+ cell->setPort("\\A", { State::S0, inbit[0], inbit[1], inbit[2] });
+ cell->setPort("\\Y", cell->getPort("\\O"));
+ cell->unsetPort("\\B");
+ cell->unsetPort("\\CI");
+ cell->unsetPort("\\CO");
+ cell->unsetPort("\\O");
+ cell->setParam("\\LUT", RTLIL::Const::from_string("0110100110010110"));
+ cell->setParam("\\WIDTH", 4);
+ }
+ continue;
+ }
}
for (auto cell : sb_lut_cells)
diff --git a/techlibs/ice40/ice40_unlut.cc b/techlibs/ice40/ice40_unlut.cc
deleted file mode 100644
index 2428a8e78..000000000
--- a/techlibs/ice40/ice40_unlut.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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>
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-static SigBit get_bit_or_zero(const SigSpec &sig)
-{
- if (GetSize(sig) == 0)
- return State::S0;
- return sig[0];
-}
-
-static void run_ice40_unlut(Module *module)
-{
- SigMap sigmap(module);
-
- for (auto cell : module->selected_cells())
- {
- if (cell->type == "\\SB_LUT4")
- {
- SigSpec inbits;
-
- inbits.append(get_bit_or_zero(cell->getPort("\\I0")));
- inbits.append(get_bit_or_zero(cell->getPort("\\I1")));
- inbits.append(get_bit_or_zero(cell->getPort("\\I2")));
- inbits.append(get_bit_or_zero(cell->getPort("\\I3")));
- sigmap.apply(inbits);
-
- log("Mapping SB_LUT4 cell %s.%s to $lut.\n", log_id(module), log_id(cell));
-
- cell->type ="$lut";
- cell->setParam("\\WIDTH", 4);
- cell->setParam("\\LUT", cell->getParam("\\LUT_INIT"));
- cell->unsetParam("\\LUT_INIT");
-
- cell->setPort("\\A", SigSpec({
- get_bit_or_zero(cell->getPort("\\I3")),
- get_bit_or_zero(cell->getPort("\\I2")),
- get_bit_or_zero(cell->getPort("\\I1")),
- get_bit_or_zero(cell->getPort("\\I0"))
- }));
- cell->setPort("\\Y", cell->getPort("\\O")[0]);
- cell->unsetPort("\\I0");
- cell->unsetPort("\\I1");
- cell->unsetPort("\\I2");
- cell->unsetPort("\\I3");
- cell->unsetPort("\\O");
-
- cell->check();
- }
- }
-}
-
-struct Ice40UnlutPass : public Pass {
- Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: perform simple optimizations") { }
- void help() YS_OVERRIDE
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" ice40_unlut [options] [selection]\n");
- log("\n");
- log("This command transforms all SB_LUT4 cells to generic $lut cells.\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
- {
- log_header(design, "Executing ICE40_UNLUT pass (convert SB_LUT4 to $lut).\n");
- log_push();
-
- 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_unlut(module);
- }
-} Ice40UnlutPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index bb96d66d1..c6de81bd9 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -37,6 +37,10 @@ struct SynthIce40Pass : public ScriptPass
log("\n");
log("This command runs synthesis for iCE40 FPGAs.\n");
log("\n");
+ log(" -device < hx | lp | u >\n");
+ log(" relevant only for '-abc9' flow, optimise timing for the specified device.\n");
+ log(" default: hx\n");
+ log("\n");
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
@@ -63,9 +67,6 @@ struct SynthIce40Pass : public ScriptPass
log(" -retime\n");
log(" run 'abc' with -dff option\n");
log("\n");
- log(" -relut\n");
- log(" combine LUTs after synthesis\n");
- log("\n");
log(" -nocarry\n");
log(" do not use SB_CARRY cells in output netlist\n");
log("\n");
@@ -74,7 +75,7 @@ struct SynthIce40Pass : public ScriptPass
log("\n");
log(" -dffe_min_ce_use <min_ce_use>\n");
log(" do not use SB_DFFE* cells if the resulting CE line would go to less\n");
- log(" than min_ce_use SB_DFFE*in output netlist\n");
+ log(" than min_ce_use SB_DFFE* in output netlist\n");
log("\n");
log(" -nobram\n");
log(" do not use SB_RAM40_4K* cells in output netlist\n");
@@ -92,14 +93,17 @@ struct SynthIce40Pass : public ScriptPass
log(" generate an output netlist (and BLIF file) suitable for VPR\n");
log(" (this feature is experimental and incomplete)\n");
log("\n");
+ log(" -abc9\n");
+ log(" use new ABC9 flow (EXPERIMENTAL)\n");
+ log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
- string top_opt, blif_file, edif_file, json_file;
- bool nocarry, nodffe, nobram, dsp, flatten, retime, relut, noabc, abc2, vpr;
+ string top_opt, blif_file, edif_file, json_file, abc, device_opt;
+ bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr;
int min_ce_use;
void clear_flags() YS_OVERRIDE
@@ -115,10 +119,11 @@ struct SynthIce40Pass : public ScriptPass
dsp = false;
flatten = true;
retime = false;
- relut = false;
noabc = false;
abc2 = false;
vpr = false;
+ abc = "abc";
+ device_opt = "hx";
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -166,7 +171,7 @@ struct SynthIce40Pass : public ScriptPass
continue;
}
if (args[argidx] == "-relut") {
- relut = true;
+ // removed, opt_lut is always run
continue;
}
if (args[argidx] == "-nocarry") {
@@ -178,7 +183,7 @@ struct SynthIce40Pass : public ScriptPass
continue;
}
if (args[argidx] == "-dffe_min_ce_use" && argidx+1 < args.size()) {
- min_ce_use = std::stoi(args[++argidx]);
+ min_ce_use = atoi(args[++argidx].c_str());
continue;
}
if (args[argidx] == "-nobram") {
@@ -201,12 +206,25 @@ struct SynthIce40Pass : public ScriptPass
vpr = true;
continue;
}
+ if (args[argidx] == "-abc9") {
+ abc = "abc9";
+ continue;
+ }
+ if (args[argidx] == "-device" && argidx+1 < args.size()) {
+ device_opt = args[++argidx];
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
+ if (device_opt != "hx" && device_opt != "lp" && device_opt !="u")
+ log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str());
+
+ if (abc == "abc9" && retime)
+ log_cmd_error("-retime option not currently compatible with -abc9!\n");
log_header(design, "Executing SYNTH_ICE40 pass.\n");
log_push();
@@ -220,7 +238,7 @@ struct SynthIce40Pass : public ScriptPass
{
if (check_label("begin"))
{
- run("read_verilog -lib +/ice40/cells_sim.v");
+ run("read_verilog -icells -lib +/ice40/cells_sim.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
run("proc");
}
@@ -257,14 +275,14 @@ struct SynthIce40Pass : public ScriptPass
run("opt_clean");
}
- if (!nobram && check_label("bram", "(skip if -nobram)"))
+ if (!nobram && check_label("map_bram", "(skip if -nobram)"))
{
run("memory_bram -rules +/ice40/brams.txt");
run("techmap -map +/ice40/brams_map.v");
run("ice40_braminit");
}
- if (check_label("map"))
+ if (check_label("map_ffram"))
{
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
@@ -275,10 +293,12 @@ struct SynthIce40Pass : public ScriptPass
{
if (nocarry)
run("techmap");
- else
+ else {
+ run("ice40_wrapcarry");
run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
+ }
if (retime || help_mode)
- run("abc -dff", "(only if -retime)");
+ run(abc + " -dff", "(only if -retime)");
run("ice40_opt");
}
@@ -291,7 +311,7 @@ struct SynthIce40Pass : public ScriptPass
run("opt_merge");
run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
}
- run("techmap -D NO_LUT -map +/ice40/cells_map.v");
+ run("techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
run("ice40_ffinit");
@@ -302,7 +322,7 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("map_luts"))
{
if (abc2 || help_mode) {
- run("abc", " (only if -abc2)");
+ run(abc, " (only if -abc2)");
run("ice40_opt", "(only if -abc2)");
}
run("techmap -map +/ice40/latches_map.v");
@@ -311,13 +331,22 @@ struct SynthIce40Pass : public ScriptPass
run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)");
}
if (!noabc) {
- run("abc -dress -lut 4", "(skip if -noabc)");
+ if (abc == "abc9") {
+ int wire_delay;
+ if (device_opt == "lp")
+ wire_delay = 400;
+ else if (device_opt == "u")
+ wire_delay = 750;
+ else
+ wire_delay = 250;
+ run(abc + stringf(" -W %d -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
+ }
+ else
+ run(abc + " -dress -lut 4", "(skip if -noabc)");
}
+ run("techmap -D NO_LUT -map +/ice40/cells_map.v");
run("clean");
- if (relut || help_mode) {
- run("ice40_unlut", " (only if -relut)");
- run("opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3", "(only if -relut)");
- }
+ run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");
}
if (check_label("map_cells"))
diff --git a/techlibs/ice40/tests/test_arith.ys b/techlibs/ice40/tests/test_arith.ys
index 160c767fb..ddb80b700 100644
--- a/techlibs/ice40/tests/test_arith.ys
+++ b/techlibs/ice40/tests/test_arith.ys
@@ -1,6 +1,5 @@
read_verilog test_arith.v
synth_ice40
-techmap -map ../cells_sim.v
rename test gate
read_verilog test_arith.v
@@ -8,3 +7,11 @@ rename test gold
miter -equiv -flatten -make_outputs gold gate miter
sat -verify -prove trigger 0 -show-ports miter
+
+synth_ice40 -top gate
+
+read_verilog test_arith.v
+rename test gold
+
+miter -equiv -flatten -make_outputs gold gate miter
+sat -verify -prove trigger 0 -show-ports miter
diff --git a/techlibs/ice40/tests/test_dsp_model.sh b/techlibs/ice40/tests/test_dsp_model.sh
index 1bc0cc688..1e564d1b2 100644
--- a/techlibs/ice40/tests/test_dsp_model.sh
+++ b/techlibs/ice40/tests/test_dsp_model.sh
@@ -1,10 +1,15 @@
#!/bin/bash
set -ex
sed 's/SB_MAC16/SB_MAC16_UUT/; /SB_MAC16_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp_model_uut.v
-cat /opt/lscc/iCEcube2.2017.01/verilog/sb_ice_syn.v > test_dsp_model_ref.v
+if [ ! -f "test_dsp_model_ref.v" ]; then
+ cat /opt/lscc/iCEcube2.2017.01/verilog/sb_ice_syn.v > test_dsp_model_ref.v
+fi
for tb in testbench \
testbench_comb_8x8_A testbench_comb_8x8_B testbench_comb_16x16 \
- testbench_seq_16x16_A testbench_seq_16x16_B
+ testbench_seq_16x16_A testbench_seq_16x16_B \
+ testbench_comb_8x8_A_signedA testbench_comb_8x8_A_signedB testbench_comb_8x8_A_signedAB \
+ testbench_comb_8x8_B_signedA testbench_comb_8x8_B_signedB testbench_comb_8x8_B_signedAB \
+ testbench_comb_16x16_signedA testbench_comb_16x16_signedB testbench_comb_16x16_signedAB
do
iverilog -s $tb -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v
vvp -N ./test_dsp_model
diff --git a/techlibs/ice40/tests/test_dsp_model.v b/techlibs/ice40/tests/test_dsp_model.v
index 594bd4ad3..f4f6858f0 100644
--- a/techlibs/ice40/tests/test_dsp_model.v
+++ b/techlibs/ice40/tests/test_dsp_model.v
@@ -241,6 +241,81 @@ module testbench_comb_8x8_A;
) testbench ();
endmodule
+module testbench_comb_8x8_A_signedA;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (2), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (0), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (2), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (0), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (1),
+ .B_SIGNED (0)
+ ) testbench ();
+endmodule
+
+module testbench_comb_8x8_A_signedB;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (2), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (0), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (2), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (0), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (0),
+ .B_SIGNED (1)
+ ) testbench ();
+endmodule
+
+module testbench_comb_8x8_A_signedAB;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (2), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (0), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (2), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (0), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (1),
+ .B_SIGNED (1)
+ ) testbench ();
+endmodule
+
module testbench_comb_8x8_B;
testbench #(
.NEG_TRIGGER (0),
@@ -266,6 +341,81 @@ module testbench_comb_8x8_B;
) testbench ();
endmodule
+module testbench_comb_8x8_B_signedA;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (1), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (1), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (1),
+ .B_SIGNED (0)
+ ) testbench ();
+endmodule
+
+module testbench_comb_8x8_B_signedB;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (1), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (1), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (0),
+ .B_SIGNED (1)
+ ) testbench ();
+endmodule
+
+module testbench_comb_8x8_B_signedAB;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (1), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (1), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (1),
+ .B_SIGNED (1)
+ ) testbench ();
+endmodule
+
module testbench_comb_16x16;
testbench #(
.NEG_TRIGGER (0),
@@ -291,6 +441,81 @@ module testbench_comb_16x16;
) testbench ();
endmodule
+module testbench_comb_16x16_signedA;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (1),
+ .B_SIGNED (0)
+ ) testbench ();
+endmodule
+
+module testbench_comb_16x16_signedB;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (0),
+ .B_SIGNED (1)
+ ) testbench ();
+endmodule
+
+module testbench_comb_16x16_signedAB;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (1),
+ .B_SIGNED (1)
+ ) testbench ();
+endmodule
+
module testbench_seq_16x16_A;
testbench #(
.NEG_TRIGGER (0),
diff --git a/techlibs/intel/Makefile.inc b/techlibs/intel/Makefile.inc
index ec7cea379..4e8f423c8 100644
--- a/techlibs/intel/Makefile.inc
+++ b/techlibs/intel/Makefile.inc
@@ -3,22 +3,12 @@ OBJS += techlibs/intel/synth_intel.o
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/m9k_bb.v))
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/altpll_bb.v))
-$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams.txt))
-$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map.v))
-$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/cells_sim.v))
-$(eval $(call add_share_file,share/intel/a10gx,techlibs/intel/a10gx/cells_sim.v))
-$(eval $(call add_share_file,share/intel/cyclonev,techlibs/intel/cyclonev/cells_sim.v))
-$(eval $(call add_share_file,share/intel/cyclone10,techlibs/intel/cyclone10/cells_sim.v))
-$(eval $(call add_share_file,share/intel/cycloneiv,techlibs/intel/cycloneiv/cells_sim.v))
-$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/cells_sim.v))
-$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/cells_map.v))
-$(eval $(call add_share_file,share/intel/a10gx,techlibs/intel/a10gx/cells_map.v))
-$(eval $(call add_share_file,share/intel/cyclonev,techlibs/intel/cyclonev/cells_map.v))
-$(eval $(call add_share_file,share/intel/cyclone10,techlibs/intel/cyclone10/cells_map.v))
-$(eval $(call add_share_file,share/intel/cycloneiv,techlibs/intel/cycloneiv/cells_map.v))
-$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/cells_map.v))
-#$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/arith_map.v))
-#$(eval $(call add_share_file,share/intel/a10gx,techlibs/intel/a10gx/arith_map.v))
-#$(eval $(call add_share_file,share/intel/cycloneiv,techlibs/intel/cycloneiv/arith_map.v))
+$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k.txt))
+$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v))
+
+# Add the cell models and mappings for the VQM backend
+families := max10 a10gx cyclonev cyclone10 cycloneiv cycloneive
+$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v)))
+$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.v)))
#$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v))
diff --git a/techlibs/intel/common/brams.txt b/techlibs/intel/common/brams_m9k.txt
index 3bf21afc9..3bf21afc9 100644
--- a/techlibs/intel/common/brams.txt
+++ b/techlibs/intel/common/brams_m9k.txt
diff --git a/techlibs/intel/common/brams_map.v b/techlibs/intel/common/brams_map_m9k.v
index d0f07c1de..d0f07c1de 100644
--- a/techlibs/intel/common/brams_map.v
+++ b/techlibs/intel/common/brams_map_m9k.v
diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc
index 639cba2c2..e5dc1adc7 100644
--- a/techlibs/intel/synth_intel.cc
+++ b/techlibs/intel/synth_intel.cc
@@ -38,9 +38,9 @@ struct SynthIntelPass : public ScriptPass {
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(" MAX10 is the default target if no family argument specified.\n");
log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n");
- log(" Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument.\n");
+ log(" Cyclone V and Arria 10 GX devices are experimental.\n");
log("\n");
log(" -top <module>\n");
log(" use the specified module as top module (default='top')\n");
@@ -48,6 +48,8 @@ struct SynthIntelPass : public ScriptPass {
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(" Note that this backend has not been tested and is likely incompatible\n");
+ log(" with recent versions of Quartus.\n");
log("\n");
log(" -vpr <file>\n");
log(" write BLIF files for VPR flow experiments. The synthesized BLIF output file is not\n");
@@ -59,11 +61,11 @@ struct SynthIntelPass : 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(" -noiopads\n");
- log(" do not use altsyncram cells in output netlist\n");
+ log(" -iopads\n");
+ log(" use IO pad cells in output netlist\n");
log("\n");
log(" -nobram\n");
- log(" do not use altsyncram cells in output netlist\n");
+ log(" do not use block RAM cells in output netlist\n");
log("\n");
log(" -noflatten\n");
log(" do not flatten design before synthesis\n");
@@ -77,7 +79,7 @@ struct SynthIntelPass : public ScriptPass {
}
string top_opt, family_opt, vout_file, blif_file;
- bool retime, flatten, nobram, noiopads;
+ bool retime, flatten, nobram, iopads;
void clear_flags() YS_OVERRIDE
{
@@ -88,7 +90,7 @@ struct SynthIntelPass : public ScriptPass {
retime = false;
flatten = true;
nobram = false;
- noiopads = false;
+ iopads = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -108,6 +110,7 @@ struct SynthIntelPass : public ScriptPass {
}
if (args[argidx] == "-vqm" && argidx + 1 < args.size()) {
vout_file = args[++argidx];
+ log_warning("The Quartus backend has not been tested recently and is likely incompatible with modern versions of Quartus.\n");
continue;
}
if (args[argidx] == "-vpr" && argidx + 1 < args.size()) {
@@ -122,8 +125,8 @@ struct SynthIntelPass : public ScriptPass {
run_to = args[argidx].substr(pos + 1);
continue;
}
- if (args[argidx] == "-noiopads") {
- noiopads = true;
+ if (args[argidx] == "-iopads") {
+ iopads = true;
continue;
}
if (args[argidx] == "-nobram") {
@@ -144,9 +147,13 @@ struct SynthIntelPass : public ScriptPass {
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 (family_opt != "max10" &&
+ family_opt != "a10gx" &&
+ family_opt != "cyclonev" &&
+ family_opt != "cycloneiv" &&
+ family_opt != "cycloneive" &&
+ family_opt != "cyclone10")
+ log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str());
log_header(design, "Executing SYNTH_INTEL pass.\n");
log_push();
@@ -159,18 +166,9 @@ struct SynthIntelPass : public ScriptPass {
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");
+ if (check_label("family"))
+ run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str()));
+
// Misc and common cells
run("read_verilog -sv -lib +/intel/common/m9k_bb.v");
run("read_verilog -sv -lib +/intel/common/altpll_bb.v");
@@ -188,12 +186,19 @@ struct SynthIntelPass : public ScriptPass {
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("map_bram", "(skip if -nobram)")) {
+ if (family_opt == "cycloneiv" ||
+ family_opt == "cycloneive" ||
+ family_opt == "max10" ||
+ help_mode) {
+ run("memory_bram -rules +/intel/common/brams_m9k.txt", "(if applicable for family)");
+ run("techmap -map +/intel/common/brams_map_m9k.v", "(if applicable for family)");
+ } else {
+ log_warning("BRAM mapping is not currently supported for %s.\n", family_opt.c_str());
+ }
}
- if (check_label("fine")) {
+ if (check_label("map_ffram")) {
run("opt -fast -mux_undef -undriven -fine -full");
run("memory_map");
run("opt -undriven -fine");
@@ -217,20 +222,9 @@ struct SynthIntelPass : public ScriptPass {
}
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");
+ if (iopads || help_mode)
+ run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(if -iopads)");
+ run(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str()));
run("dffinit -highlow -ff dffeas q power_up");
run("clean -purge");
}
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index d68f03bb4..2b1af289c 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -5,6 +5,8 @@ GENFILES += techlibs/xilinx/brams_init_36.vh
GENFILES += techlibs/xilinx/brams_init_32.vh
GENFILES += techlibs/xilinx/brams_init_18.vh
GENFILES += techlibs/xilinx/brams_init_16.vh
+GENFILES += techlibs/xilinx/brams_init_9.vh
+GENFILES += techlibs/xilinx/brams_init_8.vh
EXTRA_OBJS += techlibs/xilinx/brams_init.mk
.SECONDARY: techlibs/xilinx/brams_init.mk
@@ -18,21 +20,33 @@ techlibs/xilinx/brams_init_36.vh: techlibs/xilinx/brams_init.mk
techlibs/xilinx/brams_init_32.vh: techlibs/xilinx/brams_init.mk
techlibs/xilinx/brams_init_18.vh: techlibs/xilinx/brams_init.mk
techlibs/xilinx/brams_init_16.vh: techlibs/xilinx/brams_init.mk
+techlibs/xilinx/brams_init_9.vh: techlibs/xilinx/brams_init.mk
+techlibs/xilinx/brams_init_8.vh: techlibs/xilinx/brams_init.mk
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_sim.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_xtra.v))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams.txt))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_map.v))
-$(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/xc6s_brams.txt))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams_bb.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams.txt))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_bb.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams.txt))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.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_share_file,share/xilinx,techlibs/xilinx/mux_map.v))
+
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.box))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7_nowide.lut))
$(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))
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_18.vh))
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_16.vh))
+$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_9.vh))
+$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_8.vh))
diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box
new file mode 100644
index 000000000..3789ff350
--- /dev/null
+++ b/techlibs/xilinx/abc_xc7.box
@@ -0,0 +1,58 @@
+# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf
+
+# NB: Inputs/Outputs must be ordered alphabetically
+# (with exceptions for carry in/out)
+
+# Average across F7[AB]MUX
+# Inputs: I0 I1 S0
+# Outputs: O
+F7MUX 1 1 3 1
+204 208 286
+
+# Inputs: I0 I1 S0
+# Outputs: O
+MUXF8 2 1 3 1
+104 94 273
+
+# Inputs: I0 I1 I2 I3 S0 S1
+# Outputs: O
+$__MUXF78 3 1 6 1
+294 297 311 317 390 273
+
+# CARRY4 + CARRY4_[ABCD]X
+# Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI
+# Outputs: O0 O1 O2 O3 CO0 CO1 CO2 CO3
+# (NB: carry chain input/output must be last
+# input/output and the entire bus has been
+# moved there overriding the otherwise
+# alphabetical ordering)
+CARRY4 4 1 10 8
+482 - - - - 223 - - - 222
+598 407 - - - 400 205 - - 334
+584 556 537 - - 523 558 226 - 239
+642 615 596 438 - 582 618 330 227 313
+536 379 - - - 340 - - - 271
+494 465 445 - - 433 469 - - 157
+592 540 520 356 - 512 548 292 - 228
+580 526 507 398 385 508 528 378 380 114
+
+# SLICEM/A6LUT
+# Inputs: A0 A1 A2 A3 A4 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 WCLK WE
+# Outputs: DPO SPO
+RAM32X1D 5 0 13 2
+- - - - - - 631 472 407 238 127 - -
+631 472 407 238 127 - - - - - - - -
+
+# SLICEM/A6LUT
+# Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE
+# Outputs: DPO SPO
+RAM64X1D 6 0 15 2
+- - - - - - - 642 631 472 407 238 127 - -
+642 631 472 407 238 127 - - - - - - - - -
+
+# SLICEM/A6LUT + F7[AB]MUX
+# Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE
+# Outputs: DPO SPO
+RAM128X1D 7 0 17 2
+- - - - - - - - 1009 998 839 774 605 494 450 - -
+1047 1036 877 812 643 532 478 - - - - - - - - - -
diff --git a/techlibs/xilinx/abc_xc7.lut b/techlibs/xilinx/abc_xc7.lut
new file mode 100644
index 000000000..bcbdec127
--- /dev/null
+++ b/techlibs/xilinx/abc_xc7.lut
@@ -0,0 +1,15 @@
+# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/timings/CLBLL_L.sdf
+# and https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/tile_type_CLBLL_L.json
+
+# K area delay
+1 1 127
+2 2 127 238
+3 3 127 238 407
+4 3 127 238 407 472
+5 3 127 238 407 472 631
+6 5 127 238 407 472 631 642
+ # (F7[AB]MUX.S + [AC]OUTMUX) / 2
+7 10 464 513 624 793 858 1017 1028
+ # F8MUX.S+BOUTMUX
+ # F8MUX.I0+F7MUX.S+BOUTMUX
+8 20 468 585 634 745 914 979 1138 1149
diff --git a/techlibs/xilinx/abc_xc7_nowide.lut b/techlibs/xilinx/abc_xc7_nowide.lut
new file mode 100644
index 000000000..fab48c879
--- /dev/null
+++ b/techlibs/xilinx/abc_xc7_nowide.lut
@@ -0,0 +1,10 @@
+# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/timings/CLBLL_L.sdf
+# and https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/tile_type_CLBLL_L.json
+
+# K area delay
+1 1 127
+2 2 127 238
+3 3 127 238 407
+4 3 127 238 407 472
+5 3 127 238 407 472 631
+6 5 127 238 407 472 631 642
diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v
index 09a5f07e8..5c848d4e6 100644
--- a/techlibs/xilinx/arith_map.v
+++ b/techlibs/xilinx/arith_map.v
@@ -180,7 +180,7 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
// First one
if (i == 0) begin
- CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_part
+ CARRY4 carry4_1st_part
(
.CYINIT(CI),
.CI (1'd0),
@@ -207,7 +207,7 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
// First one
if (i == 0) begin
- CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_full
+ CARRY4 carry4_1st_full
(
.CYINIT(CI),
.CI (1'd0),
diff --git a/techlibs/xilinx/brams_init.py b/techlibs/xilinx/brams_init.py
index d46a2b4f7..10057a0cb 100644
--- a/techlibs/xilinx/brams_init.py
+++ b/techlibs/xilinx/brams_init.py
@@ -1,5 +1,17 @@
#!/usr/bin/env python3
+with open("techlibs/xilinx/brams_init_9.vh", "w") as f:
+ for i in range(4):
+ init_snippets = [" INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)]
+ for k in range(4, 256, 4):
+ init_snippets[k] = "\n " + init_snippets[k]
+ print(".INITP_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
+ for i in range(32):
+ init_snippets = [" INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)]
+ for k in range(4, 32, 4):
+ init_snippets[k] = "\n " + init_snippets[k]
+ print(".INIT_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
+
with open("techlibs/xilinx/brams_init_18.vh", "w") as f:
for i in range(8):
init_snippets = [" INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)]
@@ -24,6 +36,10 @@ with open("techlibs/xilinx/brams_init_36.vh", "w") as f:
init_snippets[k] = "\n " + init_snippets[k]
print(".INIT_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
+with open("techlibs/xilinx/brams_init_8.vh", "w") as f:
+ for i in range(32):
+ print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f)
+
with open("techlibs/xilinx/brams_init_16.vh", "w") as f:
for i in range(64):
print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f)
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
index 40789ddbe..b8e5bafc7 100644
--- a/techlibs/xilinx/cells_map.v
+++ b/techlibs/xilinx/cells_map.v
@@ -2,6 +2,7 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * 2019 Eddie Hung <eddie@fpgeh.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
@@ -23,9 +24,9 @@ module _90_dff_nn0_to_np0 (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLA
(* 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
+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 _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 \$__SHREG_ (input C, input D, input E, output Q);
parameter DEPTH = 0;
@@ -55,7 +56,6 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
localparam [DEPTH-1:0] INIT_R = brev(INIT);
parameter _TECHMAP_CONSTMSK_L_ = 0;
- parameter _TECHMAP_CONSTVAL_L_ = 0;
wire CE;
generate
@@ -88,69 +88,280 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
end else
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[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
+ else
+ \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S0(L[5]), .S1(L[6]), .O(Q));
end else
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[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
+ else
+ \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q));
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[ 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
+ else
+ \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q));
+ end
+ // For fixed length, if just 1 over a convenient value, decompose
+ else if (DEPTH <= 129 && &_TECHMAP_CONSTMSK_L_) begin
+ wire T;
+ \$__XILINX_SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(D), .L({32{1'b1}}), .E(E), .Q(T));
+ \$__XILINX_SHREG_ #(.DEPTH(1), .INIT(INIT[0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_last (.C(C), .D(T), .L(L), .E(E), .Q(Q));
end
- else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin
- // Handle cases where fixed-length depth is
- // just 1 over a convenient value
+ // For variable length, if just 1 over a convenient value, then bump up one more
+ else if (DEPTH < 129 && ~&_TECHMAP_CONSTMSK_L_)
\$__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));
+ else begin
+ localparam depth0 = 128;
+ localparam num_srl128 = DEPTH / depth0;
+ localparam depthN = DEPTH % depth0;
+ wire [num_srl128 + (depthN > 0 ? 1 : 0) - 1:0] T;
+ wire [num_srl128 + (depthN > 0 ? 1 : 0) :0] S;
+ assign S[0] = D;
+ genvar i;
+ for (i = 0; i < num_srl128; i++)
+ \$__XILINX_SHREG_ #(.DEPTH(depth0), .INIT(INIT[DEPTH-1-i*depth0-:depth0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(S[i]), .L(L[$clog2(depth0)-1:0]), .E(E), .Q(T[i]), .SO(S[i+1]));
+
+ if (depthN > 0)
+ \$__XILINX_SHREG_ #(.DEPTH(depthN), .INIT(INIT[depthN-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_last (.C(C), .D(S[num_srl128]), .L(L[$clog2(depth0)-1:0]), .E(E), .Q(T[num_srl128]));
+
+ if (&_TECHMAP_CONSTMSK_L_)
+ assign Q = T[num_srl128 + (depthN > 0 ? 1 : 0) - 1];
+ else
+ assign Q = T[L[DEPTH-1:$clog2(depth0)]];
+ end
+ endgenerate
+endmodule
+
+`ifdef MIN_MUX_INPUTS
+module \$__XILINX_SHIFTX (A, B, Y);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ 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] Y;
+
+ parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0;
+ parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0;
+ parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0;
+ parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0;
+
+ function integer A_WIDTH_trimmed;
+ input integer start;
+ begin
+ A_WIDTH_trimmed = start;
+ while (A_WIDTH_trimmed > 0 && _TECHMAP_CONSTMSK_A_[A_WIDTH_trimmed-1] && _TECHMAP_CONSTVAL_A_[A_WIDTH_trimmed-1] === 1'bx)
+ A_WIDTH_trimmed = A_WIDTH_trimmed - 1;
+ end
+ endfunction
+
+ generate
+ genvar i, j;
+ // Bit-blast
+ if (Y_WIDTH > 1) begin
+ for (i = 0; i < Y_WIDTH; i++)
+ \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i]));
+ end
+ // If the LSB of B is constant zero (and Y_WIDTH is 1) then
+ // we can optimise by removing every other entry from A
+ // and popping the constant zero from B
+ else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin
+ wire [(A_WIDTH+1)/2-1:0] A_i;
+ for (i = 0; i < (A_WIDTH+1)/2; i++)
+ assign A_i[i] = A[i*2];
+ \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y));
+ end
+ // Trim off any leading 1'bx -es in A
+ else if (_TECHMAP_CONSTMSK_A_[A_WIDTH-1] && _TECHMAP_CONSTVAL_A_[A_WIDTH-1] === 1'bx) begin
+ localparam A_WIDTH_new = A_WIDTH_trimmed(A_WIDTH-1);
+ \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B), .Y(Y));
+ end
+ else if (A_WIDTH < `MIN_MUX_INPUTS) begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ else if (A_WIDTH == 2) begin
+ MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y));
+ end
+ else if (A_WIDTH <= 4) begin
+ wire [4-1:0] Ax;
+ if (A_WIDTH == 4)
+ assign Ax = A;
+ else
+ // Rather than extend with 1'bx which gets flattened to 1'b0
+ // causing the "don't care" status to get lost, extend with
+ // the same driver of F7B.I0 so that we can optimise F7B away
+ // later
+ assign Ax = {A[1], A};
+ \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y));
+ end
+ // Note that the following decompositions are 'backwards' in that
+ // the LSBs are placed on the hard resources, and the soft resources
+ // are used for MSBs.
+ // This has the effect of more effectively utilising the hard mux;
+ // take for example a 5:1 multiplexer, currently this would map as:
+ //
+ // A[0] \___ __ A[0] \__ __
+ // A[4] / \| \ whereas the more A[1] / \| \
+ // A[1] _____| | obvious mapping A[2] \___| |
+ // A[2] _____| |-- of MSBs to hard A[3] / | |__
+ // A[3]______| | resources would A[4] ____| |
+ // |__/ lead to: 1'bx ____| |
+ // || |__/
+ // || ||
+ // B[1:0] B[1:2]
+ //
+ // Expectation would be that the 'forward' mapping (right) is more
+ // area efficient (consider a 9:1 multiplexer using 2x4:1 multiplexers
+ // on its I0 and I1 inputs, and A[8] and 1'bx on its I2 and I3 inputs)
+ // but that the 'backwards' mapping (left) is more delay efficient
+ // since smaller LUTs are faster than wider ones.
+ else if (A_WIDTH <= 8) begin
+ wire [8-1:0] Ax = {{{8-A_WIDTH}{1'bx}}, A};
+ wire T0 = B[2] ? Ax[4] : Ax[0];
+ wire T1 = B[2] ? Ax[5] : Ax[1];
+ wire T2 = B[2] ? Ax[6] : Ax[2];
+ wire T3 = B[2] ? Ax[7] : Ax[3];
+ \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y));
+ end
+ else if (A_WIDTH <= 16) begin
+ wire [16-1:0] Ax = {{{16-A_WIDTH}{1'bx}}, A};
+ wire T0 = B[2] ? B[3] ? Ax[12] : Ax[4]
+ : B[3] ? Ax[ 8] : Ax[0];
+ wire T1 = B[2] ? B[3] ? Ax[13] : Ax[5]
+ : B[3] ? Ax[ 9] : Ax[1];
+ wire T2 = B[2] ? B[3] ? Ax[14] : Ax[6]
+ : B[3] ? Ax[10] : Ax[2];
+ wire T3 = B[2] ? B[3] ? Ax[15] : Ax[7]
+ : B[3] ? Ax[11] : Ax[3];
+ \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y));
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;
+ localparam num_mux16 = (A_WIDTH+15) / 16;
+ localparam clog2_num_mux16 = $clog2(num_mux16);
+ wire [num_mux16-1:0] T;
+ wire [num_mux16*16-1:0] Ax = {{(num_mux16*16-A_WIDTH){1'bx}}, A};
+ for (i = 0; i < num_mux16; i++)
+ \$__XILINX_SHIFTX #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(16),
+ .B_WIDTH(4),
+ .Y_WIDTH(Y_WIDTH)
+ ) fpga_mux (
+ .A(Ax[i*16+:16]),
+ .B(B[3:0]),
+ .Y(T[i])
+ );
+ \$__XILINX_SHIFTX #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(num_mux16),
+ .B_WIDTH(clog2_num_mux16),
+ .Y_WIDTH(Y_WIDTH)
+ ) _TECHMAP_REPLACE_ (
+ .A(T),
+ .B(B[B_WIDTH-1-:clog2_num_mux16]),
+ .Y(Y));
end
endgenerate
endmodule
-`ifndef SRL_ONLY
+(* techmap_celltype = "$__XILINX_SHIFTX" *)
+module _90__XILINX_SHIFTX (A, B, Y);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ 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] Y;
+
+ \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
+endmodule
+
+module \$_MUX_ (A, B, S, Y);
+ input A, B, S;
+ output Y;
+ generate
+ if (`MIN_MUX_INPUTS == 2)
+ \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(2), .B_WIDTH(1), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({B,A}), .B(S), .Y(Y));
+ else
+ wire _TECHMAP_FAIL_ = 1;
+ endgenerate
+endmodule
+
+module \$_MUX4_ (A, B, C, D, S, T, Y);
+ input A, B, C, D, S, T;
+ output Y;
+ \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({D,C,B,A}), .B({T,S}), .Y(Y));
+endmodule
+
+module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y);
+ input A, B, C, D, E, F, G, H, S, T, U;
+ output Y;
+ \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y));
+endmodule
+
+module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y);
+ input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V;
+ output Y;
+ \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y));
+endmodule
+`endif
+
+`ifndef _ABC
+module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1);
+ output O;
+ input I0, I1, I2, I3, S0, S1;
+ wire T0, T1;
+ parameter _TECHMAP_BITS_CONNMAP_ = 0;
+ parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0;
+ parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0;
+ parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0;
+ parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0;
+ parameter _TECHMAP_CONSTMSK_S0_ = 0;
+ parameter _TECHMAP_CONSTVAL_S0_ = 0;
+ parameter _TECHMAP_CONSTMSK_S1_ = 0;
+ parameter _TECHMAP_CONSTVAL_S1_ = 0;
+ if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1)
+ assign T0 = I1;
+ else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_)
+ assign T0 = I0;
+ else
+ MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0));
+ if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1)
+ assign T1 = I3;
+ else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)
+ assign T1 = I2;
+ else
+ MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1));
+ if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1)
+ assign O = T1;
+ else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_))
+ assign O = T0;
+ else
+ MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O));
+endmodule
`endif
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index 3a4540b83..3ad96d7fb 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -159,19 +159,38 @@ module MUXCY(output O, input CI, DI, S);
assign O = S ? CI : DI;
endmodule
+(* abc_box_id = 1, lib_whitebox *)
module MUXF7(output O, input I0, I1, S);
assign O = S ? I1 : I0;
endmodule
+(* abc_box_id = 2, lib_whitebox *)
module MUXF8(output O, input I0, I1, S);
assign O = S ? I1 : I0;
endmodule
+`ifdef _ABC
+(* abc_box_id = 3, lib_whitebox *)
+module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1);
+ assign O = S1 ? (S0 ? I3 : I2)
+ : (S0 ? I1 : I0);
+endmodule
+`endif
+
module XORCY(output O, input CI, LI);
assign O = CI ^ LI;
endmodule
-module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
+(* abc_box_id = 4, lib_whitebox *)
+module CARRY4(
+ (* abc_carry *)
+ output [3:0] CO,
+ output [3:0] O,
+ (* abc_carry *)
+ input CI,
+ input CYINIT,
+ input [3:0] DI, S
+);
assign O = S ^ {CO[2:0], CI | CYINIT};
assign CO[0] = S[0] ? CI | CYINIT : DI[0];
assign CO[1] = S[1] ? CO[0] : DI[1];
@@ -215,7 +234,7 @@ module FDRE (output reg Q, input C, CE, D, R);
endmodule
module FDSE (output reg Q, input C, CE, D, S);
- parameter [0:0] INIT = 1'b0;
+ parameter [0:0] INIT = 1'b1;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_S_INVERTED = 1'b0;
@@ -241,7 +260,7 @@ module FDCE (output reg Q, input C, CE, D, CLR);
endmodule
module FDPE (output reg Q, input C, CE, D, PRE);
- parameter [0:0] INIT = 1'b0;
+ parameter [0:0] INIT = 1'b1;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_PRE_INVERTED = 1'b0;
@@ -278,9 +297,36 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE);
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
endmodule
+(* abc_box_id = 5 *)
+module RAM32X1D (
+ output DPO, SPO,
+ (* abc_scc_break *)
+ input D,
+ input WCLK,
+ (* abc_scc_break *)
+ input WE,
+ input A0, A1, A2, A3, A4,
+ input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
+);
+ parameter INIT = 32'h0;
+ parameter IS_WCLK_INVERTED = 1'b0;
+ wire [4:0] a = {A4, A3, A2, A1, A0};
+ wire [4:0] dpra = {DPRA4, DPRA3, DPRA2, DPRA1, DPRA0};
+ reg [31:0] mem = INIT;
+ assign SPO = mem[a];
+ assign DPO = mem[dpra];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk) if (WE) mem[a] <= D;
+endmodule
+
+(* abc_box_id = 6 *)
module RAM64X1D (
output DPO, SPO,
- input D, WCLK, WE,
+ (* abc_scc_break *)
+ input D,
+ input WCLK,
+ (* abc_scc_break *)
+ input WE,
input A0, A1, A2, A3, A4, A5,
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
);
@@ -295,9 +341,14 @@ module RAM64X1D (
always @(posedge clk) if (WE) mem[a] <= D;
endmodule
+(* abc_box_id = 7 *)
module RAM128X1D (
output DPO, SPO,
- input D, WCLK, WE,
+ (* abc_scc_break *)
+ input D,
+ input WCLK,
+ (* abc_scc_break *)
+ input WE,
input [6:0] A, DPRA
);
parameter INIT = 128'h0;
diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh
index 8e39b440d..53b528820 100644
--- a/techlibs/xilinx/cells_xtra.sh
+++ b/techlibs/xilinx/cells_xtra.sh
@@ -116,16 +116,16 @@ function xtract_cell_decl()
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
- xtract_cell_decl RAM32X1D
+ #xtract_cell_decl RAM32X1D
xtract_cell_decl RAM32X1S
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
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index fbcc74682..15fa1b63a 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -3655,17 +3655,6 @@ 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;
@@ -3705,13 +3694,6 @@ module RAM32M (...);
input WE;
endmodule
-module RAM32X1D (...);
- parameter [31:0] INIT = 32'h00000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output DPO, SPO;
- input A0, A1, A2, A3, A4, D, DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, WCLK, WE;
-endmodule
-
module RAM32X1S (...);
parameter [31:0] INIT = 32'h00000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
@@ -3756,13 +3738,6 @@ 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;
diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v
index 13beaa6ae..4571f6d5c 100644
--- a/techlibs/xilinx/ff_map.v
+++ b/techlibs/xilinx/ff_map.v
@@ -33,10 +33,10 @@ module \$_DFF_NP0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPL
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
+module \$_DFF_NN1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|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_1 #(.INIT(|1)) _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(|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(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule
`endif
diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v
index d07c59dee..13d3c3268 100644
--- a/techlibs/xilinx/lut_map.v
+++ b/techlibs/xilinx/lut_map.v
@@ -29,61 +29,86 @@ module \$lut (A, Y);
input [WIDTH-1:0] A;
output Y;
+ // Need to swap input ordering, and fix init accordingly,
+ // to match ABC's expectation of LUT inputs in non-decreasing
+ // delay order
+ function [WIDTH-1:0] permute_index;
+ input [WIDTH-1:0] i;
+ integer j;
+ begin
+ permute_index = 0;
+ for (j = 0; j < WIDTH; j = j + 1)
+ permute_index[WIDTH-1 - j] = i[j];
+ end
+ endfunction
+
+ function [2**WIDTH-1:0] permute_init;
+ input [2**WIDTH-1:0] orig;
+ integer i;
+ begin
+ permute_init = 0;
+ for (i = 0; i < 2**WIDTH; i = i + 1)
+ permute_init[i] = orig[permute_index(i)];
+ end
+ endfunction
+
+ parameter [2**WIDTH-1:0] P_LUT = permute_init(LUT);
+
generate
if (WIDTH == 1) begin
- LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ LUT1 #(.INIT(P_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]));
+ LUT2 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[1]), .I1(A[0]));
end else
if (WIDTH == 3) begin
- LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]));
+ LUT3 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[2]), .I1(A[1]), .I2(A[0]));
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]));
+ LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[3]), .I1(A[2]), .I2(A[1]),
+ .I3(A[0]));
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]));
+ LUT5 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[4]), .I1(A[3]), .I2(A[2]),
+ .I3(A[1]), .I4(A[0]));
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]));
+ LUT6 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[5]), .I1(A[4]), .I2(A[3]),
+ .I3(A[2]), .I4(A[1]), .I5(A[0]));
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]));
+ LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0),
+ .I0(A[6]), .I1(A[5]), .I2(A[4]),
+ .I3(A[3]), .I4(A[2]), .I5(A[1]));
+ LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1),
+ .I0(A[6]), .I1(A[5]), .I2(A[4]),
+ .I3(A[3]), .I4(A[2]), .I5(A[1]));
+ MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[0]));
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]));
+ LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0),
+ .I0(A[7]), .I1(A[6]), .I2(A[5]),
+ .I3(A[4]), .I4(A[3]), .I5(A[2]));
+ LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1),
+ .I0(A[7]), .I1(A[6]), .I2(A[5]),
+ .I3(A[4]), .I4(A[3]), .I5(A[2]));
+ LUT6 #(.INIT(P_LUT[191:128])) fpga_lut_2 (.O(T2),
+ .I0(A[7]), .I1(A[6]), .I2(A[5]),
+ .I3(A[4]), .I4(A[3]), .I5(A[2]));
+ LUT6 #(.INIT(P_LUT[255:192])) fpga_lut_3 (.O(T3),
+ .I0(A[7]), .I1(A[6]), .I2(A[5]),
+ .I3(A[4]), .I4(A[3]), .I5(A[2]));
+ MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[1]));
+ MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[1]));
+ MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[0]));
end else begin
wire _TECHMAP_FAIL_ = 1;
end
diff --git a/techlibs/xilinx/drams.txt b/techlibs/xilinx/lutrams.txt
index 91632bcee..2613c206c 100644
--- a/techlibs/xilinx/drams.txt
+++ b/techlibs/xilinx/lutrams.txt
@@ -1,4 +1,17 @@
+bram $__XILINX_RAM32X1D
+ init 1
+ abits 5
+ dbits 1
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 1
+ transp 0 0
+ clocks 0 1
+ clkpol 0 2
+endbram
+
bram $__XILINX_RAM64X1D
init 1
abits 6
@@ -25,6 +38,13 @@ bram $__XILINX_RAM128X1D
clkpol 0 2
endbram
+match $__XILINX_RAM32X1D
+ min bits 3
+ min wports 1
+ make_outreg
+ or_next_if_better
+endmatch
+
match $__XILINX_RAM64X1D
min bits 5
min wports 1
diff --git a/techlibs/xilinx/drams_map.v b/techlibs/xilinx/lutrams_map.v
index 47476b592..77041ca86 100644
--- a/techlibs/xilinx/drams_map.v
+++ b/techlibs/xilinx/lutrams_map.v
@@ -1,4 +1,38 @@
+module \$__XILINX_RAM32X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter [31:0] INIT = 32'bx;
+ parameter CLKPOL2 = 1;
+ input CLK1;
+
+ input [4:0] A1ADDR;
+ output A1DATA;
+
+ input [4:0] B1ADDR;
+ input B1DATA;
+ input B1EN;
+
+ RAM32X1D #(
+ .INIT(INIT),
+ .IS_WCLK_INVERTED(!CLKPOL2)
+ ) _TECHMAP_REPLACE_ (
+ .DPRA0(A1ADDR[0]),
+ .DPRA1(A1ADDR[1]),
+ .DPRA2(A1ADDR[2]),
+ .DPRA3(A1ADDR[3]),
+ .DPRA4(A1ADDR[4]),
+ .DPO(A1DATA),
+
+ .A0(B1ADDR[0]),
+ .A1(B1ADDR[1]),
+ .A2(B1ADDR[2]),
+ .A3(B1ADDR[3]),
+ .A4(B1ADDR[4]),
+ .D(B1DATA),
+ .WCLK(CLK1),
+ .WE(B1EN)
+ );
+endmodule
+
module \$__XILINX_RAM64X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
parameter [63:0] INIT = 64'bx;
parameter CLKPOL2 = 1;
diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v
new file mode 100644
index 000000000..91aaf2118
--- /dev/null
+++ b/techlibs/xilinx/mux_map.v
@@ -0,0 +1,71 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * 2019 Eddie Hung <eddie@fpgeh.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.
+ *
+ */
+
+// The purpose of these mapping rules is to allow preserve all (sufficiently
+// wide) $shiftx cells during 'techmap' so that they can be mapped to hard
+// resources, rather than being bit-blasted to gates during 'techmap'
+// execution
+
+module \$shiftx (A, B, Y);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ 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] Y;
+
+ parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0;
+ parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0;
+
+ generate
+ if (B_SIGNED) begin
+ if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && (_TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0 || _TECHMAP_CONSTVAL_B_[B_WIDTH-1] === 1'bx))
+ // Optimisation to remove B_SIGNED if sign bit of B is constant-0
+ \$shiftx #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(0),
+ .A_WIDTH(A_WIDTH),
+ .B_WIDTH(B_WIDTH-1'd1),
+ .Y_WIDTH(Y_WIDTH)
+ ) _TECHMAP_REPLACE_ (
+ .A(A), .B(B[B_WIDTH-2:0]), .Y(Y)
+ );
+ else
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ else begin
+ if (((A_WIDTH + Y_WIDTH - 1) / Y_WIDTH) < `MIN_MUX_INPUTS)
+ wire _TECHMAP_FAIL_ = 1;
+ else
+ \$__XILINX_SHIFTX #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(A_WIDTH),
+ .B_WIDTH(B_WIDTH),
+ .Y_WIDTH(Y_WIDTH)
+ ) _TECHMAP_REPLACE_ (
+ .A(A), .B(B), .Y(Y)
+ );
+ end
+ endgenerate
+endmodule
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index a293081f1..87f4af8f7 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -2,6 +2,7 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * (C) 2019 Eddie Hung <eddie@fpgeh.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
@@ -25,6 +26,9 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+#define XC7_WIRE_DELAY 300 // Number with which ABC will map a 6-input gate
+ // to one LUT6 (instead of a LUT5 + LUT2)
+
struct SynthXilinxPass : public ScriptPass
{
SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
@@ -42,8 +46,9 @@ struct SynthXilinxPass : public ScriptPass
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
- log(" -arch {xcup|xcu|xc7|xc6s}\n");
+ log(" -family {xcup|xcu|xc7|xc6s}\n");
log(" run synthesis for the specified Xilinx architecture\n");
+ log(" generate the synthesis netlist for the specified family.\n");
log(" default: xc7\n");
log("\n");
log(" -edif <file>\n");
@@ -59,13 +64,24 @@ struct SynthXilinxPass : public ScriptPass
log(" (this feature is experimental and incomplete)\n");
log("\n");
log(" -nobram\n");
- log(" disable inference of block rams\n");
+ log(" do not use block RAM cells in output netlist\n");
log("\n");
- log(" -nodram\n");
- log(" disable inference of distributed rams\n");
+ log(" -nolutram\n");
+ log(" do not use distributed RAM cells in output netlist\n");
log("\n");
log(" -nosrl\n");
- log(" disable inference of shift registers\n");
+ log(" do not use distributed SRL cells in output netlist\n");
+ log("\n");
+ log(" -nocarry\n");
+ log(" do not use XORCY/MUXCY/CARRY4 cells in output netlist\n");
+ log("\n");
+ log(" -nowidelut\n");
+ log(" do not use MUXF[78] resources to implement LUTs larger than LUT6s\n");
+ log("\n");
+ log(" -widemux <int>\n");
+ log(" enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n");
+ log(" above this number of inputs (minimum value 2, recommended value >= 5).\n");
+ log(" default: 0 (no inference)\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
log(" only run the commands between the labels (see below). an empty\n");
@@ -78,27 +94,38 @@ struct SynthXilinxPass : public ScriptPass
log(" -retime\n");
log(" run 'abc' with -dff option\n");
log("\n");
+ log(" -abc9\n");
+ log(" use new ABC9 flow (EXPERIMENTAL)\n");
+ log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
- std::string top_opt, edif_file, blif_file, arch;
- bool flatten, retime, vpr, nobram, nodram, nosrl;
+ std::string top_opt, edif_file, blif_file, family;
+ bool flatten, retime, vpr, nobram, nolutram, nosrl, nocarry, nowidelut, abc9;
+ bool flatten_before_abc;
+ int widemux;
void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
edif_file.clear();
blif_file.clear();
+ family = "xc7";
flatten = false;
retime = false;
vpr = false;
+ nocarry = false;
nobram = false;
- nodram = false;
+ nolutram = false;
nosrl = false;
- arch = "xc7";
+ nocarry = false;
+ nowidelut = false;
+ abc9 = false;
+ flatten_before_abc = false;
+ widemux = 0;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -113,8 +140,8 @@ struct SynthXilinxPass : public ScriptPass
top_opt = "-top " + args[++argidx];
continue;
}
- if (args[argidx] == "-arch" && argidx+1 < args.size()) {
- arch = args[++argidx];
+ if ((args[argidx] == "-family" || args[argidx] == "-arch") && argidx+1 < args.size()) {
+ family = args[++argidx];
continue;
}
if (args[argidx] == "-edif" && argidx+1 < args.size()) {
@@ -137,36 +164,66 @@ struct SynthXilinxPass : public ScriptPass
flatten = true;
continue;
}
+ if (args[argidx] == "-flatten_before_abc") {
+ flatten_before_abc = true;
+ continue;
+ }
if (args[argidx] == "-retime") {
retime = true;
continue;
}
+ if (args[argidx] == "-nocarry") {
+ nocarry = true;
+ continue;
+ }
+ if (args[argidx] == "-nowidelut") {
+ nowidelut = true;
+ continue;
+ }
if (args[argidx] == "-vpr") {
vpr = true;
continue;
}
+ if (args[argidx] == "-nocarry") {
+ nocarry = true;
+ continue;
+ }
if (args[argidx] == "-nobram") {
nobram = true;
continue;
}
- if (args[argidx] == "-nodram") {
- nodram = true;
+ if (args[argidx] == "-nolutram" || /*deprecated alias*/ args[argidx] == "-nodram") {
+ nolutram = true;
continue;
}
if (args[argidx] == "-nosrl") {
nosrl = true;
continue;
}
+ if (args[argidx] == "-widemux" && argidx+1 < args.size()) {
+ widemux = atoi(args[++argidx].c_str());
+ continue;
+ }
+ if (args[argidx] == "-abc9") {
+ abc9 = 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 (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s")
+ log_cmd_error("Invalid Xilinx -family setting: '%s'.\n", family.c_str());
+
+ if (widemux != 0 && widemux < 2)
+ log_cmd_error("-widemux value must be 0 or >= 2.\n");
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
+ if (abc9 && retime)
+ log_cmd_error("-retime option not currently compatible with -abc9!\n");
+
log_header(design, "Executing SYNTH_XILINX pass.\n");
log_push();
@@ -179,83 +236,181 @@ struct SynthXilinxPass : public ScriptPass
{
if (check_label("begin")) {
if (vpr)
- run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
+ run("read_verilog -lib -icells -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
else
- run("read_verilog -lib +/xilinx/cells_sim.v");
+ run("read_verilog -lib -icells -D _ABC +/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')");
+ if (help_mode) {
+ run("read_verilog -lib +/xilinx/{family}_brams_bb.v");
+ } else if (family == "xc6s") {
+ run("read_verilog -lib +/xilinx/xc6s_brams_bb.v");
+ } else if (family == "xc7") {
+ run("read_verilog -lib +/xilinx/xc7_brams_bb.v");
+ }
run(stringf("hierarchy -check %s", top_opt.c_str()));
}
- if (check_label("flatten", "(with '-flatten' only)")) {
- if (flatten || help_mode) {
- run("proc");
- run("flatten");
+ if (check_label("coarse")) {
+ run("proc");
+ if (help_mode || flatten)
+ run("flatten", "(if -flatten)");
+ run("opt_expr");
+ run("opt_clean");
+ run("check");
+ run("opt");
+ if (help_mode)
+ run("wreduce [-keepdc]", "(option for '-widemux')");
+ else
+ run("wreduce" + std::string(widemux > 0 ? " -keepdc" : ""));
+ run("peepopt");
+ run("opt_clean");
+
+ if (widemux > 0 || help_mode)
+ run("muxpack", " ('-widemux' only)");
+
+ // shregmap -tech xilinx can cope with $shiftx and $mux
+ // cells for identifying variable-length shift registers,
+ // so attempt to convert $pmux-es to the former
+ // Also: wide multiplexer inference benefits from this too
+ if (!(nosrl && widemux == 0) || help_mode) {
+ run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')");
+ run("clean", " (skip if '-nosrl' and '-widemux=0')");
}
- }
- if (check_label("coarse")) {
- run("synth -run coarse");
+ run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6");
+ run("alumacc");
+ run("share");
+ run("opt");
+ run("fsm");
+ run("opt -fast");
+ run("memory -nomap");
+ run("opt_clean");
}
- 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("map_bram", "(skip if '-nobram')")) {
+ if (help_mode) {
+ run("memory_bram -rules +/xilinx/{family}_brams.txt");
+ run("techmap -map +/xilinx/{family}_brams_map.v");
+ } else if (!nobram) {
+ if (family == "xc6s") {
+ run("memory_bram -rules +/xilinx/xc6s_brams.txt");
+ run("techmap -map +/xilinx/xc6s_brams_map.v");
+ } else if (family == "xc7") {
+ run("memory_bram -rules +/xilinx/xc7_brams.txt");
+ run("techmap -map +/xilinx/xc7_brams_map.v");
+ } else {
+ log_warning("Block RAM inference not yet supported for family %s.\n", family.c_str());
+ }
}
}
- 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("map_lutram", "(skip if '-nolutram')")) {
+ if (!nolutram || help_mode) {
+ run("memory_bram -rules +/xilinx/lutrams.txt");
+ run("techmap -map +/xilinx/lutrams_map.v");
}
}
- 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");
+ if (check_label("map_ffram")) {
+ if (widemux > 0)
+ run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover
+ // performs less efficiently
+ else
+ run("opt -fast -full");
run("memory_map");
+ }
+
+ if (check_label("fine")) {
run("dffsr2dff");
run("dff2dffe");
+ if (help_mode) {
+ run("simplemap t:$mux", " ('-widemux' only)");
+ run("muxcover <internal options>, ('-widemux' only)");
+ }
+ else if (widemux > 0) {
+ run("simplemap t:$mux");
+ constexpr int cost_mux2 = 100;
+ std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2);
+ switch (widemux) {
+ case 2: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2+1, cost_mux2+2, cost_mux2+3); break;
+ case 3:
+ case 4: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-2, cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break;
+ case 5:
+ case 6:
+ case 7:
+ case 8: muxcover_args += stringf(" -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break;
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ default: muxcover_args += stringf(" -mux16=%d", cost_mux2*(widemux-1)-1); break;
+ }
+ run("muxcover " + muxcover_args);
+ }
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')");
+ 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");
-
+ std::string techmap_args = " -map +/techmap.v";
+ if (help_mode)
+ techmap_args += " [-map +/xilinx/mux_map.v]";
+ else if (widemux > 0)
+ techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", widemux);
+ if (help_mode)
+ techmap_args += " [-map +/xilinx/arith_map.v]";
+ else if (!nocarry) {
+ techmap_args += " -map +/xilinx/arith_map.v";
+ if (vpr)
+ techmap_args += " -D _EXPLICIT_CARRY";
+ else if (abc9)
+ techmap_args += " -D _CLB_CARRY";
+ }
+ run("techmap " + techmap_args);
run("opt -fast");
}
if (check_label("map_cells")) {
- run("techmap -map +/techmap.v -map +/xilinx/cells_map.v");
+ std::string techmap_args = "-map +/techmap.v -D _ABC -map +/xilinx/cells_map.v";
+ if (widemux > 0)
+ techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux);
+ run("techmap " + techmap_args);
run("clean");
}
if (check_label("map_luts")) {
+ run("opt_expr -mux_undef");
+ if (flatten_before_abc)
+ run("flatten");
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("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut', option for '-retime')");
+ else if (abc9) {
+ if (family != "xc7")
+ log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n");
+ if (nowidelut)
+ run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY));
+ else
+ run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY));
+ }
+ else {
+ if (nowidelut)
+ run("abc -luts 2:2,3,6:5" + string(retime ? " -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)
diff --git a/techlibs/xilinx/xc6s_brams.txt b/techlibs/xilinx/xc6s_brams.txt
new file mode 100644
index 000000000..17cd8e355
--- /dev/null
+++ b/techlibs/xilinx/xc6s_brams.txt
@@ -0,0 +1,84 @@
+
+bram $__XILINX_RAMB8BWER_SDP
+ init 1
+ abits 8
+ dbits 36
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 1 4
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__XILINX_RAMB16BWER_TDP
+ init 1
+ abits 9 @a9d36
+ dbits 36 @a9d36
+ abits 10 @a10d18
+ dbits 18 @a10d18
+ abits 11 @a11d9
+ dbits 9 @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 0 1
+ enable 1 4 @a9d36
+ enable 1 2 @a10d18
+ enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__XILINX_RAMB8BWER_TDP
+ init 1
+ abits 9 @a9d18
+ dbits 18 @a9d18
+ abits 10 @a10d9
+ dbits 9 @a10d9
+ abits 11 @a11d4
+ dbits 4 @a11d4
+ abits 12 @a12d2
+ dbits 2 @a12d2
+ abits 13 @a13d1
+ dbits 1 @a13d1
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 1 2 @a9d18
+ enable 1 1 @a10d9 @a11d4 @a12d2 @a13d1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__XILINX_RAMB8BWER_SDP
+ min bits 4096
+ min efficiency 5
+ shuffle_enable B
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__XILINX_RAMB16BWER_TDP
+ min bits 4096
+ min efficiency 5
+ shuffle_enable B
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__XILINX_RAMB8BWER_TDP
+ min bits 4096
+ min efficiency 5
+ shuffle_enable B
+ make_transp
+endmatch
+
diff --git a/techlibs/xilinx/xc6s_brams_bb.v b/techlibs/xilinx/xc6s_brams_bb.v
new file mode 100644
index 000000000..eb1a29579
--- /dev/null
+++ b/techlibs/xilinx/xc6s_brams_bb.v
@@ -0,0 +1,211 @@
+module RAMB8BWER (
+ input CLKAWRCLK,
+ input CLKBRDCLK,
+ input ENAWREN,
+ input ENBRDEN,
+ input REGCEA,
+ input REGCEBREGCE,
+ input RSTA,
+ input RSTBRST,
+
+ input [12:0] ADDRAWRADDR,
+ input [12:0] ADDRBRDADDR,
+ input [15:0] DIADI,
+ input [15:0] DIBDI,
+ input [1:0] DIPADIP,
+ input [1:0] DIPBDIP,
+ input [1:0] WEAWEL,
+ input [1:0] WEBWEU,
+
+ output [15:0] DOADO,
+ output [15:0] DOBDO,
+ output [1:0] DOPADOP,
+ output [1:0] DOPBDOP
+);
+ parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+ parameter RAM_MODE = "TDP";
+ parameter integer DOA_REG = 0;
+ parameter integer DOB_REG = 0;
+
+ parameter integer DATA_WIDTH_A = 0;
+ parameter integer DATA_WIDTH_B = 0;
+
+ parameter WRITE_MODE_A = "WRITE_FIRST";
+ parameter WRITE_MODE_B = "WRITE_FIRST";
+
+ parameter EN_RSTRAM_A = "TRUE";
+ parameter EN_RSTRAM_B = "TRUE";
+
+ parameter INIT_A = 18'h000000000;
+ parameter INIT_B = 18'h000000000;
+ parameter SRVAL_A = 18'h000000000;
+ parameter SRVAL_B = 18'h000000000;
+
+ parameter RST_PRIORITY_A = "CE";
+ parameter RST_PRIORITY_B = "CE";
+
+ parameter RSTTYPE = "SYNC";
+
+ parameter SIM_COLLISION_CHECK = "ALL";
+endmodule
+
+module RAMB16BWER (
+ input CLKA,
+ input CLKB,
+ input ENA,
+ input ENB,
+ input REGCEA,
+ input REGCEB,
+ input RSTA,
+ input RSTB,
+
+ input [13:0] ADDRA,
+ input [13:0] ADDRB,
+ input [31:0] DIA,
+ input [31:0] DIB,
+ input [3:0] DIPA,
+ input [3:0] DIPB,
+ input [3:0] WEA,
+ input [3:0] WEB,
+
+ output [31:0] DOA,
+ output [31:0] DOB,
+ output [3:0] DOPA,
+ output [3:0] DOPB
+);
+ parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+ parameter integer DOA_REG = 0;
+ parameter integer DOB_REG = 0;
+
+ parameter integer DATA_WIDTH_A = 0;
+ parameter integer DATA_WIDTH_B = 0;
+
+ parameter WRITE_MODE_A = "WRITE_FIRST";
+ parameter WRITE_MODE_B = "WRITE_FIRST";
+
+ parameter EN_RSTRAM_A = "TRUE";
+ parameter EN_RSTRAM_B = "TRUE";
+
+ parameter INIT_A = 36'h000000000;
+ parameter INIT_B = 36'h000000000;
+ parameter SRVAL_A = 36'h000000000;
+ parameter SRVAL_B = 36'h000000000;
+
+ parameter RST_PRIORITY_A = "CE";
+ parameter RST_PRIORITY_B = "CE";
+
+ parameter RSTTYPE = "SYNC";
+
+ parameter SIM_COLLISION_CHECK = "ALL";
+endmodule
+
diff --git a/techlibs/xilinx/xc6s_brams_map.v b/techlibs/xilinx/xc6s_brams_map.v
new file mode 100644
index 000000000..16fd15e74
--- /dev/null
+++ b/techlibs/xilinx/xc6s_brams_map.v
@@ -0,0 +1,255 @@
+module \$__XILINX_RAMB8BWER_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [9215:0] INIT = 9216'bx;
+
+ input CLK2;
+ input CLK3;
+
+ input [7:0] A1ADDR;
+ output [35:0] A1DATA;
+ input A1EN;
+
+ input [7:0] B1ADDR;
+ input [35:0] B1DATA;
+ input [3:0] B1EN;
+
+ wire [12:0] A1ADDR_13 = {A1ADDR, 5'b0};
+ wire [12:0] B1ADDR_13 = {B1ADDR, 5'b0};
+
+ wire [3:0] DIP, DOP;
+ wire [31:0] DI, DO;
+
+ assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
+ assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
+
+ RAMB8BWER #(
+ .RAM_MODE("SDP"),
+ .DATA_WIDTH_A(36),
+ .DATA_WIDTH_B(36),
+ .WRITE_MODE_A("READ_FIRST"),
+ .WRITE_MODE_B("READ_FIRST"),
+ `include "brams_init_9.vh"
+ ) _TECHMAP_REPLACE_ (
+ .DOBDO(DO[31:16]),
+ .DOADO(DO[15:0]),
+ .DOPBDOP(DOP[3:2]),
+ .DOPADOP(DOP[1:0]),
+ .DIBDI(DI[31:16]),
+ .DIADI(DI[15:0]),
+ .DIPBDIP(DIP[3:2]),
+ .DIPADIP(DIP[1:0]),
+ .WEBWEU(B1EN[3:2]),
+ .WEAWEL(B1EN[1:0]),
+
+ .ADDRAWRADDR(B1ADDR_13),
+ .CLKAWRCLK(CLK3 ^ !CLKPOL3),
+ .ENAWREN(|1),
+ .REGCEA(|0),
+ .RSTA(|0),
+
+ .ADDRBRDADDR(A1ADDR_13),
+ .CLKBRDCLK(CLK2 ^ !CLKPOL2),
+ .ENBRDEN(A1EN),
+ .REGCEBREGCE(|1),
+ .RSTBRST(|0)
+ );
+endmodule
+
+// ------------------------------------------------------------------------
+
+module \$__XILINX_RAMB16BWER_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 9;
+ parameter CFG_DBITS = 36;
+ parameter CFG_ENABLE_B = 4;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [18431:0] INIT = 18432'bx;
+
+ input CLK2;
+ input CLK3;
+
+ 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 [CFG_ENABLE_B-1:0] B1EN;
+
+ wire [13:0] A1ADDR_14 = A1ADDR << (14 - CFG_ABITS);
+ wire [13:0] B1ADDR_14 = B1ADDR << (14 - CFG_ABITS);
+ wire [3:0] B1EN_4 = {4{B1EN}};
+
+ wire [3:0] DIP, DOP;
+ wire [31:0] DI, DO;
+
+ wire [31:0] DOB;
+ wire [3:0] DOPB;
+
+ assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
+ assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
+
+ generate if (CFG_DBITS > 8) begin
+ RAMB16BWER #(
+ .DATA_WIDTH_A(CFG_DBITS),
+ .DATA_WIDTH_B(CFG_DBITS),
+ .WRITE_MODE_A("READ_FIRST"),
+ .WRITE_MODE_B("READ_FIRST"),
+ `include "brams_init_18.vh"
+ ) _TECHMAP_REPLACE_ (
+ .DIA(32'd0),
+ .DIPA(4'd0),
+ .DOA(DO[31:0]),
+ .DOPA(DOP[3:0]),
+ .ADDRA(A1ADDR_14),
+ .CLKA(CLK2 ^ !CLKPOL2),
+ .ENA(A1EN),
+ .REGCEA(|1),
+ .RSTA(|0),
+ .WEA(4'b0),
+
+ .DIB(DI),
+ .DIPB(DIP),
+ .DOB(DOB),
+ .DOPB(DOPB),
+ .ADDRB(B1ADDR_14),
+ .CLKB(CLK3 ^ !CLKPOL3),
+ .ENB(|1),
+ .REGCEB(|0),
+ .RSTB(|0),
+ .WEB(B1EN_4)
+ );
+ end else begin
+ RAMB16BWER #(
+ .DATA_WIDTH_A(CFG_DBITS),
+ .DATA_WIDTH_B(CFG_DBITS),
+ .WRITE_MODE_A("READ_FIRST"),
+ .WRITE_MODE_B("READ_FIRST"),
+ `include "brams_init_16.vh"
+ ) _TECHMAP_REPLACE_ (
+ .DIA(32'd0),
+ .DIPA(4'd0),
+ .DOA(DO[31:0]),
+ .DOPA(DOP[3:0]),
+ .ADDRA(A1ADDR_14),
+ .CLKA(CLK2 ^ !CLKPOL2),
+ .ENA(A1EN),
+ .REGCEA(|1),
+ .RSTA(|0),
+ .WEA(4'b0),
+
+ .DIB(DI),
+ .DIPB(DIP),
+ .DOB(DOB),
+ .DOPB(DOPB),
+ .ADDRB(B1ADDR_14),
+ .CLKB(CLK3 ^ !CLKPOL3),
+ .ENB(|1),
+ .REGCEB(|0),
+ .RSTB(|0),
+ .WEB(B1EN_4)
+ );
+ end endgenerate
+endmodule
+
+// ------------------------------------------------------------------------
+
+module \$__XILINX_RAMB8BWER_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 9;
+ parameter CFG_DBITS = 18;
+ parameter CFG_ENABLE_B = 2;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [9215:0] INIT = 9216'bx;
+
+ input CLK2;
+ input CLK3;
+
+ 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 [CFG_ENABLE_B-1:0] B1EN;
+
+ wire [12:0] A1ADDR_13 = A1ADDR << (13 - CFG_ABITS);
+ wire [12:0] B1ADDR_13 = B1ADDR << (13 - CFG_ABITS);
+ wire [1:0] B1EN_2 = {2{B1EN}};
+
+ wire [1:0] DIP, DOP;
+ wire [15:0] DI, DO;
+
+ wire [15:0] DOBDO;
+ wire [1:0] DOPBDOP;
+
+ assign A1DATA = { DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
+ assign { DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
+
+ generate if (CFG_DBITS > 8) begin
+ RAMB8BWER #(
+ .RAM_MODE("TDP"),
+ .DATA_WIDTH_A(CFG_DBITS),
+ .DATA_WIDTH_B(CFG_DBITS),
+ .WRITE_MODE_A("READ_FIRST"),
+ .WRITE_MODE_B("READ_FIRST"),
+ `include "brams_init_9.vh"
+ ) _TECHMAP_REPLACE_ (
+ .DIADI(16'b0),
+ .DIPADIP(2'b0),
+ .DOADO(DO),
+ .DOPADOP(DOP),
+ .ADDRAWRADDR(A1ADDR_13),
+ .CLKAWRCLK(CLK2 ^ !CLKPOL2),
+ .ENAWREN(A1EN),
+ .REGCEA(|1),
+ .RSTA(|0),
+ .WEAWEL(2'b0),
+
+ .DIBDI(DI),
+ .DIPBDIP(DIP),
+ .DOBDO(DOBDO),
+ .DOPBDOP(DOPBDOP),
+ .ADDRBRDADDR(B1ADDR_13),
+ .CLKBRDCLK(CLK3 ^ !CLKPOL3),
+ .ENBRDEN(|1),
+ .REGCEBREGCE(|0),
+ .RSTBRST(|0),
+ .WEBWEU(B1EN_2)
+ );
+ end else begin
+ RAMB8BWER #(
+ .RAM_MODE("TDP"),
+ .DATA_WIDTH_A(CFG_DBITS),
+ .DATA_WIDTH_B(CFG_DBITS),
+ .WRITE_MODE_A("READ_FIRST"),
+ .WRITE_MODE_B("READ_FIRST"),
+ `include "brams_init_8.vh"
+ ) _TECHMAP_REPLACE_ (
+ .DIADI(16'b0),
+ .DIPADIP(2'b0),
+ .DOADO(DO),
+ .DOPADOP(DOP),
+ .ADDRAWRADDR(A1ADDR_13),
+ .CLKAWRCLK(CLK2 ^ !CLKPOL2),
+ .ENAWREN(A1EN),
+ .REGCEA(|1),
+ .RSTA(|0),
+ .WEAWEL(2'b0),
+
+ .DIBDI(DI),
+ .DIPBDIP(DIP),
+ .DOBDO(DOBDO),
+ .DOPBDOP(DOPBDOP),
+ .ADDRBRDADDR(B1ADDR_13),
+ .CLKBRDCLK(CLK3 ^ !CLKPOL3),
+ .ENBRDEN(|1),
+ .REGCEBREGCE(|0),
+ .RSTBRST(|0),
+ .WEBWEU(B1EN_2)
+ );
+ end endgenerate
+endmodule
diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/xc7_brams.txt
index f1161114e..f1161114e 100644
--- a/techlibs/xilinx/brams.txt
+++ b/techlibs/xilinx/xc7_brams.txt
diff --git a/techlibs/xilinx/brams_bb.v b/techlibs/xilinx/xc7_brams_bb.v
index a682ba4a7..a682ba4a7 100644
--- a/techlibs/xilinx/brams_bb.v
+++ b/techlibs/xilinx/xc7_brams_bb.v
diff --git a/techlibs/xilinx/brams_map.v b/techlibs/xilinx/xc7_brams_map.v
index 7ea49158d..7ea49158d 100644
--- a/techlibs/xilinx/brams_map.v
+++ b/techlibs/xilinx/xc7_brams_map.v