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_fixcarry.cc130
-rw-r--r--techlibs/anlogic/arith_map.v44
-rw-r--r--techlibs/anlogic/synth_anlogic.cc7
-rw-r--r--techlibs/common/synth.cc2
-rw-r--r--techlibs/ecp5/cells_sim.v27
-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/ice40/cells_sim.v12
-rw-r--r--techlibs/xilinx/Makefile.inc4
-rw-r--r--techlibs/xilinx/cells_sim.v106
-rw-r--r--techlibs/xilinx/cells_xtra.py257
-rw-r--r--techlibs/xilinx/cells_xtra.sh147
-rw-r--r--techlibs/xilinx/cells_xtra.v289
-rw-r--r--techlibs/xilinx/lutrams.txt (renamed from techlibs/xilinx/drams.txt)0
-rw-r--r--techlibs/xilinx/lutrams_map.v (renamed from techlibs/xilinx/drams_map.v)0
-rw-r--r--techlibs/xilinx/synth_xilinx.cc83
-rw-r--r--techlibs/xilinx/xc6s_brams_bb.v4
-rw-r--r--techlibs/xilinx/xc7_brams_bb.v4
27 files changed, 1667 insertions, 321 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 c4089dac2..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);
-
- int 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 %d cells with determined init value.\n", cnt);
- }
-} AnlogicDetermineInitPass;
-
-PRIVATE_NAMESPACE_END
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 6d6a7ca37..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,15 +44,16 @@ 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+2:0] C = {COx, CI};
+ wire [Y_WIDTH-1:0] C = { COx, CIx };
wire dummy;
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;
@@ -59,18 +63,22 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
) 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: 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 */
- AL_MAP_ADDER #(
- .ALUTYPE("ADD"))
- adder_cout (
- .c(C[Y_WIDTH+1]),
- .o(COx[Y_WIDTH+1])
- );
- assign CO = COx[Y_WIDTH+1];
- 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/synth.cc b/techlibs/common/synth.cc
index 555de9fba..a176357a7 100644
--- a/techlibs/common/synth.cc
+++ b/techlibs/common/synth.cc
@@ -175,7 +175,7 @@ struct SynthPass : public ScriptPass
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)");
+ log_cmd_error("ABC9 flow only supported for FPGA synthesis (using '-lut' option)\n");
log_header(design, "Executing SYNTH pass.\n");
log_push();
diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v
index 3d343b315..dc8334acb 100644
--- a/techlibs/ecp5/cells_sim.v
+++ b/techlibs/ecp5/cells_sim.v
@@ -15,10 +15,15 @@ module L6MUX21 (input D0, D1, SD, output Z);
endmodule
// ---------------------------------------
-(* abc_box_id=1, abc_carry="CIN,COUT", lib_whitebox *)
-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";
@@ -104,12 +109,16 @@ module PFUMX (input ALUT, BLUT, C0, output Z);
endmodule
// ---------------------------------------
-//(* abc_box_id=2, abc_scc_break="DI,WAD,WRE" *)
+//(* 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";
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/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index 2205be27d..c7f3bdad2 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -141,8 +141,16 @@ module SB_CARRY (output CO, input I0, I1, CI);
assign CO = (I0 && I1) || ((I0 || I1) && CI);
endmodule
-(* abc_box_id = 1, abc_carry="CI,CO", lib_whitebox *)
-module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI);
+(* 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),
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index 2c6e7432e..2b1af289c 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -32,8 +32,8 @@ $(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/drams.txt))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.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))
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index 05e46b4e7..973e17212 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -29,24 +29,35 @@ module GND(output G);
assign G = 0;
endmodule
-module IBUF(output O, input I);
+module IBUF(
+ output O,
+ (* iopad_external_pin *)
+ input I);
parameter IOSTANDARD = "default";
parameter IBUF_LOW_PWR = 0;
assign O = I;
endmodule
-module OBUF(output O, input I);
+module OBUF(
+ (* iopad_external_pin *)
+ output O,
+ input I);
parameter IOSTANDARD = "default";
parameter DRIVE = 12;
parameter SLEW = "SLOW";
assign O = I;
endmodule
-module BUFG(output O, input I);
+module BUFG(
+ (* clkbuf_driver *)
+ output O,
+ input I);
+
assign O = I;
endmodule
module BUFGCTRL(
+ (* clkbuf_driver *)
output O,
input I0, input I1,
input S0, input S1,
@@ -72,7 +83,11 @@ assign O = S0_true ? I0_internal : (S1_true ? I1_internal : INIT_OUT);
endmodule
-module BUFHCE(output O, input I, input CE);
+module BUFHCE(
+ (* clkbuf_driver *)
+ output O,
+ input I,
+ input CE);
parameter [0:0] INIT_OUT = 1'b0;
parameter CE_TYPE = "SYNC";
@@ -181,8 +196,16 @@ module XORCY(output O, input CI, LI);
assign O = CI ^ LI;
endmodule
-(* abc_box_id = 4, abc_carry="CI,CO", lib_whitebox *)
-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];
@@ -213,7 +236,7 @@ endmodule
`endif
-module FDRE (output reg Q, input C, CE, D, R);
+module FDRE (output reg Q, (* clkbuf_sink *) input C, input CE, D, R);
parameter [0:0] INIT = 1'b0;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
@@ -225,7 +248,7 @@ module FDRE (output reg Q, input C, CE, D, R);
endcase endgenerate
endmodule
-module FDSE (output reg Q, input C, CE, D, S);
+module FDSE (output reg Q, (* clkbuf_sink *) input C, input CE, D, S);
parameter [0:0] INIT = 1'b1;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
@@ -237,7 +260,7 @@ module FDSE (output reg Q, input C, CE, D, S);
endcase endgenerate
endmodule
-module FDCE (output reg Q, input C, CE, D, CLR);
+module FDCE (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR);
parameter [0:0] INIT = 1'b0;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
@@ -251,7 +274,7 @@ module FDCE (output reg Q, input C, CE, D, CLR);
endcase endgenerate
endmodule
-module FDPE (output reg Q, input C, CE, D, PRE);
+module FDPE (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE);
parameter [0:0] INIT = 1'b1;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
@@ -265,34 +288,39 @@ module FDPE (output reg Q, input C, CE, D, PRE);
endcase endgenerate
endmodule
-module FDRE_1 (output reg Q, input C, CE, D, R);
+module FDRE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, R);
parameter [0:0] INIT = 1'b0;
initial Q <= INIT;
always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
endmodule
-module FDSE_1 (output reg Q, input C, CE, D, S);
+module FDSE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, S);
parameter [0:0] INIT = 1'b1;
initial Q <= INIT;
always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
endmodule
-module FDCE_1 (output reg Q, input C, CE, D, CLR);
+module FDCE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR);
parameter [0:0] INIT = 1'b0;
initial Q <= INIT;
always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
endmodule
-module FDPE_1 (output reg Q, input C, CE, D, PRE);
+module FDPE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE);
parameter [0:0] INIT = 1'b1;
initial Q <= INIT;
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
endmodule
-(* abc_box_id = 5, abc_scc_break="D,WE" *)
+(* abc_box_id = 5 *)
module RAM32X1D (
output DPO, SPO,
- input D, WCLK, WE,
+ (* abc_scc_break *)
+ input D,
+ (* clkbuf_sink *)
+ input WCLK,
+ (* abc_scc_break *)
+ input WE,
input A0, A1, A2, A3, A4,
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
);
@@ -307,10 +335,15 @@ module RAM32X1D (
always @(posedge clk) if (WE) mem[a] <= D;
endmodule
-(* abc_box_id = 6, abc_scc_break="D,WE" *)
+(* abc_box_id = 6 *)
module RAM64X1D (
output DPO, SPO,
- input D, WCLK, WE,
+ (* abc_scc_break *)
+ input D,
+ (* clkbuf_sink *)
+ input WCLK,
+ (* abc_scc_break *)
+ input WE,
input A0, A1, A2, A3, A4, A5,
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
);
@@ -325,10 +358,15 @@ module RAM64X1D (
always @(posedge clk) if (WE) mem[a] <= D;
endmodule
-(* abc_box_id = 7, abc_scc_break="D,WE" *)
+(* abc_box_id = 7 *)
module RAM128X1D (
output DPO, SPO,
- input D, WCLK, WE,
+ (* abc_scc_break *)
+ input D,
+ (* clkbuf_sink *)
+ input WCLK,
+ (* abc_scc_break *)
+ input WE,
input [6:0] A, DPRA
);
parameter INIT = 128'h0;
@@ -342,19 +380,41 @@ endmodule
module SRL16E (
output Q,
+ (* clkbuf_sink *)
+ input CLK,
+ input A0, A1, A2, A3, CE, D
+);
+ parameter [15:0] INIT = 16'h0000;
+ parameter [0:0] IS_CLK_INVERTED = 1'b0;
+
+ reg [15:0] r = INIT;
+ assign Q = r[{A3,A2,A1,A0}];
+ generate
+ if (IS_CLK_INVERTED) begin
+ always @(negedge CLK) if (CE) r <= { r[14:0], D };
+ end
+ else
+ always @(posedge CLK) if (CE) r <= { r[14:0], D };
+ endgenerate
+endmodule
+
+module SRLC16E (
+ output Q,
+ output Q15,
input A0, A1, A2, A3, CE, CLK, D
);
parameter [15:0] INIT = 16'h0000;
parameter [0:0] IS_CLK_INVERTED = 1'b0;
reg [15:0] r = INIT;
+ assign Q15 = r[15];
assign Q = r[{A3,A2,A1,A0}];
generate
if (IS_CLK_INVERTED) begin
always @(negedge CLK) if (CE) r <= { r[14:0], D };
end
else
- always @(posedge CLK) if (CE) r <= { r[14:0], D };
+ always @(posedge CLK) if (CE) r <= { r[14:0], D };
endgenerate
endmodule
@@ -362,7 +422,9 @@ module SRLC32E (
output Q,
output Q31,
input [4:0] A,
- input CE, CLK, D
+ (* clkbuf_sink *)
+ input CLK,
+ input CE, D
);
parameter [31:0] INIT = 32'h00000000;
parameter [0:0] IS_CLK_INVERTED = 1'b0;
diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py
new file mode 100644
index 000000000..dd4e300ae
--- /dev/null
+++ b/techlibs/xilinx/cells_xtra.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python3
+
+from argparse import ArgumentParser
+from io import StringIO
+from enum import Enum, auto
+import os.path
+import sys
+
+
+class Cell:
+ def __init__(self, name, keep=False, port_attrs={}):
+ self.name = name
+ self.keep = keep
+ self.port_attrs = port_attrs
+
+
+CELLS = [
+ # Design elements types listed in Xilinx UG953
+ Cell('BSCANE2', keep=True),
+ # Cell('BUFG', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFGCE', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFGCE_1', port_attrs={'O': ['clkbuf_driver']}),
+ #Cell('BUFGCTRL', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFGMUX', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFGMUX_1', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFGMUX_CTRL', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFH', port_attrs={'O': ['clkbuf_driver']}),
+ #Cell('BUFHCE', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFIO', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFMR', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFMRCE', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFR', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('CAPTUREE2', keep=True),
+ # Cell('CARRY4'),
+ Cell('CFGLUT5', port_attrs={'CLK': ['clkbuf_sink']}),
+ Cell('DCIRESET', keep=True),
+ Cell('DNA_PORT'),
+ Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}),
+ Cell('EFUSE_USR'),
+ # Cell('FDCE'),
+ # Cell('FDPE'),
+ # Cell('FDRE'),
+ # Cell('FDSE'),
+ Cell('FIFO18E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
+ Cell('FIFO36E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
+ Cell('FRAME_ECCE2'),
+ Cell('GTHE2_CHANNEL'),
+ Cell('GTHE2_COMMON'),
+ Cell('GTPE2_CHANNEL'),
+ Cell('GTPE2_COMMON'),
+ Cell('GTXE2_CHANNEL'),
+ Cell('GTXE2_COMMON'),
+ # Cell('IBUF', port_attrs={'I': ['iopad_external_pin']}),
+ Cell('IBUF_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin']}),
+ Cell('IBUF_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin']}),
+ Cell('IBUFDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
+ Cell('IBUFDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
+ Cell('IBUFDS_DIFF_OUT_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
+ Cell('IBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
+ Cell('IBUFDS_GTE2', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
+ Cell('IBUFDS_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
+ Cell('IBUFDS_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
+ Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}),
+ Cell('IBUFGDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
+ Cell('IBUFGDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
+ Cell('ICAPE2', keep=True),
+ Cell('IDDR', port_attrs={'C': ['clkbuf_sink']}),
+ Cell('IDDR_2CLK', port_attrs={'C': ['clkbuf_sink'], 'CB': ['clkbuf_sink']}),
+ Cell('IDELAYCTRL', keep=True, port_attrs={'REFCLK': ['clkbuf_sink']}),
+ Cell('IDELAYE2', port_attrs={'C': ['clkbuf_sink']}),
+ Cell('IN_FIFO', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
+ Cell('IOBUF', port_attrs={'IO': ['iopad_external_pin']}),
+ Cell('IOBUF_DCIEN', port_attrs={'IO': ['iopad_external_pin']}),
+ Cell('IOBUF_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin']}),
+ Cell('IOBUFDS', port_attrs={'IO': ['iopad_external_pin']}),
+ Cell('IOBUFDS_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
+ Cell('IOBUFDS_DIFF_OUT', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
+ Cell('IOBUFDS_DIFF_OUT_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
+ Cell('IOBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
+ Cell('ISERDESE2', port_attrs={
+ 'CLK': ['clkbuf_sink'],
+ 'CLKB': ['clkbuf_sink'],
+ 'OCLK': ['clkbuf_sink'],
+ 'OCLKB': ['clkbuf_sink'],
+ 'CLKDIV': ['clkbuf_sink'],
+ 'CLKDIVP': ['clkbuf_sink'],
+ }),
+ Cell('KEEPER'),
+ Cell('LDCE'),
+ Cell('LDPE'),
+ # Cell('LUT1'),
+ # Cell('LUT2'),
+ # Cell('LUT3'),
+ # Cell('LUT4'),
+ # Cell('LUT5'),
+ # Cell('LUT6'),
+ #Cell('LUT6_2'),
+ Cell('MMCME2_ADV'),
+ Cell('MMCME2_BASE'),
+ # Cell('MUXF7'),
+ # Cell('MUXF8'),
+ # Cell('OBUF', port_attrs={'O': ['iopad_external_pin']}),
+ Cell('OBUFDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
+ Cell('OBUFT', port_attrs={'O': ['iopad_external_pin']}),
+ Cell('OBUFTDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
+ Cell('ODDR', port_attrs={'C': ['clkbuf_sink']}),
+ Cell('ODELAYE2', port_attrs={'C': ['clkbuf_sink']}),
+ Cell('OSERDESE2', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
+ Cell('OUT_FIFO', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
+ Cell('PHASER_IN'),
+ Cell('PHASER_IN_PHY'),
+ Cell('PHASER_OUT'),
+ Cell('PHASER_OUT_PHY'),
+ Cell('PHASER_REF'),
+ Cell('PHY_CONTROL'),
+ Cell('PLLE2_ADV'),
+ Cell('PLLE2_BASE'),
+ Cell('PS7', keep=True),
+ Cell('PULLDOWN'),
+ Cell('PULLUP'),
+ #Cell('RAM128X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
+ Cell('RAM128X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ Cell('RAM256X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ Cell('RAM32M', port_attrs={'WCLK': ['clkbuf_sink']}),
+ #Cell('RAM32X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
+ Cell('RAM32X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ Cell('RAM32X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
+ Cell('RAM32X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ Cell('RAM64M', port_attrs={'WCLK': ['clkbuf_sink']}),
+ #Cell('RAM64X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
+ Cell('RAM64X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ Cell('RAM64X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
+ Cell('RAM64X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAMB18E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}),
+ # Cell('RAMB36E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}),
+ Cell('ROM128X1'),
+ Cell('ROM256X1'),
+ Cell('ROM32X1'),
+ Cell('ROM64X1'),
+ #Cell('SRL16E', port_attrs={'CLK': ['clkbuf_sink']}),
+ #Cell('SRLC32E', port_attrs={'CLK': ['clkbuf_sink']}),
+ Cell('STARTUPE2', keep=True),
+ Cell('USR_ACCESSE2'),
+ Cell('XADC'),
+]
+
+class State(Enum):
+ OUTSIDE = auto()
+ IN_MODULE = auto()
+ IN_OTHER_MODULE = auto()
+ IN_FUNCTION = auto()
+ IN_TASK = auto()
+
+def xtract_cell_decl(cell, dirs, outf):
+ for dir in dirs:
+ fname = os.path.join(dir, cell.name + '.v')
+ try:
+ with open(fname) as f:
+ state = State.OUTSIDE
+ found = False
+ # Probably the most horrible Verilog "parser" ever written.
+ for l in f:
+ l = l.partition('//')[0]
+ l = l.strip()
+ if l == 'module {}'.format(cell.name) or l.startswith('module {} '.format(cell.name)):
+ if found:
+ print('Multiple modules in {}.'.format(fname))
+ sys.exit(1)
+ elif state != State.OUTSIDE:
+ print('Nested modules in {}.'.format(fname))
+ sys.exit(1)
+ found = True
+ state = State.IN_MODULE
+ if cell.keep:
+ outf.write('(* keep *)\n')
+ outf.write('module {} (...);\n'.format(cell.name))
+ elif l.startswith('module '):
+ if state != State.OUTSIDE:
+ print('Nested modules in {}.'.format(fname))
+ sys.exit(1)
+ state = State.IN_OTHER_MODULE
+ elif l.startswith('task '):
+ if state == State.IN_MODULE:
+ state = State.IN_TASK
+ elif l.startswith('function '):
+ if state == State.IN_MODULE:
+ state = State.IN_FUNCTION
+ elif l == 'endtask':
+ if state == State.IN_TASK:
+ state = State.IN_MODULE
+ elif l == 'endfunction':
+ if state == State.IN_FUNCTION:
+ state = State.IN_MODULE
+ elif l == 'endmodule':
+ if state == State.IN_MODULE:
+ outf.write(l + '\n')
+ outf.write('\n')
+ elif state != State.IN_OTHER_MODULE:
+ print('endmodule in weird place in {}.'.format(cell.name, fname))
+ sys.exit(1)
+ state = State.OUTSIDE
+ elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE:
+ if l.endswith((';', ',')):
+ l = l[:-1]
+ if ';' in l:
+ print('Weird port line in {} [{}].'.format(fname, l))
+ sys.exit(1)
+ kind, _, ports = l.partition(' ')
+ for port in ports.split(','):
+ port = port.strip()
+ for attr in cell.port_attrs.get(port, []):
+ outf.write(' (* {} *)\n'.format(attr))
+ outf.write(' {} {};\n'.format(kind, port))
+ elif l.startswith('parameter ') and state == State.IN_MODULE:
+ if 'UNPLACED' in l:
+ continue
+ if l.endswith((';', ',')):
+ l = l[:-1]
+ while ' ' in l:
+ l = l.replace(' ', ' ')
+ if ';' in l:
+ print('Weird parameter line in {} [{}].'.format(fname, l))
+ sys.exit(1)
+ outf.write(' {};\n'.format(l))
+ if state != State.OUTSIDE:
+ print('endmodule not found in {}.'.format(fname))
+ sys.exit(1)
+ if not found:
+ print('Cannot find module {} in {}.'.format(cell.name, fname))
+ sys.exit(1)
+ return
+ except FileNotFoundError:
+ continue
+ print('Cannot find {}.'.format(cell.name))
+ sys.exit(1)
+
+if __name__ == '__main__':
+ parser = ArgumentParser(description='Extract Xilinx blackbox cell definitions from Vivado.')
+ parser.add_argument('vivado_dir', nargs='?', default='/opt/Xilinx/Vivado/2018.1')
+ args = parser.parse_args()
+
+ dirs = [
+ os.path.join(args.vivado_dir, 'data/verilog/src/xeclib'),
+ os.path.join(args.vivado_dir, 'data/verilog/src/retarget'),
+ ]
+ for dir in dirs:
+ if not os.path.isdir(dir):
+ print('{} is not a directory'.format(dir))
+
+ out = StringIO()
+ for cell in CELLS:
+ xtract_cell_decl(cell, dirs, out)
+
+ with open('cells_xtra.v', 'w') as f:
+ f.write('// Created by cells_xtra.py from Xilinx models\n')
+ f.write('\n')
+ f.write(out.getvalue())
diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh
deleted file mode 100644
index 53b528820..000000000
--- a/techlibs/xilinx/cells_xtra.sh
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/bin/bash
-
-set -e
-libdir="/opt/Xilinx/Vivado/2018.1/data/verilog/src"
-
-function xtract_cell_decl()
-{
- for dir in $libdir/xeclib $libdir/retarget; do
- [ -f $dir/$1.v ] || continue
- [ -z "$2" ] || echo $2
- egrep '^\s*((end)?module|parameter|input|inout|output|(end)?function|(end)?task)' $dir/$1.v |
- sed -re '/UNPLACED/ d; /^\s*function/,/endfunction/ d; /^\s*task/,/endtask/ d;
- s,//.*,,; s/#?\(.*/(...);/; s/^(input|output|parameter)/ \1/;
- s/\s+$//; s/,$/;/; /input|output|parameter/ s/[^;]$/&;/; s/\s+/ /g;
- s/^ ((end)?module)/\1/; s/^ / /; /module.*_bb/,/endmodule/ d;'
- echo; return
- done
- echo "Can't find $1."
- exit 1
-}
-
-{
- echo "// Created by cells_xtra.sh from Xilinx models"
- echo
-
- # Design elements types listed in Xilinx UG953
- xtract_cell_decl BSCANE2
- # xtract_cell_decl BUFG
- xtract_cell_decl BUFGCE
- xtract_cell_decl BUFGCE_1
- #xtract_cell_decl BUFGCTRL
- xtract_cell_decl BUFGMUX
- xtract_cell_decl BUFGMUX_1
- xtract_cell_decl BUFGMUX_CTRL
- xtract_cell_decl BUFH
- #xtract_cell_decl BUFHCE
- xtract_cell_decl BUFIO
- xtract_cell_decl BUFMR
- xtract_cell_decl BUFMRCE
- xtract_cell_decl BUFR
- xtract_cell_decl CAPTUREE2 "(* keep *)"
- # xtract_cell_decl CARRY4
- xtract_cell_decl CFGLUT5
- xtract_cell_decl DCIRESET "(* keep *)"
- xtract_cell_decl DNA_PORT
- xtract_cell_decl DSP48E1
- xtract_cell_decl EFUSE_USR
- # xtract_cell_decl FDCE
- # xtract_cell_decl FDPE
- # xtract_cell_decl FDRE
- # xtract_cell_decl FDSE
- xtract_cell_decl FIFO18E1
- xtract_cell_decl FIFO36E1
- xtract_cell_decl FRAME_ECCE2
- xtract_cell_decl GTHE2_CHANNEL
- xtract_cell_decl GTHE2_COMMON
- xtract_cell_decl GTPE2_CHANNEL
- xtract_cell_decl GTPE2_COMMON
- xtract_cell_decl GTXE2_CHANNEL
- xtract_cell_decl GTXE2_COMMON
- # xtract_cell_decl IBUF
- xtract_cell_decl IBUF_IBUFDISABLE
- xtract_cell_decl IBUF_INTERMDISABLE
- xtract_cell_decl IBUFDS
- xtract_cell_decl IBUFDS_DIFF_OUT
- xtract_cell_decl IBUFDS_DIFF_OUT_IBUFDISABLE
- xtract_cell_decl IBUFDS_DIFF_OUT_INTERMDISABLE
- xtract_cell_decl IBUFDS_GTE2
- xtract_cell_decl IBUFDS_IBUFDISABLE
- xtract_cell_decl IBUFDS_INTERMDISABLE
- xtract_cell_decl ICAPE2 "(* keep *)"
- xtract_cell_decl IDDR
- xtract_cell_decl IDDR_2CLK
- xtract_cell_decl IDELAYCTRL "(* keep *)"
- xtract_cell_decl IDELAYE2
- xtract_cell_decl IN_FIFO
- xtract_cell_decl IOBUF
- xtract_cell_decl IOBUF_DCIEN
- xtract_cell_decl IOBUF_INTERMDISABLE
- xtract_cell_decl IOBUFDS
- xtract_cell_decl IOBUFDS_DCIEN
- xtract_cell_decl IOBUFDS_DIFF_OUT
- xtract_cell_decl IOBUFDS_DIFF_OUT_DCIEN
- xtract_cell_decl IOBUFDS_DIFF_OUT_INTERMDISABLE
- xtract_cell_decl ISERDESE2
- xtract_cell_decl KEEPER
- xtract_cell_decl LDCE
- xtract_cell_decl LDPE
- # xtract_cell_decl LUT1
- # xtract_cell_decl LUT2
- # xtract_cell_decl LUT3
- # xtract_cell_decl LUT4
- # xtract_cell_decl LUT5
- # xtract_cell_decl LUT6
- #xtract_cell_decl LUT6_2
- xtract_cell_decl MMCME2_ADV
- xtract_cell_decl MMCME2_BASE
- # xtract_cell_decl MUXF7
- # xtract_cell_decl MUXF8
- # xtract_cell_decl OBUF
- xtract_cell_decl OBUFDS
- xtract_cell_decl OBUFT
- xtract_cell_decl OBUFTDS
- xtract_cell_decl ODDR
- xtract_cell_decl ODELAYE2
- xtract_cell_decl OSERDESE2
- xtract_cell_decl OUT_FIFO
- xtract_cell_decl PHASER_IN
- xtract_cell_decl PHASER_IN_PHY
- xtract_cell_decl PHASER_OUT
- xtract_cell_decl PHASER_OUT_PHY
- xtract_cell_decl PHASER_REF
- xtract_cell_decl PHY_CONTROL
- xtract_cell_decl PLLE2_ADV
- xtract_cell_decl PLLE2_BASE
- xtract_cell_decl PS7 "(* keep *)"
- xtract_cell_decl PULLDOWN
- xtract_cell_decl PULLUP
- #xtract_cell_decl RAM128X1D
- xtract_cell_decl RAM128X1S
- xtract_cell_decl RAM256X1S
- xtract_cell_decl RAM32M
- #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 RAM64X1S
- xtract_cell_decl RAM64X1S_1
- xtract_cell_decl RAM64X2S
- # xtract_cell_decl RAMB18E1
- # xtract_cell_decl RAMB36E1
- xtract_cell_decl ROM128X1
- xtract_cell_decl ROM256X1
- xtract_cell_decl ROM32X1
- xtract_cell_decl ROM64X1
- #xtract_cell_decl SRL16E
- #xtract_cell_decl SRLC32E
- xtract_cell_decl STARTUPE2 "(* keep *)"
- xtract_cell_decl USR_ACCESSE2
- xtract_cell_decl XADC
-} > cells_xtra.new
-
-mv cells_xtra.new cells_xtra.v
-exit 0
-
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 15fa1b63a..a6669b872 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -1,5 +1,6 @@
-// Created by cells_xtra.sh from Xilinx models
+// Created by cells_xtra.py from Xilinx models
+(* keep *)
module BSCANE2 (...);
parameter DISABLE_JTAG = "FALSE";
parameter integer JTAG_CHAIN = 1;
@@ -20,29 +21,39 @@ module BUFGCE (...);
parameter CE_TYPE = "SYNC";
parameter [0:0] IS_CE_INVERTED = 1'b0;
parameter [0:0] IS_I_INVERTED = 1'b0;
+ (* clkbuf_driver *)
output O;
input CE;
input I;
endmodule
module BUFGCE_1 (...);
+ (* clkbuf_driver *)
output O;
- input CE, I;
+ input CE;
+ input I;
endmodule
module BUFGMUX (...);
parameter CLK_SEL_TYPE = "SYNC";
+ (* clkbuf_driver *)
output O;
- input I0, I1, S;
+ input I0;
+ input I1;
+ input S;
endmodule
module BUFGMUX_1 (...);
parameter CLK_SEL_TYPE = "SYNC";
+ (* clkbuf_driver *)
output O;
- input I0, I1, S;
+ input I0;
+ input I1;
+ input S;
endmodule
module BUFGMUX_CTRL (...);
+ (* clkbuf_driver *)
output O;
input I0;
input I1;
@@ -50,16 +61,19 @@ module BUFGMUX_CTRL (...);
endmodule
module BUFH (...);
+ (* clkbuf_driver *)
output O;
input I;
endmodule
module BUFIO (...);
+ (* clkbuf_driver *)
output O;
input I;
endmodule
module BUFMR (...);
+ (* clkbuf_driver *)
output O;
input I;
endmodule
@@ -68,12 +82,14 @@ module BUFMRCE (...);
parameter CE_TYPE = "SYNC";
parameter integer INIT_OUT = 0;
parameter [0:0] IS_CE_INVERTED = 1'b0;
+ (* clkbuf_driver *)
output O;
input CE;
input I;
endmodule
module BUFR (...);
+ (* clkbuf_driver *)
output O;
input CE;
input CLR;
@@ -95,8 +111,15 @@ module CFGLUT5 (...);
output CDO;
output O5;
output O6;
- input I4, I3, I2, I1, I0;
- input CDI, CE, CLK;
+ input I4;
+ input I3;
+ input I2;
+ input I1;
+ input I0;
+ input CDI;
+ input CE;
+ (* clkbuf_sink *)
+ input CLK;
endmodule
(* keep *)
@@ -108,7 +131,10 @@ endmodule
module DNA_PORT (...);
parameter [56:0] SIM_DNA_VALUE = 57'h0;
output DOUT;
- input CLK, DIN, READ, SHIFT;
+ input CLK;
+ input DIN;
+ input READ;
+ input SHIFT;
endmodule
module DSP48E1 (...);
@@ -175,6 +201,7 @@ module DSP48E1 (...);
input CEINMODE;
input CEM;
input CEP;
+ (* clkbuf_sink *)
input CLK;
input [24:0] D;
input [4:0] INMODE;
@@ -227,11 +254,13 @@ module FIFO18E1 (...);
output WRERR;
input [31:0] DI;
input [3:0] DIP;
+ (* clkbuf_sink *)
input RDCLK;
input RDEN;
input REGCE;
input RST;
input RSTREG;
+ (* clkbuf_sink *)
input WRCLK;
input WREN;
endmodule
@@ -272,11 +301,13 @@ module FIFO36E1 (...);
input [7:0] DIP;
input INJECTDBITERR;
input INJECTSBITERR;
+ (* clkbuf_sink *)
input RDCLK;
input RDEN;
input REGCE;
input RST;
input RSTREG;
+ (* clkbuf_sink *)
input WRCLK;
input WREN;
endmodule
@@ -1969,6 +2000,7 @@ module IBUF_IBUFDISABLE (...);
parameter SIM_DEVICE = "7SERIES";
parameter USE_IBUFDISABLE = "TRUE";
output O;
+ (* iopad_external_pin *)
input I;
input IBUFDISABLE;
endmodule
@@ -1979,6 +2011,7 @@ module IBUF_INTERMDISABLE (...);
parameter SIM_DEVICE = "7SERIES";
parameter USE_IBUFDISABLE = "TRUE";
output O;
+ (* iopad_external_pin *)
input I;
input IBUFDISABLE;
input INTERMDISABLE;
@@ -1993,7 +2026,10 @@ module IBUFDS (...);
parameter IFD_DELAY_VALUE = "AUTO";
parameter IOSTANDARD = "DEFAULT";
output O;
- input I, IB;
+ (* iopad_external_pin *)
+ input I;
+ (* iopad_external_pin *)
+ input IB;
endmodule
module IBUFDS_DIFF_OUT (...);
@@ -2001,8 +2037,12 @@ module IBUFDS_DIFF_OUT (...);
parameter DQS_BIAS = "FALSE";
parameter IBUF_LOW_PWR = "TRUE";
parameter IOSTANDARD = "DEFAULT";
- output O, OB;
- input I, IB;
+ output O;
+ output OB;
+ (* iopad_external_pin *)
+ input I;
+ (* iopad_external_pin *)
+ input IB;
endmodule
module IBUFDS_DIFF_OUT_IBUFDISABLE (...);
@@ -2014,7 +2054,9 @@ module IBUFDS_DIFF_OUT_IBUFDISABLE (...);
parameter USE_IBUFDISABLE = "TRUE";
output O;
output OB;
+ (* iopad_external_pin *)
input I;
+ (* iopad_external_pin *)
input IB;
input IBUFDISABLE;
endmodule
@@ -2028,7 +2070,9 @@ module IBUFDS_DIFF_OUT_INTERMDISABLE (...);
parameter USE_IBUFDISABLE = "TRUE";
output O;
output OB;
+ (* iopad_external_pin *)
input I;
+ (* iopad_external_pin *)
input IB;
input IBUFDISABLE;
input INTERMDISABLE;
@@ -2041,7 +2085,9 @@ module IBUFDS_GTE2 (...);
output O;
output ODIV2;
input CEB;
+ (* iopad_external_pin *)
input I;
+ (* iopad_external_pin *)
input IB;
endmodule
@@ -2053,7 +2099,9 @@ module IBUFDS_IBUFDISABLE (...);
parameter SIM_DEVICE = "7SERIES";
parameter USE_IBUFDISABLE = "TRUE";
output O;
+ (* iopad_external_pin *)
input I;
+ (* iopad_external_pin *)
input IB;
input IBUFDISABLE;
endmodule
@@ -2066,12 +2114,50 @@ module IBUFDS_INTERMDISABLE (...);
parameter SIM_DEVICE = "7SERIES";
parameter USE_IBUFDISABLE = "TRUE";
output O;
+ (* iopad_external_pin *)
input I;
+ (* iopad_external_pin *)
input IB;
input IBUFDISABLE;
input INTERMDISABLE;
endmodule
+module IBUFG (...);
+ parameter CAPACITANCE = "DONT_CARE";
+ parameter IBUF_DELAY_VALUE = "0";
+ parameter IBUF_LOW_PWR = "TRUE";
+ parameter IOSTANDARD = "DEFAULT";
+ output O;
+ (* iopad_external_pin *)
+ input I;
+endmodule
+
+module IBUFGDS (...);
+ parameter CAPACITANCE = "DONT_CARE";
+ parameter DIFF_TERM = "FALSE";
+ parameter IBUF_DELAY_VALUE = "0";
+ parameter IBUF_LOW_PWR = "TRUE";
+ parameter IOSTANDARD = "DEFAULT";
+ output O;
+ (* iopad_external_pin *)
+ input I;
+ (* iopad_external_pin *)
+ input IB;
+endmodule
+
+module IBUFGDS_DIFF_OUT (...);
+ parameter DIFF_TERM = "FALSE";
+ parameter DQS_BIAS = "FALSE";
+ parameter IBUF_LOW_PWR = "TRUE";
+ parameter IOSTANDARD = "DEFAULT";
+ output O;
+ output OB;
+ (* iopad_external_pin *)
+ input I;
+ (* iopad_external_pin *)
+ input IB;
+endmodule
+
(* keep *)
module ICAPE2 (...);
parameter [31:0] DEVICE_ID = 32'h04244093;
@@ -2095,6 +2181,7 @@ module IDDR (...);
parameter XON = "TRUE";
output Q1;
output Q2;
+ (* clkbuf_sink *)
input C;
input CE;
input D;
@@ -2112,7 +2199,9 @@ module IDDR_2CLK (...);
parameter SRTYPE = "SYNC";
output Q1;
output Q2;
+ (* clkbuf_sink *)
input C;
+ (* clkbuf_sink *)
input CB;
input CE;
input D;
@@ -2124,6 +2213,7 @@ endmodule
module IDELAYCTRL (...);
parameter SIM_DEVICE = "7SERIES";
output RDY;
+ (* clkbuf_sink *)
input REFCLK;
input RST;
endmodule
@@ -2143,6 +2233,7 @@ module IDELAYE2 (...);
parameter integer SIM_DELAY_D = 0;
output [4:0] CNTVALUEOUT;
output DATAOUT;
+ (* clkbuf_sink *)
input C;
input CE;
input CINVCTRL;
@@ -2174,9 +2265,11 @@ module IN_FIFO (...);
output [7:0] Q7;
output [7:0] Q8;
output [7:0] Q9;
+ (* clkbuf_sink *)
input RDCLK;
input RDEN;
input RESET;
+ (* clkbuf_sink *)
input WRCLK;
input WREN;
input [3:0] D0;
@@ -2197,8 +2290,10 @@ module IOBUF (...);
parameter IOSTANDARD = "DEFAULT";
parameter SLEW = "SLOW";
output O;
+ (* iopad_external_pin *)
inout IO;
- input I, T;
+ input I;
+ input T;
endmodule
module IOBUF_DCIEN (...);
@@ -2209,6 +2304,7 @@ module IOBUF_DCIEN (...);
parameter SLEW = "SLOW";
parameter USE_IBUFDISABLE = "TRUE";
output O;
+ (* iopad_external_pin *)
inout IO;
input DCITERMDISABLE;
input I;
@@ -2224,6 +2320,7 @@ module IOBUF_INTERMDISABLE (...);
parameter SLEW = "SLOW";
parameter USE_IBUFDISABLE = "TRUE";
output O;
+ (* iopad_external_pin *)
inout IO;
input I;
input IBUFDISABLE;
@@ -2238,8 +2335,11 @@ module IOBUFDS (...);
parameter IOSTANDARD = "DEFAULT";
parameter SLEW = "SLOW";
output O;
- inout IO, IOB;
- input I, T;
+ (* iopad_external_pin *)
+ inout IO;
+ inout IOB;
+ input I;
+ input T;
endmodule
module IOBUFDS_DCIEN (...);
@@ -2251,7 +2351,9 @@ module IOBUFDS_DCIEN (...);
parameter SLEW = "SLOW";
parameter USE_IBUFDISABLE = "TRUE";
output O;
+ (* iopad_external_pin *)
inout IO;
+ (* iopad_external_pin *)
inout IOB;
input DCITERMDISABLE;
input I;
@@ -2266,7 +2368,9 @@ module IOBUFDS_DIFF_OUT (...);
parameter IOSTANDARD = "DEFAULT";
output O;
output OB;
+ (* iopad_external_pin *)
inout IO;
+ (* iopad_external_pin *)
inout IOB;
input I;
input TM;
@@ -2282,7 +2386,9 @@ module IOBUFDS_DIFF_OUT_DCIEN (...);
parameter USE_IBUFDISABLE = "TRUE";
output O;
output OB;
+ (* iopad_external_pin *)
inout IO;
+ (* iopad_external_pin *)
inout IOB;
input DCITERMDISABLE;
input I;
@@ -2300,7 +2406,9 @@ module IOBUFDS_DIFF_OUT_INTERMDISABLE (...);
parameter USE_IBUFDISABLE = "TRUE";
output O;
output OB;
+ (* iopad_external_pin *)
inout IO;
+ (* iopad_external_pin *)
inout IOB;
input I;
input IBUFDISABLE;
@@ -2348,15 +2456,21 @@ module ISERDESE2 (...);
input BITSLIP;
input CE1;
input CE2;
+ (* clkbuf_sink *)
input CLK;
+ (* clkbuf_sink *)
input CLKB;
+ (* clkbuf_sink *)
input CLKDIV;
+ (* clkbuf_sink *)
input CLKDIVP;
input D;
input DDLY;
input DYNCLKDIVSEL;
input DYNCLKSEL;
+ (* clkbuf_sink *)
input OCLK;
+ (* clkbuf_sink *)
input OCLKB;
input OFB;
input RST;
@@ -2375,7 +2489,10 @@ module LDCE (...);
parameter MSGON = "TRUE";
parameter XON = "TRUE";
output Q;
- input CLR, D, G, GE;
+ input CLR;
+ input D;
+ input G;
+ input GE;
endmodule
module LDPE (...);
@@ -2385,7 +2502,10 @@ module LDPE (...);
parameter MSGON = "TRUE";
parameter XON = "TRUE";
output Q;
- input D, G, GE, PRE;
+ input D;
+ input G;
+ input GE;
+ input PRE;
endmodule
module MMCME2_ADV (...);
@@ -2533,7 +2653,10 @@ module OBUFDS (...);
parameter CAPACITANCE = "DONT_CARE";
parameter IOSTANDARD = "DEFAULT";
parameter SLEW = "SLOW";
- output O, OB;
+ (* iopad_external_pin *)
+ output O;
+ (* iopad_external_pin *)
+ output OB;
input I;
endmodule
@@ -2542,20 +2665,27 @@ module OBUFT (...);
parameter integer DRIVE = 12;
parameter IOSTANDARD = "DEFAULT";
parameter SLEW = "SLOW";
+ (* iopad_external_pin *)
output O;
- input I, T;
+ input I;
+ input T;
endmodule
module OBUFTDS (...);
parameter CAPACITANCE = "DONT_CARE";
parameter IOSTANDARD = "DEFAULT";
parameter SLEW = "SLOW";
- output O, OB;
- input I, T;
+ (* iopad_external_pin *)
+ output O;
+ (* iopad_external_pin *)
+ output OB;
+ input I;
+ input T;
endmodule
module ODDR (...);
output Q;
+ (* clkbuf_sink *)
input C;
input CE;
input D1;
@@ -2586,6 +2716,7 @@ module ODELAYE2 (...);
parameter integer SIM_DELAY_D = 0;
output [4:0] CNTVALUEOUT;
output DATAOUT;
+ (* clkbuf_sink *)
input C;
input CE;
input CINVCTRL;
@@ -2631,7 +2762,9 @@ module OSERDESE2 (...);
output TBYTEOUT;
output TFB;
output TQ;
+ (* clkbuf_sink *)
input CLK;
+ (* clkbuf_sink *)
input CLKDIV;
input D1;
input D2;
@@ -2673,9 +2806,11 @@ module OUT_FIFO (...);
output [3:0] Q9;
output [7:0] Q5;
output [7:0] Q6;
+ (* clkbuf_sink *)
input RDCLK;
input RDEN;
input RESET;
+ (* clkbuf_sink *)
input WRCLK;
input WREN;
input [7:0] D0;
@@ -3659,7 +3794,17 @@ module RAM128X1S (...);
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
output O;
- input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
+ input A5;
+ input A6;
+ input D;
+ (* clkbuf_sink *)
+ input WCLK;
+ input WE;
endmodule
module RAM256X1S (...);
@@ -3668,6 +3813,7 @@ module RAM256X1S (...);
output O;
input [7:0] A;
input D;
+ (* clkbuf_sink *)
input WCLK;
input WE;
endmodule
@@ -3690,6 +3836,7 @@ module RAM32M (...);
input [1:0] DIB;
input [1:0] DIC;
input [1:0] DID;
+ (* clkbuf_sink *)
input WCLK;
input WE;
endmodule
@@ -3698,22 +3845,48 @@ module RAM32X1S (...);
parameter [31:0] INIT = 32'h00000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
output O;
- input A0, A1, A2, A3, A4, D, WCLK, WE;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
+ input D;
+ (* clkbuf_sink *)
+ input WCLK;
+ input WE;
endmodule
module RAM32X1S_1 (...);
parameter [31:0] INIT = 32'h00000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
output O;
- input A0, A1, A2, A3, A4, D, WCLK, WE;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
+ input D;
+ (* clkbuf_sink *)
+ input WCLK;
+ input WE;
endmodule
module RAM32X2S (...);
parameter [31:0] INIT_00 = 32'h00000000;
parameter [31:0] INIT_01 = 32'h00000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O0, O1;
- input A0, A1, A2, A3, A4, D0, D1, WCLK, WE;
+ output O0;
+ output O1;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
+ input D0;
+ input D1;
+ (* clkbuf_sink *)
+ input WCLK;
+ input WE;
endmodule
module RAM64M (...);
@@ -3734,6 +3907,7 @@ module RAM64M (...);
input DIB;
input DIC;
input DID;
+ (* clkbuf_sink *)
input WCLK;
input WE;
endmodule
@@ -3742,46 +3916,97 @@ module RAM64X1S (...);
parameter [63:0] INIT = 64'h0000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
output O;
- input A0, A1, A2, A3, A4, A5, D, WCLK, WE;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
+ input A5;
+ input D;
+ (* clkbuf_sink *)
+ input WCLK;
+ input WE;
endmodule
module RAM64X1S_1 (...);
parameter [63:0] INIT = 64'h0000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
output O;
- input A0, A1, A2, A3, A4, A5, D, WCLK, WE;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
+ input A5;
+ input D;
+ (* clkbuf_sink *)
+ input WCLK;
+ input WE;
endmodule
module RAM64X2S (...);
parameter [63:0] INIT_00 = 64'h0000000000000000;
parameter [63:0] INIT_01 = 64'h0000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O0, O1;
- input A0, A1, A2, A3, A4, A5, D0, D1, WCLK, WE;
+ output O0;
+ output O1;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
+ input A5;
+ input D0;
+ input D1;
+ (* clkbuf_sink *)
+ input WCLK;
+ input WE;
endmodule
module ROM128X1 (...);
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
output O;
- input A0, A1, A2, A3, A4, A5, A6;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
+ input A5;
+ input A6;
endmodule
module ROM256X1 (...);
parameter [255:0] INIT = 256'h0000000000000000000000000000000000000000000000000000000000000000;
output O;
- input A0, A1, A2, A3, A4, A5, A6, A7;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
+ input A5;
+ input A6;
+ input A7;
endmodule
module ROM32X1 (...);
parameter [31:0] INIT = 32'h00000000;
output O;
- input A0, A1, A2, A3, A4;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
endmodule
module ROM64X1 (...);
parameter [63:0] INIT = 64'h0000000000000000;
output O;
- input A0, A1, A2, A3, A4, A5;
+ input A0;
+ input A1;
+ input A2;
+ input A3;
+ input A4;
+ input A5;
endmodule
(* keep *)
diff --git a/techlibs/xilinx/drams.txt b/techlibs/xilinx/lutrams.txt
index 2613c206c..2613c206c 100644
--- a/techlibs/xilinx/drams.txt
+++ b/techlibs/xilinx/lutrams.txt
diff --git a/techlibs/xilinx/drams_map.v b/techlibs/xilinx/lutrams_map.v
index 77041ca86..77041ca86 100644
--- a/techlibs/xilinx/drams_map.v
+++ b/techlibs/xilinx/lutrams_map.v
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index d143c6823..f058da83d 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -63,14 +63,17 @@ struct SynthXilinxPass : 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(" -ise\n");
+ log(" generate an output netlist suitable for ISE (enables -iopad)\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");
@@ -78,6 +81,15 @@ struct SynthXilinxPass : public ScriptPass
log(" -nowidelut\n");
log(" do not use MUXF[78] resources to implement LUTs larger than LUT6s\n");
log("\n");
+ log(" -iopad\n");
+ log(" enable I/O buffer insertion (selected automatically by -ise)\n");
+ log("\n");
+ log(" -noiopad\n");
+ log(" disable I/O buffer insertion (only useful with -ise)\n");
+ log("\n");
+ log(" -noclkbuf\n");
+ log(" disable automatic clock buffer insertion\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");
@@ -104,7 +116,8 @@ struct SynthXilinxPass : public ScriptPass
}
std::string top_opt, edif_file, blif_file, family;
- bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, abc9;
+ bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, abc9;
+ bool flatten_before_abc;
int widemux;
void clear_flags() YS_OVERRIDE
@@ -116,13 +129,18 @@ struct SynthXilinxPass : public ScriptPass
flatten = false;
retime = false;
vpr = false;
+ ise = false;
+ iopad = false;
+ noiopad = false;
+ noclkbuf = false;
nocarry = false;
nobram = false;
- nodram = false;
+ nolutram = false;
nosrl = false;
nocarry = false;
nowidelut = false;
abc9 = false;
+ flatten_before_abc = false;
widemux = 0;
}
@@ -162,6 +180,10 @@ 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;
@@ -178,6 +200,22 @@ struct SynthXilinxPass : public ScriptPass
vpr = true;
continue;
}
+ if (args[argidx] == "-ise") {
+ ise = true;
+ continue;
+ }
+ if (args[argidx] == "-iopad") {
+ iopad = true;
+ continue;
+ }
+ if (args[argidx] == "-noiopad") {
+ noiopad = true;
+ continue;
+ }
+ if (args[argidx] == "-noclkbuf") {
+ noclkbuf = true;
+ continue;
+ }
if (args[argidx] == "-nocarry") {
nocarry = true;
continue;
@@ -186,8 +224,8 @@ struct SynthXilinxPass : 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] == "-nosrl") {
@@ -284,7 +322,7 @@ struct SynthXilinxPass : public ScriptPass
run("opt_clean");
}
- if (check_label("bram", "(skip if '-nobram')")) {
+ 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");
@@ -301,20 +339,23 @@ struct SynthXilinxPass : public ScriptPass
}
}
- 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")) {
+ 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) {
@@ -382,6 +423,8 @@ struct SynthXilinxPass : public ScriptPass
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]", "(option for 'nowidelut', option for '-retime')");
else if (abc9) {
@@ -410,6 +453,18 @@ struct SynthXilinxPass : public ScriptPass
run("clean");
}
+ if (check_label("finalize")) {
+ bool do_iopad = iopad || (ise && !noiopad);
+ if (help_mode || !noclkbuf) {
+ if (help_mode || do_iopad)
+ run("clkbufmap -buf BUFG O:I -inpad IBUFG O:I", "(skip if '-noclkbuf', '-inpad' passed if '-iopad' or '-ise' and not '-noiopad')");
+ else
+ run("clkbufmap -buf BUFG O:I");
+ }
+ if (do_iopad)
+ run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I A:top", "(only if '-iopad' or '-ise' and not '-noiopad')");
+ }
+
if (check_label("check")) {
run("hierarchy -check");
run("stat -tech xilinx");
diff --git a/techlibs/xilinx/xc6s_brams_bb.v b/techlibs/xilinx/xc6s_brams_bb.v
index eb1a29579..041d6b54f 100644
--- a/techlibs/xilinx/xc6s_brams_bb.v
+++ b/techlibs/xilinx/xc6s_brams_bb.v
@@ -1,5 +1,7 @@
module RAMB8BWER (
+ (* clkbuf_sink *)
input CLKAWRCLK,
+ (* clkbuf_sink *)
input CLKBRDCLK,
input ENAWREN,
input ENBRDEN,
@@ -87,7 +89,9 @@ module RAMB8BWER (
endmodule
module RAMB16BWER (
+ (* clkbuf_sink *)
input CLKA,
+ (* clkbuf_sink *)
input CLKB,
input ENA,
input ENB,
diff --git a/techlibs/xilinx/xc7_brams_bb.v b/techlibs/xilinx/xc7_brams_bb.v
index a682ba4a7..a43b4b5a1 100644
--- a/techlibs/xilinx/xc7_brams_bb.v
+++ b/techlibs/xilinx/xc7_brams_bb.v
@@ -1,5 +1,7 @@
module RAMB18E1 (
+ (* clkbuf_sink *)
input CLKARDCLK,
+ (* clkbuf_sink *)
input CLKBWRCLK,
input ENARDEN,
input ENBWREN,
@@ -123,7 +125,9 @@ module RAMB18E1 (
endmodule
module RAMB36E1 (
+ (* clkbuf_sink *)
input CLKARDCLK,
+ (* clkbuf_sink *)
input CLKBWRCLK,
input ENARDEN,
input ENBWREN,