aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/efinix
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2019-08-22 18:06:02 +0200
committerGitHub <noreply@github.com>2019-08-22 18:06:02 +0200
commit4d37710e82b0f1fe9f9eecc248de35e2adb840cd (patch)
tree62a2b2511dfc8309a21a28c42a6807eb0500d2c7 /techlibs/efinix
parent34a7c0209d23e8905009c4c122f850be6dd3ac05 (diff)
parent2897fe4d09118e37934b7e76f4990cc1d69a0cb5 (diff)
downloadyosys-4d37710e82b0f1fe9f9eecc248de35e2adb840cd.tar.gz
yosys-4d37710e82b0f1fe9f9eecc248de35e2adb840cd.tar.bz2
yosys-4d37710e82b0f1fe9f9eecc248de35e2adb840cd.zip
Merge pull request #1281 from mmicko/efinix
Initial support for Efinix Trion series FPGAs
Diffstat (limited to 'techlibs/efinix')
-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
9 files changed, 798 insertions, 0 deletions
diff --git a/techlibs/efinix/Makefile.inc b/techlibs/efinix/Makefile.inc
new file mode 100644
index 000000000..f1ce58276
--- /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)) \ No newline at end of file
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