From 36bd07586506a1a60fa8dae3215baad54d03ccbf Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Sat, 10 Oct 2020 19:08:54 +0200 Subject: [PATCH 01/15] start implementing support for intel le based logic devices --- techlibs/intel_le/Makefile.inc | 27 + techlibs/intel_le/common/abc9_map.v | 18 + techlibs/intel_le/common/abc9_model.v | 10 + techlibs/intel_le/common/abc9_unmap.v | 11 + techlibs/intel_le/common/arith_alm_map.v | 71 +++ techlibs/intel_le/common/bram_m10k.txt | 33 ++ techlibs/intel_le/common/bram_m20k.txt | 33 ++ techlibs/intel_le/common/bram_m20k_map.v | 31 + techlibs/intel_le/common/dff_map.v | 13 + techlibs/intel_le/common/dff_sim.v | 114 ++++ techlibs/intel_le/common/dsp_map.v | 51 ++ techlibs/intel_le/common/dsp_sim.v | 83 +++ techlibs/intel_le/common/le_map.v | 57 ++ techlibs/intel_le/common/le_sim.v | 561 ++++++++++++++++++ techlibs/intel_le/common/lutram_mlab.txt | 18 + techlibs/intel_le/common/megafunction_bb.v | 629 +++++++++++++++++++++ techlibs/intel_le/common/mem_sim.v | 109 ++++ techlibs/intel_le/common/quartus_rename.v | 235 ++++++++ techlibs/intel_le/cycloneiv/cells_sim.v | 150 +++++ techlibs/intel_le/synth_intel_le.cc | 280 +++++++++ tests/arch/intel_le/add_sub.ys | 18 + tests/arch/intel_le/adffs.ys | 94 +++ tests/arch/intel_le/blockram.ys | 6 + tests/arch/intel_le/counter.ys | 27 + tests/arch/intel_le/dffs.ys | 43 ++ tests/arch/intel_le/fsm.ys | 44 ++ tests/arch/intel_le/logic.ys | 25 + tests/arch/intel_le/lutram.ys | 41 ++ tests/arch/intel_le/mul.ys | 60 ++ tests/arch/intel_le/mux.ys | 88 +++ tests/arch/intel_le/quartus_ice.ys | 26 + tests/arch/intel_le/run-test.sh | 4 + tests/arch/intel_le/shifter.ys | 21 + tests/arch/intel_le/tribuf.ys | 27 + 34 files changed, 3058 insertions(+) create mode 100644 techlibs/intel_le/Makefile.inc create mode 100644 techlibs/intel_le/common/abc9_map.v create mode 100644 techlibs/intel_le/common/abc9_model.v create mode 100644 techlibs/intel_le/common/abc9_unmap.v create mode 100644 techlibs/intel_le/common/arith_alm_map.v create mode 100644 techlibs/intel_le/common/bram_m10k.txt create mode 100644 techlibs/intel_le/common/bram_m20k.txt create mode 100644 techlibs/intel_le/common/bram_m20k_map.v create mode 100644 techlibs/intel_le/common/dff_map.v create mode 100644 techlibs/intel_le/common/dff_sim.v create mode 100644 techlibs/intel_le/common/dsp_map.v create mode 100644 techlibs/intel_le/common/dsp_sim.v create mode 100644 techlibs/intel_le/common/le_map.v create mode 100644 techlibs/intel_le/common/le_sim.v create mode 100644 techlibs/intel_le/common/lutram_mlab.txt create mode 100644 techlibs/intel_le/common/megafunction_bb.v create mode 100644 techlibs/intel_le/common/mem_sim.v create mode 100644 techlibs/intel_le/common/quartus_rename.v create mode 100644 techlibs/intel_le/cycloneiv/cells_sim.v create mode 100644 techlibs/intel_le/synth_intel_le.cc create mode 100644 tests/arch/intel_le/add_sub.ys create mode 100644 tests/arch/intel_le/adffs.ys create mode 100644 tests/arch/intel_le/blockram.ys create mode 100644 tests/arch/intel_le/counter.ys create mode 100644 tests/arch/intel_le/dffs.ys create mode 100644 tests/arch/intel_le/fsm.ys create mode 100644 tests/arch/intel_le/logic.ys create mode 100644 tests/arch/intel_le/lutram.ys create mode 100644 tests/arch/intel_le/mul.ys create mode 100644 tests/arch/intel_le/mux.ys create mode 100644 tests/arch/intel_le/quartus_ice.ys create mode 100755 tests/arch/intel_le/run-test.sh create mode 100644 tests/arch/intel_le/shifter.ys create mode 100644 tests/arch/intel_le/tribuf.ys diff --git a/techlibs/intel_le/Makefile.inc b/techlibs/intel_le/Makefile.inc new file mode 100644 index 000000000..efc9de821 --- /dev/null +++ b/techlibs/intel_le/Makefile.inc @@ -0,0 +1,27 @@ + +OBJS += techlibs/intel_le/synth_intel_le.o + +# Techmap +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/abc9_map.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/abc9_unmap.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/abc9_model.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/alm_map.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/alm_sim.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/arith_alm_map.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dff_map.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dff_sim.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dsp_sim.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dsp_map.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/mem_sim.v)) + +$(eval $(call add_share_file,share/intel_le/cyclonev,techlibs/intel_le/cycloneiv/cells_sim.v)) + +# RAM +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/bram_m10k.txt)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/bram_m20k.txt)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/bram_m20k_map.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/lutram_mlab.txt)) + +# Miscellaneous +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/megafunction_bb.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/quartus_rename.v)) diff --git a/techlibs/intel_le/common/abc9_map.v b/techlibs/intel_le/common/abc9_map.v new file mode 100644 index 000000000..9d11bb240 --- /dev/null +++ b/techlibs/intel_le/common/abc9_map.v @@ -0,0 +1,18 @@ +// This file exists to map purely-synchronous flops to ABC9 flops, while +// mapping flops with asynchronous-clear as boxes, this is because ABC9 +// doesn't support asynchronous-clear flops in sequential synthesis. + +module MISTRAL_FF( + input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA, + output reg Q +); + +parameter _TECHMAP_CONSTMSK_ACLR_ = 1'b0; + +// If the async-clear is constant, we assume it's disabled. +if (_TECHMAP_CONSTMSK_ACLR_ != 1'b0) + $__MISTRAL_FF_SYNCONLY _TECHMAP_REPLACE_ (.DATAIN(DATAIN), .CLK(CLK), .ENA(ENA), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q)); +else + wire _TECHMAP_FAIL_ = 1; + +endmodule diff --git a/techlibs/intel_le/common/abc9_model.v b/techlibs/intel_le/common/abc9_model.v new file mode 100644 index 000000000..8f06d3835 --- /dev/null +++ b/techlibs/intel_le/common/abc9_model.v @@ -0,0 +1,10 @@ +// This is a purely-synchronous flop, that ABC9 can use for sequential synthesis. +(* abc9_flop, lib_whitebox *) +module $__MISTRAL_FF_SYNCONLY ( + input DATAIN, CLK, ENA, SCLR, SLOAD, SDATA, + output reg Q +); + +MISTRAL_FF ff (.DATAIN(DATAIN), .CLK(CLK), .ENA(ENA), .ACLR(1'b1), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q)); + +endmodule diff --git a/techlibs/intel_le/common/abc9_unmap.v b/techlibs/intel_le/common/abc9_unmap.v new file mode 100644 index 000000000..4b28866a3 --- /dev/null +++ b/techlibs/intel_le/common/abc9_unmap.v @@ -0,0 +1,11 @@ +// After performing sequential synthesis, map the synchronous flops back to +// standard MISTRAL_FF flops. + +module $__MISTRAL_FF_SYNCONLY ( + input DATAIN, CLK, ENA, SCLR, SLOAD, SDATA, + output reg Q +); + +MISTRAL_FF _TECHMAP_REPLACE_ (.DATAIN(DATAIN), .CLK(CLK), .ACLR(1'b1), .ENA(ENA), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q)); + +endmodule diff --git a/techlibs/intel_le/common/arith_alm_map.v b/techlibs/intel_le/common/arith_alm_map.v new file mode 100644 index 000000000..8515eeb56 --- /dev/null +++ b/techlibs/intel_le/common/arith_alm_map.v @@ -0,0 +1,71 @@ +`default_nettype none + +module \$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; + +parameter _TECHMAP_CONSTMSK_CI_ = 0; +parameter _TECHMAP_CONSTVAL_CI_ = 0; + +(* force_downto *) +input [A_WIDTH-1:0] A; +(* force_downto *) +input [B_WIDTH-1:0] B; +input CI, BI; +(* force_downto *) +output [Y_WIDTH-1:0] X, Y, CO; + +(* force_downto *) +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)); + +(* force_downto *) +wire [Y_WIDTH-1:0] AA = A_buf; +(* force_downto *) +wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; +(* force_downto *) +wire [Y_WIDTH-1:0] BX = B_buf; +wire [Y_WIDTH:0] ALM_CARRY; + +// Start of carry chain +generate + if (_TECHMAP_CONSTMSK_CI_ == 1) begin + assign ALM_CARRY[0] = _TECHMAP_CONSTVAL_CI_; + end else begin + MISTRAL_ALUT_ARITH #( + .LUT0(16'b1010_1010_1010_1010), // Q = A + .LUT1(16'b0000_0000_0000_0000), // Q = 0 (LUT1's input to the adder is inverted) + ) alm_start ( + .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1), + .CI(1'b0), + .CO(ALM_CARRY[0]) + ); + end +endgenerate + +// Carry chain +genvar i; +generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice + // TODO: mwk suggests that a pass could merge pre-adder logic into this. + MISTRAL_ALUT_ARITH #( + .LUT0(16'b1010_1010_1010_1010), // Q = A + .LUT1(16'b1100_0011_1100_0011), // Q = C ? B : ~B (LUT1's input to the adder is inverted) + ) alm_i ( + .A(AA[i]), .B(BX[i]), .C(BI), .D0(1'b1), .D1(1'b1), + .CI(ALM_CARRY[i]), + .SO(Y[i]), + .CO(ALM_CARRY[i+1]) + ); + + // ALM carry chain is not directly accessible, so calculate the carry through soft logic if really needed. + assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i])); +end endgenerate + +assign X = AA ^ BB; + +endmodule diff --git a/techlibs/intel_le/common/bram_m10k.txt b/techlibs/intel_le/common/bram_m10k.txt new file mode 100644 index 000000000..e9355fe2c --- /dev/null +++ b/techlibs/intel_le/common/bram_m10k.txt @@ -0,0 +1,33 @@ +bram MISTRAL_M10K + init 0 # TODO: Re-enable when I figure out how BRAM init works + abits 13 @D8192x1 + dbits 1 @D8192x1 + abits 12 @D4096x2 + dbits 2 @D4096x2 + abits 11 @D2048x4 @D2048x5 + dbits 4 @D2048x4 + dbits 5 @D2048x5 + abits 10 @D1024x8 @D1024x10 + dbits 8 @D1024x8 + dbits 10 @D1024x10 + abits 9 @D512x16 @D512x20 + dbits 16 @D512x16 + dbits 20 @D512x20 + abits 8 @D256x32 @D256x40 + dbits 32 @D256x32 + dbits 40 @D256x40 + groups 2 + ports 1 1 + wrmode 1 0 + # read enable; write enable + byte enables (only for multiples of 8) + enable 1 1 + transp 0 0 + clocks 1 1 + clkpol 1 1 +endbram + + +match MISTRAL_M10K + min efficiency 5 + make_transp +endmatch diff --git a/techlibs/intel_le/common/bram_m20k.txt b/techlibs/intel_le/common/bram_m20k.txt new file mode 100644 index 000000000..b4c5a5372 --- /dev/null +++ b/techlibs/intel_le/common/bram_m20k.txt @@ -0,0 +1,33 @@ +bram __MISTRAL_M20K_SDP + init 1 # TODO: Re-enable when I figure out how BRAM init works + abits 14 @D16384x1 + dbits 1 @D16384x1 + abits 13 @D8192x2 + dbits 2 @D8192x2 + abits 12 @D4096x4 @D4096x5 + dbits 4 @D4096x4 + dbits 5 @D4096x5 + abits 11 @D2048x8 @D2048x10 + dbits 8 @D2048x8 + dbits 10 @D2048x10 + abits 10 @D1024x16 @D1024x20 + dbits 16 @D1024x16 + dbits 20 @D1024x20 + abits 9 @D512x32 @D512x40 + dbits 32 @D512x32 + dbits 40 @D512x40 + groups 2 + ports 1 1 + wrmode 1 0 + # read enable; write enable + byte enables (only for multiples of 8) + enable 1 1 + transp 0 0 + clocks 1 1 + clkpol 1 1 +endbram + + +match __MISTRAL_M20K_SDP + min efficiency 5 + make_transp +endmatch diff --git a/techlibs/intel_le/common/bram_m20k_map.v b/techlibs/intel_le/common/bram_m20k_map.v new file mode 100644 index 000000000..92f41310f --- /dev/null +++ b/techlibs/intel_le/common/bram_m20k_map.v @@ -0,0 +1,31 @@ +module __MISTRAL_M20K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); + +parameter CFG_ABITS = 10; +parameter CFG_DBITS = 20; +parameter CFG_ENABLE_A = 1; +parameter CFG_ENABLE_B = 1; + +input CLK1; +input [CFG_ABITS-1:0] A1ADDR, B1ADDR; +input [CFG_DBITS-1:0] A1DATA; +output [CFG_DBITS-1:0] B1DATA; +input [CFG_ENABLE_A-1:0] A1EN, B1EN; + +altsyncram #( + .operation_mode("dual_port"), + .ram_block_type("m20k"), + .widthad_a(CFG_ABITS), + .width_a(CFG_DBITS), + .widthad_b(CFG_ABITS), + .width_b(CFG_DBITS), +) _TECHMAP_REPLACE_ ( + .address_a(A1ADDR), + .data_a(A1DATA), + .wren_a(A1EN), + .address_b(B1ADDR), + .q_b(B1DATA), + .clock0(CLK1), + .clock1(CLK1) +); + +endmodule diff --git a/techlibs/intel_le/common/dff_map.v b/techlibs/intel_le/common/dff_map.v new file mode 100644 index 000000000..1a4b5d65a --- /dev/null +++ b/techlibs/intel_le/common/dff_map.v @@ -0,0 +1,13 @@ +`default_nettype none + +// D flip-flop with async reset and enable +module \$_DFFE_PN0P_ (input D, C, R, E, output Q); + wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; + MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(R), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +endmodule + +// D flip-flop with sync reset and enable (enable has priority) +module \$_SDFFCE_PP0P_ (input D, C, R, E, output Q); + wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; + MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(E), .SCLR(R), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +endmodule diff --git a/techlibs/intel_le/common/dff_sim.v b/techlibs/intel_le/common/dff_sim.v new file mode 100644 index 000000000..d2cff0adb --- /dev/null +++ b/techlibs/intel_le/common/dff_sim.v @@ -0,0 +1,114 @@ +// The four D flip-flops (DFFs) in a Cyclone V/10GX Adaptive Logic Module (ALM) +// act as one-bit memory cells that can be placed very flexibly (wherever there's +// an ALM); each flop is represented by a MISTRAL_FF cell. +// +// The flops in these chips are rather flexible in some ways, but in practice +// quite crippled by FPGA standards. +// +// What the flops can do +// --------------------- +// The core flop acts as a single-bit memory that initialises to zero at chip +// reset. It takes in data on the rising edge of CLK if ENA is high, +// and outputs it to Q. The ENA (clock enable) pin can therefore be used to +// capture the input only if a condition is true. +// +// The data itself is zero if SCLR (synchronous clear) is high, else it comes +// from SDATA (synchronous data) if SLOAD (synchronous load) is high, or DATAIN +// if SLOAD is low. +// +// If ACLR (asynchronous clear) is low then Q is forced to zero, regardless of +// the synchronous inputs or CLK edge. This is most often used for an FPGA-wide +// power-on reset. +// +// An asynchronous set that sets Q to one can be emulated by inverting the input +// and output of the flop, resulting in ACLR forcing Q to zero, which then gets +// inverted to produce one. Likewise, logic can operate on the falling edge of +// CLK if CLK is inverted before being passed as an input. +// +// What the flops *can't* do +// ------------------------- +// The trickiest part of the above capabilities is the lack of configurable +// initialisation state. For example, it isn't possible to implement a flop with +// asynchronous clear that initialises to one, because the hardware initialises +// to zero. Likewise, you can't emulate a flop with asynchronous set that +// initialises to zero, because the inverters mean the flop initialises to one. +// +// If the input design requires one of these cells (which appears to be rare +// in practice) then synth_intel_alm will fail to synthesize the design where +// other Yosys synthesis scripts might succeed. +// +// This stands in notable contrast to e.g. Xilinx flip-flops, which have +// configurable initialisation state and native synchronous/asynchronous +// set/clear (although not at the same time), which means they can generally +// implement a much wider variety of logic. + +// DATAIN: synchronous data input +// CLK: clock input (positive edge) +// ACLR: asynchronous clear (negative-true) +// ENA: clock-enable +// SCLR: synchronous clear +// SLOAD: synchronous load +// SDATA: synchronous load data +// +// Q: data output +// +// Note: the DFFEAS primitive is mostly emulated; it does not reflect what the hardware implements. + +(* abc9_box, lib_whitebox *) +module MISTRAL_FF( + input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA, + output reg Q +); + +`ifdef cyclonev +specify + if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 731; + if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 890; + if (ENA && !SCLR && SLOAD) (posedge CLK => (Q : SDATA)) = 618; + + $setup(DATAIN, posedge CLK, /* -196 */ 0); + $setup(ENA, posedge CLK, /* -196 */ 0); + $setup(SCLR, posedge CLK, /* -196 */ 0); + $setup(SLOAD, posedge CLK, /* -196 */ 0); + $setup(SDATA, posedge CLK, /* -196 */ 0); + + if (ACLR === 1'b0) (ACLR => Q) = 282; +endspecify +`endif +`ifdef cyclone10gx +specify + // TODO (long-term): investigate these numbers. + // It seems relying on the Quartus Timing Analyzer was not the best idea; it's too fiddly. + if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 219; + if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 219; + if (ENA && !SCLR && SLOAD) (posedge CLK => (Q : SDATA)) = 219; + + $setup(DATAIN, posedge CLK, 268); + $setup(ENA, posedge CLK, 268); + $setup(SCLR, posedge CLK, 268); + $setup(SLOAD, posedge CLK, 268); + $setup(SDATA, posedge CLK, 268); + + if (ACLR === 1'b0) (ACLR => Q) = 0; +endspecify +`endif + +initial begin + // Altera flops initialise to zero. + Q = 0; +end + +always @(posedge CLK, negedge ACLR) begin + // Asynchronous clear + if (!ACLR) Q <= 0; + // Clock-enable + else if (ENA) begin + // Synchronous clear + if (SCLR) Q <= 0; + // Synchronous load + else if (SLOAD) Q <= SDATA; + else Q <= DATAIN; + end +end + +endmodule diff --git a/techlibs/intel_le/common/dsp_map.v b/techlibs/intel_le/common/dsp_map.v new file mode 100644 index 000000000..e12e777a4 --- /dev/null +++ b/techlibs/intel_le/common/dsp_map.v @@ -0,0 +1,51 @@ +`default_nettype none + +module __MUL27X27(A, B, Y); + +parameter A_SIGNED = 1; +parameter B_SIGNED = 1; +parameter A_WIDTH = 27; +parameter B_WIDTH = 27; +parameter Y_WIDTH = 54; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +MISTRAL_MUL27X27 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); + +endmodule + + +module __MUL18X18(A, B, Y); + +parameter A_SIGNED = 1; +parameter B_SIGNED = 1; +parameter A_WIDTH = 18; +parameter B_WIDTH = 18; +parameter Y_WIDTH = 36; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +MISTRAL_MUL18X18 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); + +endmodule + + +module __MUL9X9(A, B, Y); + +parameter A_SIGNED = 1; +parameter B_SIGNED = 1; +parameter A_WIDTH = 9; +parameter B_WIDTH = 9; +parameter Y_WIDTH = 18; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +MISTRAL_MUL9X9 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); + +endmodule diff --git a/techlibs/intel_le/common/dsp_sim.v b/techlibs/intel_le/common/dsp_sim.v new file mode 100644 index 000000000..bdb6d18d5 --- /dev/null +++ b/techlibs/intel_le/common/dsp_sim.v @@ -0,0 +1,83 @@ +(* abc9_box *) +module MISTRAL_MUL27X27(input [26:0] A, input [26:0] B, output [53:0] Y); + +parameter A_SIGNED = 1; +parameter B_SIGNED = 1; + +// TODO: Cyclone 10 GX timings; the below are for Cyclone V +specify + (A *> Y) = 3732; + (B *> Y) = 3928; +endspecify + +wire [53:0] A_, B_; + +if (A_SIGNED) + assign A_ = $signed(A); +else + assign A_ = $unsigned(A); + +if (B_SIGNED) + assign B_ = $signed(B); +else + assign B_ = $unsigned(B); + +assign Y = A_ * B_; + +endmodule + +(* abc9_box *) +module MISTRAL_MUL18X18(input [17:0] A, input [17:0] B, output [35:0] Y); + +parameter A_SIGNED = 1; +parameter B_SIGNED = 1; + +// TODO: Cyclone 10 GX timings; the below are for Cyclone V +specify + (A *> Y) = 3180; + (B *> Y) = 3982; +endspecify + +wire [35:0] A_, B_; + +if (A_SIGNED) + assign A_ = $signed(A); +else + assign A_ = $unsigned(A); + +if (B_SIGNED) + assign B_ = $signed(B); +else + assign B_ = $unsigned(B); + +assign Y = A_ * B_; + +endmodule + +(* abc9_box *) +module MISTRAL_MUL9X9(input [8:0] A, input [8:0] B, output [17:0] Y); + +parameter A_SIGNED = 1; +parameter B_SIGNED = 1; + +// TODO: Cyclone 10 GX timings; the below are for Cyclone V +specify + (A *> Y) = 2818; + (B *> Y) = 3051; +endspecify + +wire [17:0] A_, B_; + +if (A_SIGNED) + assign A_ = $signed(A); +else + assign A_ = $unsigned(A); + +if (B_SIGNED) + assign B_ = $signed(B); +else + assign B_ = $unsigned(B); + +assign Y = A_ * B_; + +endmodule diff --git a/techlibs/intel_le/common/le_map.v b/techlibs/intel_le/common/le_map.v new file mode 100644 index 000000000..6697b2e78 --- /dev/null +++ b/techlibs/intel_le/common/le_map.v @@ -0,0 +1,57 @@ +module \$lut (A, Y); + +parameter WIDTH = 1; +parameter LUT = 0; + +(* force_downto *) +input [WIDTH-1:0] A; +output Y; + +generate + if (WIDTH == 1) begin + generate + if (LUT == 2'b00) begin + assign Y = 1'b0; + end + else if (LUT == 2'b01) begin + MISTRAL_NOT _TECHMAP_REPLACE_( + .A(A[0]), .Q(Y) + ); + end + else if (LUT == 2'b10) begin + assign Y = A; + end + else if (LUT == 2'b11) begin + assign Y = 1'b1; + end + endgenerate + end else + if (WIDTH == 2) begin + MISTRAL_ALUT2 #(.LUT(LUT)) _TECHMAP_REPLACE_( + .A(A[0]), .B(A[1]), .Q(Y) + ); + end else + if (WIDTH == 3) begin + MISTRAL_ALUT3 #(.LUT(LUT)) _TECHMAP_REPLACE_( + .A(A[0]), .B(A[1]), .C(A[2]), .Q(Y) + ); + end else + if (WIDTH == 4) begin + MISTRAL_ALUT4 #(.LUT(LUT)) _TECHMAP_REPLACE_( + .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .Q(Y) + ); + end else + if (WIDTH == 5) begin + MISTRAL_ALUT5 #(.LUT(LUT)) _TECHMAP_REPLACE_ ( + .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .Q(Y) + ); + end else + if (WIDTH == 6) begin + MISTRAL_ALUT6 #(.LUT(LUT)) _TECHMAP_REPLACE_ ( + .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .F(A[5]), .Q(Y) + ); + end else begin + wire _TECHMAP_FAIL_ = 1'b1; + end +endgenerate +endmodule diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v new file mode 100644 index 000000000..906a95b0b --- /dev/null +++ b/techlibs/intel_le/common/le_sim.v @@ -0,0 +1,561 @@ +// The core logic primitive of the Cyclone V/10GX is the Adaptive Logic Module +// (ALM). Each ALM is made up of an 8-input, 2-output look-up table, covered +// in this file, connected to combinational outputs, a carry chain, and four +// D flip-flops (which are covered as MISTRAL_FF in dff_sim.v). +// +// The ALM is vertically symmetric, so I find it helps to think in terms of +// half-ALMs, as that's predominantly the unit that synth_intel_alm uses. +// +// ALMs are quite flexible, having multiple modes. +// +// Normal (combinational) mode +// --------------------------- +// The ALM can implement: +// - a single 6-input function (with the other inputs usable for flip-flop access) +// - two 5-input functions that share two inputs +// - a 5-input and a 4-input function that share one input +// - a 5-input and a 3-or-less-input function that share no inputs +// - two 4-or-less-input functions that share no inputs +// +// Normal-mode functions are represented as MISTRAL_ALUTN cells with N inputs. +// It would be possible to represent a normal mode function as a single cell - +// the vendor cyclone{v,10gx}_lcell_comb cell does exactly that - but I felt +// it was more user-friendly to print out the specific function sizes +// separately. +// +// With the exception of MISTRAL_ALUT6, you can think of two normal-mode cells +// fitting inside a single ALM. +// +// Extended (7-input) mode +// ----------------------- +// The ALM can also fit a 7-input function made of two 5-input functions that +// share four inputs, multiplexed by another input. +// +// Because this can't accept arbitrary 7-input functions, Yosys can't handle +// it, so it doesn't have a cell, but I would likely call it MISTRAL_ALUT7(E?) +// if it did, and it would take up a full ALM. +// +// It might be possible to add an extraction pass to examine all ALUT5 cells +// that feed into ALUT3 cells to see if they can be combined into an extended +// ALM, but I don't think it will be worth it. +// +// Arithmetic mode +// --------------- +// In arithmetic mode, each half-ALM uses its carry chain to perform fast addition +// of two four-input functions that share three inputs. Oddly, the result of +// one of the functions is inverted before being added (you can see this as +// the dot on a full-adder input of Figure 1-8 in the Handbook). +// +// The cell for an arithmetic-mode half-ALM is MISTRAL_ALM_ARITH. One idea +// I've had (or rather was suggested by mwk) is that functions that feed into +// arithmetic-mode cells could be packed directly into the arithmetic-mode +// cell as a function, which reduces the number of ALMs needed. +// +// Shared arithmetic mode +// ---------------------- +// Shared arithmetic mode looks a lot like arithmetic mode, but here the +// output of every other four-input function goes to the input of the adder +// the next bit along. What this means is that adding three bits together can +// be done in an ALM, because functions can be used to implement addition that +// then feeds into the carry chain. This means that three bits can be added per +// ALM, as opposed to two in the arithmetic mode. +// +// Shared arithmetic mode doesn't currently have a cell, but I intend to add +// it as MISTRAL_ALM_SHARED, and have it occupy a full ALM. Because it adds +// three bits per cell, it makes addition shorter and use less ALMs, but +// I don't know enough to tell whether it's more efficient to use shared +// arithmetic mode to shorten the carry chain, or plain arithmetic mode with +// the functions packed in. + +`default_nettype none + +// Cyclone V LUT output timings (picoseconds): +// +// CARRY A B C D E F G +// COMBOUT - 605 583 510 512 - 97 400 (LUT6) +// COMBOUT - 602 583 457 510 302 93 483 (LUT7) +// SUMOUT 368 1342 1323 887 927 - 785 - +// CARRYOUT 71 1082 1062 866 813 - 1198 - + +(* abc9_lut=2, lib_whitebox *) +module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); + +parameter [63:0] LUT = 64'h0000_0000_0000_0000; + +`ifdef cyclonev +specify + (A => Q) = 605; + (B => Q) = 583; + (C => Q) = 510; + (D => Q) = 512; + (E => Q) = 400; + (F => Q) = 97; +endspecify +`endif +`ifdef cyclone10gx +specify + (A => Q) = 275; + (B => Q) = 272; + (C => Q) = 175; + (D => Q) = 165; + (E => Q) = 162; + (F => Q) = 53; +endspecify +`endif + +assign Q = LUT >> {F, E, D, C, B, A}; + +endmodule + + +(* abc9_lut=1, lib_whitebox *) +module MISTRAL_ALUT5(input A, B, C, D, E, output Q); + +parameter [31:0] LUT = 32'h0000_0000; + +`ifdef cyclonev +specify + (A => Q) = 583; + (B => Q) = 510; + (C => Q) = 512; + (D => Q) = 400; + (E => Q) = 97; +endspecify +`endif +`ifdef cyclone10gx +specify + (A => Q) = 272; + (B => Q) = 175; + (C => Q) = 165; + (D => Q) = 162; + (E => Q) = 53; +endspecify +`endif + +assign Q = LUT >> {E, D, C, B, A}; + +endmodule + + +(* abc9_lut=1, lib_whitebox *) +module MISTRAL_ALUT4(input A, B, C, D, output Q); + +parameter [15:0] LUT = 16'h0000; + +`ifdef cyclonev +specify + (A => Q) = 510; + (B => Q) = 512; + (C => Q) = 400; + (D => Q) = 97; +endspecify +`endif +`ifdef cyclone10gx +specify + (A => Q) = 175; + (B => Q) = 165; + (C => Q) = 162; + (D => Q) = 53; +endspecify +`endif + +assign Q = LUT >> {D, C, B, A}; + +endmodule + + +(* abc9_lut=1, lib_whitebox *) +module MISTRAL_ALUT3(input A, B, C, output Q); + +parameter [7:0] LUT = 8'h00; + +`ifdef cyclonev +specify + (A => Q) = 510; + (B => Q) = 400; + (C => Q) = 97; +endspecify +`endif +`ifdef cyclone10gx +specify + (A => Q) = 165; + (B => Q) = 162; + (C => Q) = 53; +endspecify +`endif + +assign Q = LUT >> {C, B, A}; + +endmodule + + +(* abc9_lut=1, lib_whitebox *) +module MISTRAL_ALUT2(input A, B, output Q); + +parameter [3:0] LUT = 4'h0; + +`ifdef cyclonev +specify + (A => Q) = 400; + (B => Q) = 97; +endspecify +`endif +`ifdef cyclone10gx +specify + (A => Q) = 162; + (B => Q) = 53; +endspecify +`endif + +assign Q = LUT >> {B, A}; + +endmodule + + +(* abc9_lut=1, lib_whitebox *) +module MISTRAL_NOT(input A, output Q); + +`ifdef cyclonev +specify + (A => Q) = 97; +endspecify +`endif +`ifdef cyclone10gx +specify + (A => Q) = 53; +endspecify +`endif + +assign Q = ~A; + +endmodule + +(* abc9_box, lib_whitebox *) +module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, (* abc9_carry *) input CI, output SO, (* abc9_carry *) output CO); + +parameter LUT0 = 16'h0000; +parameter LUT1 = 16'h0000; + +`ifdef cyclonev +specify + (A => SO) = 1342; + (B => SO) = 1323; + (C => SO) = 927; + (D0 => SO) = 887; + (D1 => SO) = 785; + (CI => SO) = 368; + + (A => CO) = 1082; + (B => CO) = 1062; + (C => CO) = 813; + (D0 => CO) = 866; + (D1 => CO) = 1198; + (CI => CO) = 36; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM) +endspecify +`endif +`ifdef cyclone10gx +specify + (A => SO) = 644; + (B => SO) = 477; + (C => SO) = 416; + (D0 => SO) = 380; + (D1 => SO) = 431; + (CI => SO) = 276; + + (A => CO) = 525; + (B => CO) = 433; + (C => CO) = 712; + (D0 => CO) = 653; + (D1 => CO) = 593; + (CI => CO) = 16; +endspecify +`endif + +wire q0, q1; + +assign q0 = LUT0 >> {D0, C, B, A}; +assign q1 = LUT1 >> {D1, C, B, A}; + +assign {CO, SO} = q0 + !q1 + CI; + +endmodule + + +/* +// A, B, C0, C1, E0, E1, F0, F1: data inputs +// CARRYIN: carry input +// SHAREIN: shared-arithmetic input +// CLK0, CLK1, CLK2: clock inputs +// +// COMB0, COMB1: combinational outputs +// FF0, FF1, FF2, FF3: DFF outputs +// SUM0, SUM1: adder outputs +// CARRYOUT: carry output +// SHAREOUT: shared-arithmetic output +module MISTRAL_ALM( + input A, B, C0, C1, E0, E1, F0, F1, CARRYIN, SHAREIN, // LUT path + input CLK0, CLK1, CLK2, AC0, AC1, // FF path + output COMB0, COMB1, SUM0, SUM1, CARRYOUT, SHAREOUT, + output FF0, FF1, FF2, FF3 +); + +parameter LUT0 = 16'b0000; +parameter LUT1 = 16'b0000; +parameter LUT2 = 16'b0000; +parameter LUT3 = 16'b0000; + +parameter INIT0 = 1'b0; +parameter INIT1 = 1'b0; +parameter INIT2 = 1'b0; +parameter INIT3 = 1'b0; + +parameter C0_MUX = "C0"; +parameter C1_MUX = "C1"; + +parameter F0_MUX = "VCC"; +parameter F1_MUX = "GND"; + +parameter FEEDBACK0 = "FF0"; +parameter FEEDBACK1 = "FF2"; + +parameter ADD_MUX = "LUT"; + +parameter DFF01_DATA_MUX = "COMB"; +parameter DFF23_DATA_MUX = "COMB"; + +parameter DFF0_CLK = "CLK0"; +parameter DFF1_CLK = "CLK0"; +parameter DFF2_CLK = "CLK0"; +parameter DFF3_CLK = "CLK0"; + +parameter DFF0_AC = "AC0"; +parameter DFF1_AC = "AC0"; +parameter DFF2_AC = "AC0"; +parameter DFF3_AC = "AC0"; + +// Feedback muxes from the flip-flop outputs. +wire ff_feedback_mux0, ff_feedback_mux1; + +// C-input muxes which can be set to also use the F-input. +wire c0_input_mux, c1_input_mux; + +// F-input muxes which can be set to a constant to allow LUT5 use. +wire f0_input_mux, f1_input_mux; + +// Adder input muxes to select between shared-arithmetic mode and arithmetic mode. +wire add0_input_mux, add1_input_mux; + +// Combinational-output muxes for LUT #1 and LUT #3 +wire lut1_comb_mux, lut3_comb_mux; + +// Sum-output muxes for LUT #1 and LUT #3 +wire lut1_sum_mux, lut3_sum_mux; + +// DFF data-input muxes +wire dff01_data_mux, dff23_data_mux; + +// DFF clock selectors +wire dff0_clk, dff1_clk, dff2_clk, dff3_clk; + +// DFF asynchronous-clear selectors +wire dff0_ac, dff1_ac, dff2_ac, dff3_ac; + +// LUT, DFF and adder output wires for routing. +wire lut0_out, lut1a_out, lut1b_out, lut2_out, lut3a_out, lut3b_out; +wire dff0_out, dff1_out, dff2_out, dff3_out; +wire add0_sum, add1_sum, add0_carry, add1_carry; + +generate + if (FEEDBACK0 === "FF0") + assign ff_feedback_mux0 = dff0_out; + else if (FEEDBACK0 === "FF1") + assign ff_feedback_mux0 = dff1_out; + else + $error("Invalid FEEDBACK0 setting!"); + + if (FEEDBACK1 == "FF2") + assign ff_feedback_mux1 = dff2_out; + else if (FEEDBACK1 == "FF3") + assign ff_feedback_mux1 = dff3_out; + else + $error("Invalid FEEDBACK1 setting!"); + + if (C0_MUX === "C0") + assign c0_input_mux = C0; + else if (C0_MUX === "F1") + assign c0_input_mux = F1; + else if (C0_MUX === "FEEDBACK1") + assign c0_input_mux = ff_feedback_mux1; + else + $error("Invalid C0_MUX setting!"); + + if (C1_MUX === "C1") + assign c1_input_mux = C1; + else if (C1_MUX === "F0") + assign c1_input_mux = F0; + else if (C1_MUX === "FEEDBACK0") + assign c1_input_mux = ff_feedback_mux0; + else + $error("Invalid C1_MUX setting!"); + + // F0 == VCC is LUT5 + // F0 == F0 is LUT6 + // F0 == FEEDBACK is unknown + if (F0_MUX === "VCC") + assign f0_input_mux = 1'b1; + else if (F0_MUX === "F0") + assign f0_input_mux = F0; + else if (F0_MUX === "FEEDBACK0") + assign f0_input_mux = ff_feedback_mux0; + else + $error("Invalid F0_MUX setting!"); + + // F1 == GND is LUT5 + // F1 == F1 is LUT6 + // F1 == FEEDBACK is unknown + if (F1_MUX === "GND") + assign f1_input_mux = 1'b0; + else if (F1_MUX === "F1") + assign f1_input_mux = F1; + else if (F1_MUX === "FEEDBACK1") + assign f1_input_mux = ff_feedback_mux1; + else + $error("Invalid F1_MUX setting!"); + + if (ADD_MUX === "LUT") begin + assign add0_input_mux = ~lut1_sum_mux; + assign add1_input_mux = ~lut3_sum_mux; + end else if (ADD_MUX === "SHARE") begin + assign add0_input_mux = SHAREIN; + assign add1_input_mux = lut1_comb_mux; + end else + $error("Invalid ADD_MUX setting!"); + + if (DFF01_DATA_MUX === "COMB") + assign dff01_data_mux = COMB0; + else if (DFF01_DATA_MUX === "SUM") + assign dff01_data_mux = SUM0; + else + $error("Invalid DFF01_DATA_MUX setting!"); + + if (DFF23_DATA_MUX === "COMB") + assign dff23_data_mux = COMB0; + else if (DFF23_DATA_MUX === "SUM") + assign dff23_data_mux = SUM0; + else + $error("Invalid DFF23_DATA_MUX setting!"); + + if (DFF0_CLK === "CLK0") + assign dff0_clk = CLK0; + else if (DFF0_CLK === "CLK1") + assign dff0_clk = CLK1; + else if (DFF0_CLK === "CLK2") + assign dff0_clk = CLK2; + else + $error("Invalid DFF0_CLK setting!"); + + if (DFF1_CLK === "CLK0") + assign dff1_clk = CLK0; + else if (DFF1_CLK === "CLK1") + assign dff1_clk = CLK1; + else if (DFF1_CLK === "CLK2") + assign dff1_clk = CLK2; + else + $error("Invalid DFF1_CLK setting!"); + + if (DFF2_CLK === "CLK0") + assign dff2_clk = CLK0; + else if (DFF2_CLK === "CLK1") + assign dff2_clk = CLK1; + else if (DFF2_CLK === "CLK2") + assign dff2_clk = CLK2; + else + $error("Invalid DFF2_CLK setting!"); + + if (DFF3_CLK === "CLK0") + assign dff3_clk = CLK0; + else if (DFF3_CLK === "CLK1") + assign dff3_clk = CLK1; + else if (DFF3_CLK === "CLK2") + assign dff3_clk = CLK2; + else + $error("Invalid DFF3_CLK setting!"); + + if (DFF0_AC === "AC0") + assign dff0_ac = AC0; + else if (DFF0_AC === "AC1") + assign dff0_ac = AC1; + else + $error("Invalid DFF0_AC setting!"); + + if (DFF1_AC === "AC0") + assign dff1_ac = AC0; + else if (DFF1_AC === "AC1") + assign dff1_ac = AC1; + else + $error("Invalid DFF1_AC setting!"); + + if (DFF2_AC === "AC0") + assign dff2_ac = AC0; + else if (DFF2_AC === "AC1") + assign dff2_ac = AC1; + else + $error("Invalid DFF2_AC setting!"); + + if (DFF3_AC === "AC0") + assign dff3_ac = AC0; + else if (DFF3_AC === "AC1") + assign dff3_ac = AC1; + else + $error("Invalid DFF3_AC setting!"); + +endgenerate + +// F0 on the Quartus diagram +MISTRAL_ALUT4 #(.LUT(LUT0)) lut0 (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut0_out)); + +// F2 on the Quartus diagram +MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_comb (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut1_comb_mux)); +MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_sum (.A(A), .B(B), .C(C0), .D(E0), .Q(lut1_sum_mux)); + +// F1 on the Quartus diagram +MISTRAL_ALUT4 #(.LUT(LUT2)) lut2 (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut2_out)); + +// F3 on the Quartus diagram +MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_comb (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut3_comb_mux)); +MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_sum (.A(A), .B(B), .C(C1), .D(E1), .Q(lut3_sum_mux)); + +MISTRAL_FF #(.INIT(INIT0)) dff0 (.D(dff01_data_mux), .CLK(dff0_clk), .ACn(dff0_ac), .Q(dff0_out)); +MISTRAL_FF #(.INIT(INIT1)) dff1 (.D(dff01_data_mux), .CLK(dff1_clk), .ACn(dff1_ac), .Q(dff1_out)); +MISTRAL_FF #(.INIT(INIT2)) dff2 (.D(dff23_data_mux), .CLK(dff2_clk), .ACn(dff2_ac), .Q(dff2_out)); +MISTRAL_FF #(.INIT(INIT3)) dff3 (.D(dff23_data_mux), .CLK(dff3_clk), .ACn(dff3_ac), .Q(dff3_out)); + +// Adders +assign {add0_carry, add0_sum} = CARRYIN + lut0_out + lut1_sum_mux; +assign {add1_carry, add1_sum} = add0_carry + lut2_out + lut3_sum_mux; + +// COMBOUT outputs on the Quartus diagram +assign COMB0 = E0 ? (f0_input_mux ? lut3_comb_mux : lut1_comb_mux) + : (f0_input_mux ? lut2_out : lut0_out); + +assign COMB1 = E1 ? (f1_input_mux ? lut3_comb_mux : lut1_comb_mux) + : (f1_input_mux ? lut2_out : lut0_out); + +// SUMOUT output on the Quartus diagram +assign SUM0 = add0_sum; +assign SUM1 = add1_sum; + +// COUT output on the Quartus diagram +assign CARRYOUT = add1_carry; + +// SHAREOUT output on the Quartus diagram +assign SHAREOUT = lut3_comb_mux; + +// REGOUT outputs on the Quartus diagram +assign FF0 = dff0_out; +assign FF1 = dff1_out; +assign FF2 = dff2_out; +assign FF3 = dff3_out; + +endmodule +*/ diff --git a/techlibs/intel_le/common/lutram_mlab.txt b/techlibs/intel_le/common/lutram_mlab.txt new file mode 100644 index 000000000..3cc69399d --- /dev/null +++ b/techlibs/intel_le/common/lutram_mlab.txt @@ -0,0 +1,18 @@ +bram MISTRAL_MLAB + init 0 # TODO: Re-enable when Yosys remembers the original filename. + abits 5 + dbits 1 + groups 2 + ports 1 1 + wrmode 1 0 + # write enable + enable 1 0 + transp 0 0 + clocks 1 0 + clkpol 1 1 +endbram + +match MISTRAL_MLAB + min efficiency 5 + make_outreg +endmatch \ No newline at end of file diff --git a/techlibs/intel_le/common/megafunction_bb.v b/techlibs/intel_le/common/megafunction_bb.v new file mode 100644 index 000000000..874f293b1 --- /dev/null +++ b/techlibs/intel_le/common/megafunction_bb.v @@ -0,0 +1,629 @@ +// Intel megafunction declarations, to avoid Yosys complaining. +`default_nettype none + +(* blackbox *) +module altera_pll +#( + parameter reference_clock_frequency = "0 ps", + parameter fractional_vco_multiplier = "false", + parameter pll_type = "General", + parameter pll_subtype = "General", + parameter number_of_clocks = 1, + parameter operation_mode = "internal feedback", + parameter deserialization_factor = 4, + parameter data_rate = 0, + + parameter sim_additional_refclk_cycles_to_lock = 0, + parameter output_clock_frequency0 = "0 ps", + parameter phase_shift0 = "0 ps", + parameter duty_cycle0 = 50, + + parameter output_clock_frequency1 = "0 ps", + parameter phase_shift1 = "0 ps", + parameter duty_cycle1 = 50, + + parameter output_clock_frequency2 = "0 ps", + parameter phase_shift2 = "0 ps", + parameter duty_cycle2 = 50, + + parameter output_clock_frequency3 = "0 ps", + parameter phase_shift3 = "0 ps", + parameter duty_cycle3 = 50, + + parameter output_clock_frequency4 = "0 ps", + parameter phase_shift4 = "0 ps", + parameter duty_cycle4 = 50, + + parameter output_clock_frequency5 = "0 ps", + parameter phase_shift5 = "0 ps", + parameter duty_cycle5 = 50, + + parameter output_clock_frequency6 = "0 ps", + parameter phase_shift6 = "0 ps", + parameter duty_cycle6 = 50, + + parameter output_clock_frequency7 = "0 ps", + parameter phase_shift7 = "0 ps", + parameter duty_cycle7 = 50, + + parameter output_clock_frequency8 = "0 ps", + parameter phase_shift8 = "0 ps", + parameter duty_cycle8 = 50, + + parameter output_clock_frequency9 = "0 ps", + parameter phase_shift9 = "0 ps", + parameter duty_cycle9 = 50, + + + parameter output_clock_frequency10 = "0 ps", + parameter phase_shift10 = "0 ps", + parameter duty_cycle10 = 50, + + parameter output_clock_frequency11 = "0 ps", + parameter phase_shift11 = "0 ps", + parameter duty_cycle11 = 50, + + parameter output_clock_frequency12 = "0 ps", + parameter phase_shift12 = "0 ps", + parameter duty_cycle12 = 50, + + parameter output_clock_frequency13 = "0 ps", + parameter phase_shift13 = "0 ps", + parameter duty_cycle13 = 50, + + parameter output_clock_frequency14 = "0 ps", + parameter phase_shift14 = "0 ps", + parameter duty_cycle14 = 50, + + parameter output_clock_frequency15 = "0 ps", + parameter phase_shift15 = "0 ps", + parameter duty_cycle15 = 50, + + parameter output_clock_frequency16 = "0 ps", + parameter phase_shift16 = "0 ps", + parameter duty_cycle16 = 50, + + parameter output_clock_frequency17 = "0 ps", + parameter phase_shift17 = "0 ps", + parameter duty_cycle17 = 50, + + parameter clock_name_0 = "", + parameter clock_name_1 = "", + parameter clock_name_2 = "", + parameter clock_name_3 = "", + parameter clock_name_4 = "", + parameter clock_name_5 = "", + parameter clock_name_6 = "", + parameter clock_name_7 = "", + parameter clock_name_8 = "", + + parameter clock_name_global_0 = "false", + parameter clock_name_global_1 = "false", + parameter clock_name_global_2 = "false", + parameter clock_name_global_3 = "false", + parameter clock_name_global_4 = "false", + parameter clock_name_global_5 = "false", + parameter clock_name_global_6 = "false", + parameter clock_name_global_7 = "false", + parameter clock_name_global_8 = "false", + + parameter m_cnt_hi_div = 1, + parameter m_cnt_lo_div = 1, + parameter m_cnt_bypass_en = "false", + parameter m_cnt_odd_div_duty_en = "false", + parameter n_cnt_hi_div = 1, + parameter n_cnt_lo_div = 1, + parameter n_cnt_bypass_en = "false", + parameter n_cnt_odd_div_duty_en = "false", + parameter c_cnt_hi_div0 = 1, + parameter c_cnt_lo_div0 = 1, + parameter c_cnt_bypass_en0 = "false", + parameter c_cnt_in_src0 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en0 = "false", + parameter c_cnt_prst0 = 1, + parameter c_cnt_ph_mux_prst0 = 0, + parameter c_cnt_hi_div1 = 1, + parameter c_cnt_lo_div1 = 1, + parameter c_cnt_bypass_en1 = "false", + parameter c_cnt_in_src1 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en1 = "false", + parameter c_cnt_prst1 = 1, + parameter c_cnt_ph_mux_prst1 = 0, + parameter c_cnt_hi_div2 = 1, + parameter c_cnt_lo_div2 = 1, + parameter c_cnt_bypass_en2 = "false", + parameter c_cnt_in_src2 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en2 = "false", + parameter c_cnt_prst2 = 1, + parameter c_cnt_ph_mux_prst2 = 0, + parameter c_cnt_hi_div3 = 1, + parameter c_cnt_lo_div3 = 1, + parameter c_cnt_bypass_en3 = "false", + parameter c_cnt_in_src3 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en3 = "false", + parameter c_cnt_prst3 = 1, + parameter c_cnt_ph_mux_prst3 = 0, + parameter c_cnt_hi_div4 = 1, + parameter c_cnt_lo_div4 = 1, + parameter c_cnt_bypass_en4 = "false", + parameter c_cnt_in_src4 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en4 = "false", + parameter c_cnt_prst4 = 1, + parameter c_cnt_ph_mux_prst4 = 0, + parameter c_cnt_hi_div5 = 1, + parameter c_cnt_lo_div5 = 1, + parameter c_cnt_bypass_en5 = "false", + parameter c_cnt_in_src5 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en5 = "false", + parameter c_cnt_prst5 = 1, + parameter c_cnt_ph_mux_prst5 = 0, + parameter c_cnt_hi_div6 = 1, + parameter c_cnt_lo_div6 = 1, + parameter c_cnt_bypass_en6 = "false", + parameter c_cnt_in_src6 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en6 = "false", + parameter c_cnt_prst6 = 1, + parameter c_cnt_ph_mux_prst6 = 0, + parameter c_cnt_hi_div7 = 1, + parameter c_cnt_lo_div7 = 1, + parameter c_cnt_bypass_en7 = "false", + parameter c_cnt_in_src7 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en7 = "false", + parameter c_cnt_prst7 = 1, + parameter c_cnt_ph_mux_prst7 = 0, + parameter c_cnt_hi_div8 = 1, + parameter c_cnt_lo_div8 = 1, + parameter c_cnt_bypass_en8 = "false", + parameter c_cnt_in_src8 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en8 = "false", + parameter c_cnt_prst8 = 1, + parameter c_cnt_ph_mux_prst8 = 0, + parameter c_cnt_hi_div9 = 1, + parameter c_cnt_lo_div9 = 1, + parameter c_cnt_bypass_en9 = "false", + parameter c_cnt_in_src9 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en9 = "false", + parameter c_cnt_prst9 = 1, + parameter c_cnt_ph_mux_prst9 = 0, + parameter c_cnt_hi_div10 = 1, + parameter c_cnt_lo_div10 = 1, + parameter c_cnt_bypass_en10 = "false", + parameter c_cnt_in_src10 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en10 = "false", + parameter c_cnt_prst10 = 1, + parameter c_cnt_ph_mux_prst10 = 0, + parameter c_cnt_hi_div11 = 1, + parameter c_cnt_lo_div11 = 1, + parameter c_cnt_bypass_en11 = "false", + parameter c_cnt_in_src11 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en11 = "false", + parameter c_cnt_prst11 = 1, + parameter c_cnt_ph_mux_prst11 = 0, + parameter c_cnt_hi_div12 = 1, + parameter c_cnt_lo_div12 = 1, + parameter c_cnt_bypass_en12 = "false", + parameter c_cnt_in_src12 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en12 = "false", + parameter c_cnt_prst12 = 1, + parameter c_cnt_ph_mux_prst12 = 0, + parameter c_cnt_hi_div13 = 1, + parameter c_cnt_lo_div13 = 1, + parameter c_cnt_bypass_en13 = "false", + parameter c_cnt_in_src13 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en13 = "false", + parameter c_cnt_prst13 = 1, + parameter c_cnt_ph_mux_prst13 = 0, + parameter c_cnt_hi_div14 = 1, + parameter c_cnt_lo_div14 = 1, + parameter c_cnt_bypass_en14 = "false", + parameter c_cnt_in_src14 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en14 = "false", + parameter c_cnt_prst14 = 1, + parameter c_cnt_ph_mux_prst14 = 0, + parameter c_cnt_hi_div15 = 1, + parameter c_cnt_lo_div15 = 1, + parameter c_cnt_bypass_en15 = "false", + parameter c_cnt_in_src15 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en15 = "false", + parameter c_cnt_prst15 = 1, + parameter c_cnt_ph_mux_prst15 = 0, + parameter c_cnt_hi_div16 = 1, + parameter c_cnt_lo_div16 = 1, + parameter c_cnt_bypass_en16 = "false", + parameter c_cnt_in_src16 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en16 = "false", + parameter c_cnt_prst16 = 1, + parameter c_cnt_ph_mux_prst16 = 0, + parameter c_cnt_hi_div17 = 1, + parameter c_cnt_lo_div17 = 1, + parameter c_cnt_bypass_en17 = "false", + parameter c_cnt_in_src17 = "ph_mux_clk", + parameter c_cnt_odd_div_duty_en17 = "false", + parameter c_cnt_prst17 = 1, + parameter c_cnt_ph_mux_prst17 = 0, + parameter pll_vco_div = 1, + parameter pll_slf_rst = "false", + parameter pll_bw_sel = "low", + parameter pll_output_clk_frequency = "0 MHz", + parameter pll_cp_current = 0, + parameter pll_bwctrl = 0, + parameter pll_fractional_division = 1, + parameter pll_fractional_cout = 24, + parameter pll_dsm_out_sel = "1st_order", + parameter mimic_fbclk_type = "gclk", + parameter pll_fbclk_mux_1 = "glb", + parameter pll_fbclk_mux_2 = "fb_1", + parameter pll_m_cnt_in_src = "ph_mux_clk", + parameter pll_vcoph_div = 1, + parameter refclk1_frequency = "0 MHz", + parameter pll_clkin_0_src = "clk_0", + parameter pll_clkin_1_src = "clk_0", + parameter pll_clk_loss_sw_en = "false", + parameter pll_auto_clk_sw_en = "false", + parameter pll_manu_clk_sw_en = "false", + parameter pll_clk_sw_dly = 0, + parameter pll_extclk_0_cnt_src = "pll_extclk_cnt_src_vss", + parameter pll_extclk_1_cnt_src = "pll_extclk_cnt_src_vss" +) ( + //input + input refclk, + input refclk1, + input fbclk, + input rst, + input phase_en, + input updn, + input [2:0] num_phase_shifts, + input scanclk, + input [4:0] cntsel, + input [63:0] reconfig_to_pll, + input extswitch, + input adjpllin, + input cclk, + + //output + output [ number_of_clocks -1 : 0] outclk, + output fboutclk, + output locked, + output phase_done, + output [63:0] reconfig_from_pll, + output activeclk, + output [1:0] clkbad, + output [7:0] phout, + output [1:0] lvds_clk, + output [1:0] loaden, + output [1:0] extclk_out, + output [ number_of_clocks -1 : 0] cascade_out, + + //inout + inout zdbfbclk +); + +endmodule + + +(* blackbox *) +module altera_std_synchronizer(clk, din, dout, reset_n); + +parameter depth = 2; + +input clk; +input reset_n; +input din; +output dout; + +endmodule + +(* blackbox *) +module altddio_in ( + datain, // required port, DDR input data + inclock, // required port, input reference clock to sample data by + inclocken, // enable data clock + aset, // asynchronous set + aclr, // asynchronous clear + sset, // synchronous set + sclr, // synchronous clear + dataout_h, // data sampled at the rising edge of inclock + dataout_l // data sampled at the falling edge of inclock +); + +parameter width = 1; +parameter power_up_high = "OFF"; +parameter invert_input_clocks = "OFF"; +parameter intended_device_family = "Stratix"; +parameter lpm_type = "altddio_in"; +parameter lpm_hint = "UNUSED"; + +input [width-1:0] datain; +input inclock; +input inclocken; +input aset; +input aclr; +input sset; +input sclr; + +output [width-1:0] dataout_h; +output [width-1:0] dataout_l; + +endmodule + + +(* blackbox *) +module altddio_out ( + datain_h, + datain_l, + outclock, + outclocken, + aset, + aclr, + sset, + sclr, + oe, + dataout, + oe_out +); + +parameter width = 1; +parameter power_up_high = "OFF"; +parameter oe_reg = "UNUSED"; +parameter extend_oe_disable = "UNUSED"; +parameter intended_device_family = "Stratix"; +parameter invert_output = "OFF"; +parameter lpm_type = "altddio_out"; +parameter lpm_hint = "UNUSED"; + +input [width-1:0] datain_h; +input [width-1:0] datain_l; +input outclock; +input outclocken; +input aset; +input aclr; +input sset; +input sclr; +input oe; + +output [width-1:0] dataout; +output [width-1:0] oe_out; + +endmodule + + +(* blackbox *) +module altddio_bidir ( + datain_h, + datain_l, + inclock, + inclocken, + outclock, + outclocken, + aset, + aclr, + sset, + sclr, + oe, + dataout_h, + dataout_l, + combout, + oe_out, + dqsundelayedout, + padio +); + +// GLOBAL PARAMETER DECLARATION +parameter width = 1; // required parameter +parameter power_up_high = "OFF"; +parameter oe_reg = "UNUSED"; +parameter extend_oe_disable = "UNUSED"; +parameter implement_input_in_lcell = "UNUSED"; +parameter invert_output = "OFF"; +parameter intended_device_family = "Stratix"; +parameter lpm_type = "altddio_bidir"; +parameter lpm_hint = "UNUSED"; + +// INPUT PORT DECLARATION +input [width-1:0] datain_h; +input [width-1:0] datain_l; +input inclock; +input inclocken; +input outclock; +input outclocken; +input aset; +input aclr; +input sset; +input sclr; +input oe; + +// OUTPUT PORT DECLARATION +output [width-1:0] dataout_h; +output [width-1:0] dataout_l; +output [width-1:0] combout; +output [width-1:0] oe_out; +output [width-1:0] dqsundelayedout; +// BIDIRECTIONAL PORT DECLARATION +inout [width-1:0] padio; + +endmodule + + +(* blackbox *) +module altiobuf_in(datain, dataout); + +parameter enable_bus_hold = "FALSE"; +parameter use_differential_mode = "FALSE"; +parameter number_of_channels = 1; + +input [number_of_channels-1:0] datain; +output [number_of_channels-1:0] dataout; + +endmodule + +(* blackbox *) +module altiobuf_out(datain, dataout); + +parameter enable_bus_hold = "FALSE"; +parameter use_differential_mode = "FALSE"; +parameter use_oe = "FALSE"; +parameter number_of_channels = 1; + +input [number_of_channels-1:0] datain; +output [number_of_channels-1:0] dataout; + +endmodule + +(* blackbox *) +module altiobuf_bidir(dataio, oe, datain, dataout); + +parameter number_of_channels = 1; +parameter enable_bus_hold = "OFF"; + +inout [number_of_channels-1:0] dataio; +input [number_of_channels-1:0] datain; +output [number_of_channels-1:0] dataout; +input [number_of_channels-1:0] oe; + +endmodule + +(* blackbox *) +module altsyncram(clock0, clock1, address_a, data_a, rden_a, wren_a, byteena_a, q_a, addressstall_a, address_b, data_b, rden_b, wren_b, byteena_b, q_b, addressstall_b, clocken0, clocken1, clocken2, clocken3, aclr0, aclr1, eccstatus); + +parameter lpm_type = "altsyncram"; +parameter operation_mode = "dual_port"; +parameter ram_block_type = "auto"; +parameter intended_device_family = "auto"; +parameter power_up_uninitialized = "false"; +parameter read_during_write_mode_mixed_ports = "dontcare"; +parameter byte_size = 8; +parameter widthad_a = 1; +parameter width_a = 1; +parameter width_byteena_a = 1; +parameter numwords_a = 1; +parameter clock_enable_input_a = "clocken0"; +parameter widthad_b = 1; +parameter width_b = 1; +parameter numwords_b = 1; +parameter address_aclr_b = "aclr0"; +parameter address_reg_b = ""; +parameter outdata_aclr_b = "aclr0"; +parameter outdata_reg_b = ""; +parameter clock_enable_input_b = "clocken0"; +parameter clock_enable_output_b = "clocken0"; + +input clock0, clock1; +input [widthad_a-1:0] address_a; +input [width_a-1:0] data_a; +input rden_a; +input wren_a; +input [(width_a/8)-1:0] byteena_a; +input addressstall_a; + +output [width_a-1:0] q_a; + +input wren_b; +input rden_b; +input [widthad_b-1:0] address_b; +input [width_b-1:0] data_b; +input [(width_b/8)-1:0] byteena_b; +input addressstall_b; + +output [width_b-1:0] q_b; + +input clocken0; +input clocken1; +input clocken2; +input clocken3; + +input aclr0; +input aclr1; + +output eccstatus; + +endmodule + +(* blackbox *) +module cyclonev_mlab_cell(portaaddr, portadatain, portbaddr, portbdataout, ena0, clk0, clk1); + +parameter logical_ram_name = ""; +parameter logical_ram_depth = 32; +parameter logical_ram_width = 20; +parameter mixed_port_feed_through_mode = "new"; +parameter first_bit_number = 0; +parameter first_address = 0; +parameter last_address = 31; +parameter address_width = 5; +parameter data_width = 1; +parameter byte_enable_mask_width = 1; +parameter port_b_data_out_clock = "NONE"; +parameter [639:0] mem_init0 = 640'b0; + +input [address_width-1:0] portaaddr, portbaddr; +input [data_width-1:0] portadatain; +output [data_width-1:0] portbdataout; +input ena0, clk0, clk1; + +endmodule + +(* blackbox *) +module cyclonev_mac(ax, ay, resulta); + +parameter ax_width = 9; +parameter signed_max = "true"; +parameter ay_scan_in_width = 9; +parameter signed_may = "true"; +parameter result_a_width = 18; +parameter operation_mode = "M9x9"; + +input [ax_width-1:0] ax; +input [ay_scan_in_width-1:0] ay; +output [result_a_width-1:0] resulta; + +endmodule + +(* blackbox *) +module cyclone10gx_mac(ax, ay, resulta); + +parameter ax_width = 18; +parameter signed_max = "true"; +parameter ay_scan_in_width = 18; +parameter signed_may = "true"; +parameter result_a_width = 36; +parameter operation_mode = "M18X18_FULL"; + +input [ax_width-1:0] ax; +input [ay_scan_in_width-1:0] ay; +output [result_a_width-1:0] resulta; + +endmodule + +(* blackbox *) +module cyclonev_ram_block(portaaddr, portadatain, portawe, portbaddr, portbdataout, portbre, clk0); + +parameter operation_mode = "dual_port"; +parameter logical_ram_name = ""; +parameter port_a_address_width = 10; +parameter port_a_data_width = 10; +parameter port_a_logical_ram_depth = 1024; +parameter port_a_logical_ram_width = 10; +parameter port_a_first_address = 0; +parameter port_a_last_address = 1023; +parameter port_a_first_bit_number = 0; +parameter port_b_address_width = 10; +parameter port_b_data_width = 10; +parameter port_b_logical_ram_depth = 1024; +parameter port_b_logical_ram_width = 10; +parameter port_b_first_address = 0; +parameter port_b_last_address = 1023; +parameter port_b_first_bit_number = 0; +parameter port_b_address_clock = "clock0"; +parameter port_b_read_enable_clock = "clock0"; +parameter mem_init0 = ""; +parameter mem_init1 = ""; +parameter mem_init2 = ""; +parameter mem_init3 = ""; +parameter mem_init4 = ""; + +input [port_a_address_width-1:0] portaaddr; +input [port_b_address_width-1:0] portbaddr; +input [port_a_data_width-1:0] portadatain; +output [port_b_data_width-1:0] portbdataout; +input clk0, portawe, portbre; + +endmodule diff --git a/techlibs/intel_le/common/mem_sim.v b/techlibs/intel_le/common/mem_sim.v new file mode 100644 index 000000000..e09aafaa2 --- /dev/null +++ b/techlibs/intel_le/common/mem_sim.v @@ -0,0 +1,109 @@ +// The MLAB +// -------- +// In addition to Logic Array Blocks (LABs) that contain ten Adaptive Logic +// Modules (ALMs, see alm_sim.v), the Cyclone V/10GX also contain +// Memory/Logic Array Blocks (MLABs) that can act as either ten ALMs, or utilise +// the memory the ALM uses to store the look-up table data for general usage, +// producing a 32 address by 20-bit block of memory. MLABs are spread out +// around the chip, so they can be placed near where they are needed, rather than +// being comparatively limited in placement for a deep but narrow memory such as +// the M10K memory block. +// +// MLABs are used mainly for shallow but wide memories, such as CPU register +// files (which have perhaps 32 registers that are comparatively wide (16/32-bit)) +// or shift registers (by using the output of the Nth bit as input for the N+1th +// bit). +// +// Oddly, instead of providing a block 32 address by 20-bit cell, Quartus asks +// synthesis tools to build MLABs out of 32 address by 1-bit cells, and tries +// to put these cells in the same MLAB during cell placement. Because of this +// a MISTRAL_MLAB cell represents one of these 32 address by 1-bit cells, and +// 20 of them represent a physical MLAB. +// +// How the MLAB works +// ------------------ +// MLABs are poorly documented, so the following information is based mainly +// on the simulation model and my knowledge of how memories like these work. +// Additionally, note that the ports of MISTRAL_MLAB are the ones auto-generated +// by the Yosys `memory_bram` pass, and it doesn't make sense to me to use +// `techmap` just for the sake of renaming the cell ports. +// +// The MLAB can be initialised to any value, but unfortunately Quartus only +// allows memory initialisation from a file. Since Yosys doesn't preserve input +// file information, or write the contents of an `initial` block to a file, +// Yosys can't currently initialise the MLAB in a way Quartus will accept. +// +// The MLAB takes in data from A1DATA at the rising edge of CLK1, and if A1EN +// is high, writes it to the address in A1ADDR. A1EN can therefore be used to +// conditionally write data to the MLAB. +// +// Simultaneously, the MLAB reads data from B1ADDR, and outputs it to B1DATA, +// asynchronous to CLK1 and ignoring A1EN. If a synchronous read is needed +// then the output can be fed to embedded flops. Presently, Yosys assumes +// Quartus will pack external flops into the MLAB, but this is an assumption +// that needs testing. + +// The vendor sim model outputs 'x for a very short period (a few +// combinational delta cycles) after each write. This has been omitted from +// the following model because it's very difficult to trigger this in practice +// as clock cycles will be much longer than any potential blip of 'x, so the +// model can be treated as always returning a defined result. + +(* abc9_box, lib_whitebox *) +module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA); + +reg [31:0] mem = 32'b0; + +// TODO: Cyclone 10 GX timings; the below timings are for Cyclone V +specify + $setup(A1ADDR, posedge CLK1, 86); + $setup(A1DATA, posedge CLK1, 86); + $setup(A1EN, posedge CLK1, 86); + + (B1ADDR[0] => B1DATA) = 487; + (B1ADDR[1] => B1DATA) = 475; + (B1ADDR[2] => B1DATA) = 382; + (B1ADDR[3] => B1DATA) = 284; + (B1ADDR[4] => B1DATA) = 96; +endspecify + +always @(posedge CLK1) + if (A1EN) mem[A1ADDR] <= A1DATA; + +assign B1DATA = mem[B1ADDR]; + +endmodule + +// The M10K +// -------- +// TODO + +module MISTRAL_M10K(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); + +parameter CFG_ABITS = 10; +parameter CFG_DBITS = 10; + +input CLK1; +input [CFG_ABITS-1:0] A1ADDR, B1ADDR; +input [CFG_DBITS-1:0] A1DATA; +input A1EN, B1EN; +output reg [CFG_DBITS-1:0] B1DATA; + +reg [2**CFG_ABITS * CFG_DBITS - 1 : 0] mem = 0; + +specify + $setup(A1ADDR, posedge CLK1, 0); + $setup(A1DATA, posedge CLK1, 0); + + if (B1EN) (posedge CLK1 => (B1DATA : A1DATA)) = 0; +endspecify + +always @(posedge CLK1) begin + if (A1EN) + mem[(A1ADDR + 1) * CFG_DBITS - 1 : A1ADDR * CFG_DBITS] <= A1DATA; + + if (B1EN) + B1DATA <= mem[(B1ADDR + 1) * CFG_DBITS - 1 : B1ADDR * CFG_DBITS]; +end + +endmodule diff --git a/techlibs/intel_le/common/quartus_rename.v b/techlibs/intel_le/common/quartus_rename.v new file mode 100644 index 000000000..3b4628675 --- /dev/null +++ b/techlibs/intel_le/common/quartus_rename.v @@ -0,0 +1,235 @@ +`ifdef cyclonev +`define LCELL cyclonev_lcell_comb +`define MAC cyclonev_mac +`define MLAB cyclonev_mlab_cell +`endif +`ifdef cyclone10gx +`define LCELL cyclone10gx_lcell_comb +`define MAC cyclone10gx_mac +`define MLAB cyclone10gx_mlab_cell +`endif + +module __MISTRAL_VCC(output Q); + +MISTRAL_ALUT2 #(.LUT(4'b1111)) _TECHMAP_REPLACE_ (.A(1'b1), .B(1'b1), .Q(Q)); + +endmodule + + +module __MISTRAL_GND(output Q); + +MISTRAL_ALUT2 #(.LUT(4'b0000)) _TECHMAP_REPLACE_ (.A(1'b1), .B(1'b1), .Q(Q)); + +endmodule + + +module MISTRAL_FF(input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA, output reg Q); + +dffeas #(.power_up("low"), .is_wysiwyg("true")) _TECHMAP_REPLACE_ (.d(DATAIN), .clk(CLK), .clrn(ACLR), .ena(ENA), .sclr(SCLR), .sload(SLOAD), .asdata(SDATA), .q(Q)); + +endmodule + + +module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); +parameter [63:0] LUT = 64'h0000_0000_0000_0000; + +`LCELL #(.lut_mask(LUT)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .dataf(F), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT5(input A, B, C, D, E, output Q); +parameter [31:0] LUT = 32'h0000_0000; + +`LCELL #(.lut_mask({2{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT4(input A, B, C, D, output Q); +parameter [15:0] LUT = 16'h0000; + +`LCELL #(.lut_mask({4{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT3(input A, B, C, output Q); +parameter [7:0] LUT = 8'h00; + +`LCELL #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT2(input A, B, output Q); +parameter [3:0] LUT = 4'h0; + +`LCELL #(.lut_mask({16{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); + +endmodule + + +module MISTRAL_NOT(input A, output Q); + +NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q)); + +endmodule + + +module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, CI, output SO, CO); +parameter LUT0 = 16'h0000; +parameter LUT1 = 16'h0000; + +`LCELL #(.lut_mask({16'h0, LUT1, 16'h0, LUT0})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D0), .dataf(D1), .cin(CI), .sumout(SO), .cout(CO)); + +endmodule + + +module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA); + +parameter _TECHMAP_CELLNAME_ = ""; + +// Here we get to an unfortunate situation. The cell has a mem_init0 parameter, +// which takes in a hexadecimal string that could be used to initialise RAM. +// In the vendor simulation models, this appears to work fine, but Quartus, +// either intentionally or not, forgets about this parameter and initialises the +// RAM to zero. +// +// Because of this, RAM initialisation is presently disabled, but the source +// used to generate mem_init0 is kept (commented out) in case this gets fixed +// or an undocumented way to get Quartus to initialise from mem_init0 is found. + +`MLAB #( + .logical_ram_name(_TECHMAP_CELLNAME_), + .logical_ram_depth(32), + .logical_ram_width(1), + .mixed_port_feed_through_mode("Dont Care"), + .first_bit_number(0), + .first_address(0), + .last_address(31), + .address_width(5), + .data_width(1), + .byte_enable_mask_width(1), + .port_b_data_out_clock("NONE"), + // .mem_init0($sformatf("%08x", INIT)) +) _TECHMAP_REPLACE_ ( + .portaaddr(A1ADDR), + .portadatain(A1DATA), + .portbaddr(B1ADDR), + .portbdataout(B1DATA), + .ena0(A1EN), + .clk0(CLK1) +); + +endmodule + + +module MISTRAL_M10K(A1ADDR, A1DATA, A1EN, CLK1, B1ADDR, B1DATA, B1EN); + +parameter CFG_ABITS = 10; +parameter CFG_DBITS = 10; + +parameter _TECHMAP_CELLNAME_ = ""; + +input [CFG_ABITS-1:0] A1ADDR, B1ADDR; +input [CFG_DBITS-1:0] A1DATA; +input CLK1, A1EN, B1EN; +output [CFG_DBITS-1:0] B1DATA; + +// Much like the MLAB, the M10K has mem_init[01234] parameters which would let +// you initialise the RAM cell via hex literals. If they were implemented. + +cyclonev_ram_block #( + .operation_mode("dual_port"), + .logical_ram_name(_TECHMAP_CELLNAME_), + .port_a_address_width(CFG_ABITS), + .port_a_data_width(CFG_DBITS), + .port_a_logical_ram_depth(2**CFG_ABITS), + .port_a_logical_ram_width(CFG_DBITS), + .port_a_first_address(0), + .port_a_last_address(2**CFG_ABITS - 1), + .port_a_first_bit_number(0), + .port_b_address_width(CFG_ABITS), + .port_b_data_width(CFG_DBITS), + .port_b_logical_ram_depth(2**CFG_ABITS), + .port_b_logical_ram_width(CFG_DBITS), + .port_b_first_address(0), + .port_b_last_address(2**CFG_ABITS - 1), + .port_b_first_bit_number(0), + .port_b_address_clock("clock0"), + .port_b_read_enable_clock("clock0") +) _TECHMAP_REPLACE_ ( + .portaaddr(A1ADDR), + .portadatain(A1DATA), + .portawe(A1EN), + .portbaddr(B1ADDR), + .portbdataout(B1DATA), + .portbre(B1EN), + .clk0(CLK1) +); + +endmodule + + +module MISTRAL_MUL27X27(input [26:0] A, B, output [53:0] Y); + +parameter A_SIGNED = 1; +parameter B_SIGNED = 1; + +`MAC #( + .ax_width(27), + .signed_max(A_SIGNED ? "true" : "false"), + .ay_scan_in_width(27), + .signed_may(B_SIGNED ? "true" : "false"), + .result_a_width(54), + .operation_mode("M27x27") +) _TECHMAP_REPLACE_ ( + .ax(A), + .ay(B), + .resulta(Y) +); + +endmodule + + +module MISTRAL_MUL18X18(input [17:0] A, B, output [35:0] Y); + +parameter A_SIGNED = 1; +parameter B_SIGNED = 1; + +`MAC #( + .ax_width(18), + .signed_max(A_SIGNED ? "true" : "false"), + .ay_scan_in_width(18), + .signed_may(B_SIGNED ? "true" : "false"), + .result_a_width(36), + .operation_mode("M18x18_FULL") +) _TECHMAP_REPLACE_ ( + .ax(A), + .ay(B), + .resulta(Y) +); + +endmodule + + +module MISTRAL_MUL9X9(input [8:0] A, B, output [17:0] Y); + +parameter A_SIGNED = 1; +parameter B_SIGNED = 1; + +`MAC #( + .ax_width(9), + .signed_max(A_SIGNED ? "true" : "false"), + .ay_scan_in_width(9), + .signed_may(B_SIGNED ? "true" : "false"), + .result_a_width(18), + .operation_mode("M9x9") +) _TECHMAP_REPLACE_ ( + .ax(A), + .ay(B), + .resulta(Y) +); + +endmodule diff --git a/techlibs/intel_le/cycloneiv/cells_sim.v b/techlibs/intel_le/cycloneiv/cells_sim.v new file mode 100644 index 000000000..f7abfaf14 --- /dev/null +++ b/techlibs/intel_le/cycloneiv/cells_sim.v @@ -0,0 +1,150 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +module VCC (output V); + assign V = 1'b1; +endmodule // VCC + +module GND (output G); + assign G = 1'b0; +endmodule // GND + +/* Altera Cyclone IV devices Input Buffer Primitive */ +module cyclonev_io_ibuf + (output o, input i, input ibar); + assign ibar = ibar; + assign o = i; +endmodule // cyclonev_io_ibuf + +/* Altera Cyclone IV devices Output Buffer Primitive */ +module cyclonev_io_obuf + (output o, input i, input oe); + assign o = i; + assign oe = oe; +endmodule // cyclonev_io_obuf + +/* Altera Cyclone V LUT Primitive */ +module cyclonev_lcell_comb + (output combout, cout, sumout, shareout, + input dataa, datab, datac, datad, + input datae, dataf, datag, cin, + input sharein); + + parameter lut_mask = 64'hFFFFFFFFFFFFFFFF; + parameter dont_touch = "off"; + parameter lpm_type = "cyclonev_lcell_comb"; + parameter shared_arith = "off"; + parameter extended_lut = "off"; + + // Internal variables + // Sub mask for fragmented LUTs + wire [15:0] mask_a, mask_b, mask_c, mask_d; + // Independent output for fragmented LUTs + wire output_0, output_1, output_2, output_3; + // Extended mode uses mux to define the output + wire mux_0, mux_1; + // Input for hold the shared LUT mode value + wire shared_lut_alm; + + // Simulation model of 4-input LUT + function lut4; + input [15:0] mask; + input dataa, datab, datac, datad; + reg [7:0] s3; + reg [3:0] s2; + reg [1:0] s1; + begin + s3 = datad ? mask[15:8] : mask[7:0]; + s2 = datac ? s3[7:4] : s3[3:0]; + s1 = datab ? s2[3:2] : s2[1:0]; + lut4 = dataa ? s1[1] : s1[0]; + end + endfunction // lut4 + + // Simulation model of 5-input LUT + function lut5; + input [31:0] mask; // wp-01003.pdf, page 3: "a 5-LUT can be built with two 4-LUTs and a multiplexer. + input dataa, datab, datac, datad, datae; + reg upper_lut_value; + reg lower_lut_value; + begin + upper_lut_value = lut4(mask[31:16], dataa, datab, datac, datad); + lower_lut_value = lut4(mask[15:0], dataa, datab, datac, datad); + lut5 = (datae) ? upper_lut_value : lower_lut_value; + end + endfunction // lut5 + + // Simulation model of 6-input LUT + function lut6; + input [63:0] mask; + input dataa, datab, datac, datad, datae, dataf; + reg upper_lut_value; + reg lower_lut_value; + reg out_0, out_1, out_2, out_3; + begin + upper_lut_value = lut5(mask[63:32], dataa, datab, datac, datad, datae); + lower_lut_value = lut5(mask[31:0], dataa, datab, datac, datad, datae); + lut6 = (dataf) ? upper_lut_value : lower_lut_value; + end + endfunction // lut6 + + assign {mask_a, mask_b, mask_c, mask_d} = {lut_mask[15:0], lut_mask[31:16], lut_mask[47:32], lut_mask[63:48]}; +`ifdef ADVANCED_ALM + always @(*) begin + if(extended_lut == "on") + shared_lut_alm = datag; + else + shared_lut_alm = datac; + // Build the ALM behaviour + out_0 = lut4(mask_a, dataa, datab, datac, datad); + out_1 = lut4(mask_b, dataa, datab, shared_lut_alm, datad); + out_2 = lut4(mask_c, dataa, datab, datac, datad); + out_3 = lut4(mask_d, dataa, datab, shared_lut_alm, datad); + end +`else + `ifdef DEBUG + initial $display("Advanced ALM lut combine is not implemented yet"); + `endif +`endif +endmodule // cyclonev_lcell_comb + + +/* Altera D Flip-Flop Primitive */ +module dffeas + (output q, + input d, clk, clrn, prn, ena, + input asdata, aload, sclr, sload); + + // Timing simulation is not covered + parameter power_up="dontcare"; + parameter is_wysiwyg="false"; + + reg q_tmp; + wire reset; + reg [7:0] debug_net; + + assign reset = (prn && sclr && ~clrn && ena); + assign q = q_tmp & 1'b1; + + always @(posedge clk, posedge aload) begin + if(reset) q_tmp <= 0; + else q_tmp <= d; + end + assign q = q_tmp; + +endmodule // dffeas diff --git a/techlibs/intel_le/synth_intel_le.cc b/techlibs/intel_le/synth_intel_le.cc new file mode 100644 index 000000000..8c65c43fa --- /dev/null +++ b/techlibs/intel_le/synth_intel_le.cc @@ -0,0 +1,280 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Wolf + * Copyright (C) 2019 Dan Ravensloft + * + * 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/celltypes.h" +#include "kernel/log.h" +#include "kernel/register.h" +#include "kernel/rtlil.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct SynthIntelLEPass : public ScriptPass { + SynthIntelLEPass() : ScriptPass("synth_intel_le", "synthesis for LE-based Intel (Altera) FPGAs.") {} + + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" synth_intel_le [options]\n"); + log("\n"); + log("This command runs synthesis for LE-based Intel FPGAs.\n"); + log("\n"); + log(" -top \n"); + log(" use the specified module as top module\n"); + log("\n"); + log(" -family \n"); + log(" target one of:\n"); + log(" \"cycloneiv\" - Cyclone IV (default)\n"); + log("\n"); + log(" -vqm \n"); + log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n"); + log(" output file is omitted if this parameter is not specified. Implies -quartus.\n"); + log("\n"); + log(" -noflatten\n"); + log(" do not flatten design before synthesis; useful for per-module area statistics\n"); + log("\n"); + log(" -quartus\n"); + log(" output a netlist using Quartus cells instead of MISTRAL_* cells\n"); + log("\n"); + log(" -dff\n"); + log(" pass DFFs to ABC to perform sequential logic optimisations (EXPERIMENTAL)\n"); + log("\n"); + log(" -run :\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(" -nolutram\n"); + log(" do not use LUT RAM cells in output netlist\n"); + log("\n"); + log(" -nobram\n"); + log(" do not use block RAM cells in output netlist\n"); + log("\n"); + log(" -nodsp\n"); + log(" do not map multipliers to MISTRAL_MUL cells\n"); + log("\n"); + log("The following commands are executed by this synthesis command:\n"); + help_script(); + log("\n"); + } + + string top_opt, family_opt, bram_type, vout_file; + bool flatten, quartus, nolutram, nobram, dff, nodsp; + + void clear_flags() override + { + top_opt = "-auto-top"; + family_opt = "cycloneiv"; + bram_type = "m10k"; + vout_file = ""; + flatten = true; + quartus = false; + nolutram = false; + nobram = false; + dff = false; + nodsp = false; + } + + void execute(std::vector args, RTLIL::Design *design) override + { + string run_from, run_to; + clear_flags(); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-family" && argidx + 1 < args.size()) { + family_opt = args[++argidx]; + continue; + } + if (args[argidx] == "-top" && argidx + 1 < args.size()) { + top_opt = "-top " + args[++argidx]; + continue; + } + if (args[argidx] == "-vqm" && argidx + 1 < args.size()) { + quartus = true; + vout_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] == "-quartus") { + quartus = true; + continue; + } + if (args[argidx] == "-nolutram") { + nolutram = true; + continue; + } + if (args[argidx] == "-nobram") { + nobram = true; + continue; + } + if (args[argidx] == "-nodsp") { + nodsp = true; + continue; + } + if (args[argidx] == "-noflatten") { + flatten = false; + continue; + } + if (args[argidx] == "-dff") { + dff = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (!design->full_selection()) + log_cmd_error("This command only operates on fully selected designs!\n"); + + if (family_opt == "cycloneiv") { + bram_type = "m9k"; + } else { + log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str()); + } + + log_header(design, "Executing SYNTH_intel_le pass.\n"); + log_push(); + + run_script(design, run_from, run_to); + + log_pop(); + } + + void script() override + { + if (help_mode) { + family_opt = ""; + bram_type = ""; + } + + if (check_label("begin")) { + if (family_opt == "cyclonev") + run(stringf("read_verilog -sv -lib +/intel_le/%s/cells_sim.v", family_opt.c_str())); + run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/alm_sim.v", family_opt.c_str())); + run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/dff_sim.v", family_opt.c_str())); + run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/dsp_sim.v", family_opt.c_str())); + run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/mem_sim.v", family_opt.c_str())); + run(stringf("read_verilog -specify -lib -D %s -icells +/intel_le/common/abc9_model.v", family_opt.c_str())); + + // Misc and common cells + run("read_verilog -lib +/intel/common/altpll_bb.v"); + run("read_verilog -lib +/intel_le/common/megafunction_bb.v"); + run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); + } + + if (check_label("coarse")) { + run("proc"); + if (flatten || help_mode) + run("flatten", "(skip if -noflatten)"); + run("tribuf -logic"); + run("deminout"); + run("opt_expr"); + run("opt_clean"); + run("check"); + run("opt -nodffe -nosdff"); + run("fsm"); + run("opt"); + run("wreduce"); + run("peepopt"); + run("opt_clean"); + run("share"); + run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4"); + run("opt_expr"); + run("opt_clean"); + run("alumacc"); + run("techmap -map +/intel_le/common/arith_alm_map.v -map +/intel_le/common/dsp_map.v"); + run("opt"); + run("memory -nomap"); + run("opt_clean"); + } + + if (!nobram && check_label("map_bram", "(skip if -nobram)")) { + run(stringf("memory_bram -rules +/intel_le/common/bram_%s.txt", bram_type.c_str())); + if (help_mode || bram_type != "m9k") + run(stringf("techmap -map +/intel_le/common/bram_%s_map.v", bram_type.c_str())); + } + + if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { + run("memory_bram -rules +/intel_le/common/lutram_mlab.txt", "(for Cyclone IV )"); + } + + if (check_label("map_ffram")) { + run("memory_map"); + run("opt -full"); + } + + if (check_label("map_ffs")) { + run("techmap"); + run("dfflegalize -cell $_DFFE_PN0P_ 0 -cell $_SDFFCE_PP0P_ 0"); + run("techmap -map +/intel_le/common/dff_map.v"); + run("opt -full -undriven -mux_undef"); + run("clean -purge"); + } + + if (check_label("map_luts")) { + run("techmap -map +/intel_le/common/abc9_map.v"); + run(stringf("abc9 %s -maxlut 6 -W 600", help_mode ? "[-dff]" : dff ? "-dff" : "")); + run("techmap -map +/intel_le/common/abc9_unmap.v"); + run("techmap -map +/intel_le/common/alm_map.v"); + run("opt -fast"); + run("autoname"); + run("clean"); + } + + if (check_label("check")) { + run("hierarchy -check"); + run("stat"); + run("check"); + } + + if (check_label("quartus")) { + if (quartus || help_mode) { + // Quartus ICEs if you have a wire which has `[]` in its name, + // which Yosys produces when building memories out of flops. + run("rename -hide w:*[* w:*]*"); + // VQM mode does not support 'x, so replace those with zero. + run("setundef -zero"); + // VQM mode does not support multi-bit constant assignments + // (e.g. 2'b00 is an error), so as a workaround use references + // to constant driver cells, which Quartus accepts. + run("hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q"); + // Rename from Yosys-internal MISTRAL_* cells to Quartus cells. + run(stringf("techmap -D %s -map +/intel_le/common/quartus_rename.v", family_opt.c_str())); + } + } + + if (check_label("vqm")) { + if (!vout_file.empty() || help_mode) { + run(stringf("write_verilog -attr2comment -defparam -nohex -decimal %s", help_mode ? "" : vout_file.c_str())); + } + } + } +} SynthIntelLEPass; + +PRIVATE_NAMESPACE_END diff --git a/tests/arch/intel_le/add_sub.ys b/tests/arch/intel_le/add_sub.ys new file mode 100644 index 000000000..ac75935b7 --- /dev/null +++ b/tests/arch/intel_le/add_sub.ys @@ -0,0 +1,18 @@ +read_verilog ../common/add_sub.v +hierarchy -top top +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +stat +select -assert-count 8 t:MISTRAL_ALUT_ARITH +select -assert-none t:MISTRAL_ALUT_ARITH %% t:* %D + +design -reset +read_verilog ../common/add_sub.v +hierarchy -top top +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +stat +select -assert-count 8 t:MISTRAL_ALUT_ARITH +select -assert-none t:MISTRAL_ALUT_ARITH %% t:* %D diff --git a/tests/arch/intel_le/adffs.ys b/tests/arch/intel_le/adffs.ys new file mode 100644 index 000000000..ec0085d65 --- /dev/null +++ b/tests/arch/intel_le/adffs.ys @@ -0,0 +1,94 @@ +read_verilog ../common/adffs.v +design -save read + +hierarchy -top adff +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd adff # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF +select -assert-count 1 t:MISTRAL_NOT + +select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D + + +design -load read +hierarchy -top adff +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd adff # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF +select -assert-count 1 t:MISTRAL_NOT + +select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D + + +design -load read +hierarchy -top adffn +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd adffn # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF + +select -assert-none t:MISTRAL_FF %% t:* %D + + +design -load read +hierarchy -top adffn +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd adffn # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF + +select -assert-none t:MISTRAL_FF %% t:* %D + + +design -load read +hierarchy -top dffs +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffs # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF +select -assert-count 1 t:MISTRAL_ALUT2 + +select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 %% t:* %D + + +design -load read +hierarchy -top dffs +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffs # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF +select -assert-count 1 t:MISTRAL_ALUT2 + +select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 %% t:* %D + + +design -load read +hierarchy -top ndffnr +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd ndffnr # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF +select -assert-count 2 t:MISTRAL_NOT + +select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D + + +design -load read +hierarchy -top ndffnr +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd ndffnr # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF +select -assert-count 2 t:MISTRAL_NOT + +select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D diff --git a/tests/arch/intel_le/blockram.ys b/tests/arch/intel_le/blockram.ys new file mode 100644 index 000000000..ce7502571 --- /dev/null +++ b/tests/arch/intel_le/blockram.ys @@ -0,0 +1,6 @@ +read_verilog ../common/blockram.v +chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 10 sync_ram_sdp +synth_intel_le -family cyclonev +cd sync_ram_sdp +select -assert-count 1 t:MISTRAL_M10K +select -assert-none t:MISTRAL_M10K %% t:* %D diff --git a/tests/arch/intel_le/counter.ys b/tests/arch/intel_le/counter.ys new file mode 100644 index 000000000..147b3d4c0 --- /dev/null +++ b/tests/arch/intel_le/counter.ys @@ -0,0 +1,27 @@ +read_verilog ../common/counter.v +hierarchy -top top +proc +flatten +equiv_opt -async2sync -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 2 t:MISTRAL_NOT +select -assert-count 8 t:MISTRAL_ALUT_ARITH +select -assert-count 8 t:MISTRAL_FF +select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH t:MISTRAL_FF %% t:* %D + + +design -reset +read_verilog ../common/counter.v +hierarchy -top top +proc +flatten +equiv_opt -async2sync -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 2 t:MISTRAL_NOT +select -assert-count 8 t:MISTRAL_ALUT_ARITH +select -assert-count 8 t:MISTRAL_FF +select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH t:MISTRAL_FF %% t:* %D diff --git a/tests/arch/intel_le/dffs.ys b/tests/arch/intel_le/dffs.ys new file mode 100644 index 000000000..484e4b7ba --- /dev/null +++ b/tests/arch/intel_le/dffs.ys @@ -0,0 +1,43 @@ +read_verilog ../common/dffs.v +design -save read + +hierarchy -top dff +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dff # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF + +select -assert-none t:MISTRAL_FF %% t:* %D + +design -load read +hierarchy -top dff +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dff # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF + +select -assert-none t:MISTRAL_FF %% t:* %D + + +design -load read +hierarchy -top dffe +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffe # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF + +select -assert-none t:MISTRAL_FF %% t:* %D + + +design -load read +hierarchy -top dffe +proc +equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffe # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_FF + +select -assert-none t:MISTRAL_FF %% t:* %D diff --git a/tests/arch/intel_le/fsm.ys b/tests/arch/intel_le/fsm.ys new file mode 100644 index 000000000..0bccaf549 --- /dev/null +++ b/tests/arch/intel_le/fsm.ys @@ -0,0 +1,44 @@ +read_verilog ../common/fsm.v +hierarchy -top fsm +proc +flatten + +equiv_opt -run :prove -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev +async2sync +miter -equiv -make_assert -flatten gold gate miter +sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter + +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd fsm # Constrain all select calls below inside the top module + +select -assert-count 6 t:MISTRAL_FF +select -assert-max 1 t:MISTRAL_NOT +select -assert-max 2 t:MISTRAL_ALUT2 # Clang returns 2, GCC returns 1 +select -assert-max 1 t:MISTRAL_ALUT3 +select -assert-max 2 t:MISTRAL_ALUT4 # Clang returns 0, GCC returns 1 +select -assert-max 6 t:MISTRAL_ALUT5 # Clang returns 5, GCC returns 4 +select -assert-max 2 t:MISTRAL_ALUT6 # Clang returns 1, GCC returns 2 +select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D + +design -reset +read_verilog ../common/fsm.v +hierarchy -top fsm +proc +flatten + +equiv_opt -run :prove -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx +async2sync +miter -equiv -make_assert -flatten gold gate miter +sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter + +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd fsm # Constrain all select calls below inside the top module + +select -assert-count 6 t:MISTRAL_FF +select -assert-max 1 t:MISTRAL_NOT +select -assert-max 2 t:MISTRAL_ALUT2 # Clang returns 2, GCC returns 1 +select -assert-max 2 t:MISTRAL_ALUT3 # Clang returns 2, GCC returns 1 +select -assert-max 2 t:MISTRAL_ALUT4 # Clang returns 0, GCC returns 1 +select -assert-max 6 t:MISTRAL_ALUT5 # Clang returns 5, GCC returns 4 +select -assert-max 2 t:MISTRAL_ALUT6 # Clang returns 1, GCC returns 2 +select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D diff --git a/tests/arch/intel_le/logic.ys b/tests/arch/intel_le/logic.ys new file mode 100644 index 000000000..689c9908f --- /dev/null +++ b/tests/arch/intel_le/logic.ys @@ -0,0 +1,25 @@ +read_verilog ../common/logic.v +hierarchy -top top +proc +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 1 t:MISTRAL_NOT +select -assert-count 6 t:MISTRAL_ALUT2 +select -assert-count 2 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D + + +design -reset +read_verilog ../common/logic.v +hierarchy -top top +proc +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 1 t:MISTRAL_NOT +select -assert-count 6 t:MISTRAL_ALUT2 +select -assert-count 2 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D \ No newline at end of file diff --git a/tests/arch/intel_le/lutram.ys b/tests/arch/intel_le/lutram.ys new file mode 100644 index 000000000..f08bb1c7c --- /dev/null +++ b/tests/arch/intel_le/lutram.ys @@ -0,0 +1,41 @@ +read_verilog ../common/lutram.v +hierarchy -top lutram_1w1r +proc +memory -nomap +equiv_opt -run :prove -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v -map +/intel_le/common/mem_sim.v synth_intel_le -family cyclonev -nobram +memory +opt -full + +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter + +design -load postopt +cd lutram_1w1r +select -assert-count 16 t:MISTRAL_MLAB +select -assert-count 1 t:MISTRAL_NOT +select -assert-count 2 t:MISTRAL_ALUT2 +select -assert-count 8 t:MISTRAL_ALUT3 +select -assert-count 17 t:MISTRAL_FF +select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D + + +design -reset +read_verilog ../common/lutram.v +hierarchy -top lutram_1w1r +proc +memory -nomap +equiv_opt -run :prove -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v -map +/intel_le/common/mem_sim.v synth_intel_le -family cyclonev -nobram +memory +opt -full + +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter + +design -load postopt +cd lutram_1w1r +select -assert-count 16 t:MISTRAL_MLAB +select -assert-count 1 t:MISTRAL_NOT +select -assert-count 2 t:MISTRAL_ALUT2 +select -assert-count 8 t:MISTRAL_ALUT3 +select -assert-count 17 t:MISTRAL_FF +select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D diff --git a/tests/arch/intel_le/mul.ys b/tests/arch/intel_le/mul.ys new file mode 100644 index 000000000..e0b8e8142 --- /dev/null +++ b/tests/arch/intel_le/mul.ys @@ -0,0 +1,60 @@ +read_verilog ../common/mul.v +chparam -set X_WIDTH 8 -set Y_WIDTH 8 -set A_WIDTH 16 +hierarchy -top top +proc +equiv_opt -assert -map +/intel_le/common/dsp_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 1 t:MISTRAL_MUL9X9 +select -assert-none t:MISTRAL_MUL9X9 %% t:* %D + +# Cyclone 10 GX does not have 9x9 multipliers. + +design -reset +read_verilog ../common/mul.v +chparam -set X_WIDTH 17 -set Y_WIDTH 17 -set A_WIDTH 34 +hierarchy -top top +proc +equiv_opt -assert -map +/intel_le/common/dsp_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 1 t:MISTRAL_MUL18X18 +select -assert-none t:MISTRAL_MUL18X18 %% t:* %D + +design -reset +read_verilog ../common/mul.v +chparam -set X_WIDTH 17 -set Y_WIDTH 17 -set A_WIDTH 34 +hierarchy -top top +proc +equiv_opt -assert -map +/intel_le/common/dsp_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 1 t:MISTRAL_MUL18X18 +select -assert-none t:MISTRAL_MUL18X18 %% t:* %D + +design -reset +read_verilog ../common/mul.v +chparam -set X_WIDTH 26 -set Y_WIDTH 26 -set A_WIDTH 52 +hierarchy -top top +proc +equiv_opt -assert -map +/intel_le/common/dsp_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 1 t:MISTRAL_MUL27X27 +select -assert-none t:MISTRAL_MUL27X27 %% t:* %D + +design -reset +read_verilog ../common/mul.v +chparam -set X_WIDTH 26 -set Y_WIDTH 26 -set A_WIDTH 52 +hierarchy -top top +proc +equiv_opt -assert -map +/intel_le/common/dsp_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 1 t:MISTRAL_MUL27X27 +select -assert-none t:MISTRAL_MUL27X27 %% t:* %D diff --git a/tests/arch/intel_le/mux.ys b/tests/arch/intel_le/mux.ys new file mode 100644 index 000000000..67bdabae1 --- /dev/null +++ b/tests/arch/intel_le/mux.ys @@ -0,0 +1,88 @@ +read_verilog ../common/mux.v +design -save read + + +hierarchy -top mux2 +proc +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux2 # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_ALUT3 +select -assert-none t:MISTRAL_ALUT3 %% t:* %D + + +design -load read +hierarchy -top mux2 +proc +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux2 # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_ALUT3 +select -assert-none t:MISTRAL_ALUT3 %% t:* %D + + +design -load read +hierarchy -top mux4 +proc +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux4 # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_ALUT6 +select -assert-none t:MISTRAL_ALUT6 %% t:* %D + + +design -load read +hierarchy -top mux4 +proc +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux4 # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_ALUT6 +select -assert-none t:MISTRAL_ALUT6 %% t:* %D + + +design -load read +hierarchy -top mux8 +proc +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux8 # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_ALUT3 +select -assert-count 2 t:MISTRAL_ALUT6 +select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT6 %% t:* %D + + +design -load read +hierarchy -top mux8 +proc +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux8 # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_ALUT3 +select -assert-count 2 t:MISTRAL_ALUT6 +select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT6 %% t:* %D + + +design -load read +hierarchy -top mux16 +proc +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux16 # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_ALUT3 +select -assert-max 2 t:MISTRAL_ALUT5 +select -assert-max 5 t:MISTRAL_ALUT6 +select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D + + +design -load read +hierarchy -top mux16 +proc +equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux16 # Constrain all select calls below inside the top module +select -assert-count 1 t:MISTRAL_ALUT3 +select -assert-count 2 t:MISTRAL_ALUT5 +select -assert-count 4 t:MISTRAL_ALUT6 + +select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D diff --git a/tests/arch/intel_le/quartus_ice.ys b/tests/arch/intel_le/quartus_ice.ys new file mode 100644 index 000000000..0f15f4d86 --- /dev/null +++ b/tests/arch/intel_le/quartus_ice.ys @@ -0,0 +1,26 @@ +read_verilog < Date: Wed, 14 Oct 2020 00:56:16 +0200 Subject: [PATCH 02/15] continue cleanup of files for intel-le handling --- techlibs/intel_le/Makefile.inc | 12 ++-- techlibs/intel_le/common/arith_le_map.v | 71 ++++++++++++++++++++++ techlibs/intel_le/common/bram_m9k.txt | 33 ++++++++++ techlibs/intel_le/common/dff_sim.v | 2 +- techlibs/intel_le/common/le_sim.v | 14 ++--- techlibs/intel_le/common/lutram_mlab.txt | 18 ------ techlibs/intel_le/common/megafunction_bb.v | 6 +- techlibs/intel_le/common/quartus_rename.v | 10 +-- techlibs/intel_le/cycloneiv/cells_sim.v | 14 ++--- techlibs/intel_le/synth_intel_le.cc | 26 +++----- 10 files changed, 139 insertions(+), 67 deletions(-) create mode 100644 techlibs/intel_le/common/arith_le_map.v create mode 100644 techlibs/intel_le/common/bram_m9k.txt delete mode 100644 techlibs/intel_le/common/lutram_mlab.txt diff --git a/techlibs/intel_le/Makefile.inc b/techlibs/intel_le/Makefile.inc index efc9de821..5c5260ea3 100644 --- a/techlibs/intel_le/Makefile.inc +++ b/techlibs/intel_le/Makefile.inc @@ -5,22 +5,20 @@ OBJS += techlibs/intel_le/synth_intel_le.o $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/abc9_map.v)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/abc9_unmap.v)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/abc9_model.v)) -$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/alm_map.v)) -$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/alm_sim.v)) -$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/arith_alm_map.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/le_map.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/le_sim.v)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/arith_le_map.v)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dff_map.v)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dff_sim.v)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dsp_sim.v)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dsp_map.v)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/mem_sim.v)) -$(eval $(call add_share_file,share/intel_le/cyclonev,techlibs/intel_le/cycloneiv/cells_sim.v)) +$(eval $(call add_share_file,share/intel_le/cycloneiv,techlibs/intel_le/cycloneiv/cells_sim.v)) # RAM -$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/bram_m10k.txt)) -$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/bram_m20k.txt)) +$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/bram_m9k.txt)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/bram_m20k_map.v)) -$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/lutram_mlab.txt)) # Miscellaneous $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/megafunction_bb.v)) diff --git a/techlibs/intel_le/common/arith_le_map.v b/techlibs/intel_le/common/arith_le_map.v new file mode 100644 index 000000000..8515eeb56 --- /dev/null +++ b/techlibs/intel_le/common/arith_le_map.v @@ -0,0 +1,71 @@ +`default_nettype none + +module \$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; + +parameter _TECHMAP_CONSTMSK_CI_ = 0; +parameter _TECHMAP_CONSTVAL_CI_ = 0; + +(* force_downto *) +input [A_WIDTH-1:0] A; +(* force_downto *) +input [B_WIDTH-1:0] B; +input CI, BI; +(* force_downto *) +output [Y_WIDTH-1:0] X, Y, CO; + +(* force_downto *) +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)); + +(* force_downto *) +wire [Y_WIDTH-1:0] AA = A_buf; +(* force_downto *) +wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; +(* force_downto *) +wire [Y_WIDTH-1:0] BX = B_buf; +wire [Y_WIDTH:0] ALM_CARRY; + +// Start of carry chain +generate + if (_TECHMAP_CONSTMSK_CI_ == 1) begin + assign ALM_CARRY[0] = _TECHMAP_CONSTVAL_CI_; + end else begin + MISTRAL_ALUT_ARITH #( + .LUT0(16'b1010_1010_1010_1010), // Q = A + .LUT1(16'b0000_0000_0000_0000), // Q = 0 (LUT1's input to the adder is inverted) + ) alm_start ( + .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1), + .CI(1'b0), + .CO(ALM_CARRY[0]) + ); + end +endgenerate + +// Carry chain +genvar i; +generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice + // TODO: mwk suggests that a pass could merge pre-adder logic into this. + MISTRAL_ALUT_ARITH #( + .LUT0(16'b1010_1010_1010_1010), // Q = A + .LUT1(16'b1100_0011_1100_0011), // Q = C ? B : ~B (LUT1's input to the adder is inverted) + ) alm_i ( + .A(AA[i]), .B(BX[i]), .C(BI), .D0(1'b1), .D1(1'b1), + .CI(ALM_CARRY[i]), + .SO(Y[i]), + .CO(ALM_CARRY[i+1]) + ); + + // ALM carry chain is not directly accessible, so calculate the carry through soft logic if really needed. + assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i])); +end endgenerate + +assign X = AA ^ BB; + +endmodule diff --git a/techlibs/intel_le/common/bram_m9k.txt b/techlibs/intel_le/common/bram_m9k.txt new file mode 100644 index 000000000..e9355fe2c --- /dev/null +++ b/techlibs/intel_le/common/bram_m9k.txt @@ -0,0 +1,33 @@ +bram MISTRAL_M10K + init 0 # TODO: Re-enable when I figure out how BRAM init works + abits 13 @D8192x1 + dbits 1 @D8192x1 + abits 12 @D4096x2 + dbits 2 @D4096x2 + abits 11 @D2048x4 @D2048x5 + dbits 4 @D2048x4 + dbits 5 @D2048x5 + abits 10 @D1024x8 @D1024x10 + dbits 8 @D1024x8 + dbits 10 @D1024x10 + abits 9 @D512x16 @D512x20 + dbits 16 @D512x16 + dbits 20 @D512x20 + abits 8 @D256x32 @D256x40 + dbits 32 @D256x32 + dbits 40 @D256x40 + groups 2 + ports 1 1 + wrmode 1 0 + # read enable; write enable + byte enables (only for multiples of 8) + enable 1 1 + transp 0 0 + clocks 1 1 + clkpol 1 1 +endbram + + +match MISTRAL_M10K + min efficiency 5 + make_transp +endmatch diff --git a/techlibs/intel_le/common/dff_sim.v b/techlibs/intel_le/common/dff_sim.v index d2cff0adb..05c3dce86 100644 --- a/techlibs/intel_le/common/dff_sim.v +++ b/techlibs/intel_le/common/dff_sim.v @@ -60,7 +60,7 @@ module MISTRAL_FF( output reg Q ); -`ifdef cyclonev +`ifdef cycloneiv specify if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 731; if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 890; diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v index 906a95b0b..1cd955362 100644 --- a/techlibs/intel_le/common/le_sim.v +++ b/techlibs/intel_le/common/le_sim.v @@ -82,7 +82,7 @@ module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); parameter [63:0] LUT = 64'h0000_0000_0000_0000; -`ifdef cyclonev +`ifdef cycloneiv specify (A => Q) = 605; (B => Q) = 583; @@ -113,7 +113,7 @@ module MISTRAL_ALUT5(input A, B, C, D, E, output Q); parameter [31:0] LUT = 32'h0000_0000; -`ifdef cyclonev +`ifdef cycloneiv specify (A => Q) = 583; (B => Q) = 510; @@ -142,7 +142,7 @@ module MISTRAL_ALUT4(input A, B, C, D, output Q); parameter [15:0] LUT = 16'h0000; -`ifdef cyclonev +`ifdef cycloneiv specify (A => Q) = 510; (B => Q) = 512; @@ -169,7 +169,7 @@ module MISTRAL_ALUT3(input A, B, C, output Q); parameter [7:0] LUT = 8'h00; -`ifdef cyclonev +`ifdef cycloneiv specify (A => Q) = 510; (B => Q) = 400; @@ -194,7 +194,7 @@ module MISTRAL_ALUT2(input A, B, output Q); parameter [3:0] LUT = 4'h0; -`ifdef cyclonev +`ifdef cycloneiv specify (A => Q) = 400; (B => Q) = 97; @@ -215,7 +215,7 @@ endmodule (* abc9_lut=1, lib_whitebox *) module MISTRAL_NOT(input A, output Q); -`ifdef cyclonev +`ifdef cycloneiv specify (A => Q) = 97; endspecify @@ -236,7 +236,7 @@ module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, (* abc9_carry *) input CI, outp parameter LUT0 = 16'h0000; parameter LUT1 = 16'h0000; -`ifdef cyclonev +`ifdef cycloneiv specify (A => SO) = 1342; (B => SO) = 1323; diff --git a/techlibs/intel_le/common/lutram_mlab.txt b/techlibs/intel_le/common/lutram_mlab.txt deleted file mode 100644 index 3cc69399d..000000000 --- a/techlibs/intel_le/common/lutram_mlab.txt +++ /dev/null @@ -1,18 +0,0 @@ -bram MISTRAL_MLAB - init 0 # TODO: Re-enable when Yosys remembers the original filename. - abits 5 - dbits 1 - groups 2 - ports 1 1 - wrmode 1 0 - # write enable - enable 1 0 - transp 0 0 - clocks 1 0 - clkpol 1 1 -endbram - -match MISTRAL_MLAB - min efficiency 5 - make_outreg -endmatch \ No newline at end of file diff --git a/techlibs/intel_le/common/megafunction_bb.v b/techlibs/intel_le/common/megafunction_bb.v index 874f293b1..0f723f7a1 100644 --- a/techlibs/intel_le/common/megafunction_bb.v +++ b/techlibs/intel_le/common/megafunction_bb.v @@ -539,7 +539,7 @@ output eccstatus; endmodule (* blackbox *) -module cyclonev_mlab_cell(portaaddr, portadatain, portbaddr, portbdataout, ena0, clk0, clk1); +module cycloneiv_mlab_cell(portaaddr, portadatain, portbaddr, portbdataout, ena0, clk0, clk1); parameter logical_ram_name = ""; parameter logical_ram_depth = 32; @@ -562,7 +562,7 @@ input ena0, clk0, clk1; endmodule (* blackbox *) -module cyclonev_mac(ax, ay, resulta); +module cycloneiv_mac(ax, ay, resulta); parameter ax_width = 9; parameter signed_max = "true"; @@ -594,7 +594,7 @@ output [result_a_width-1:0] resulta; endmodule (* blackbox *) -module cyclonev_ram_block(portaaddr, portadatain, portawe, portbaddr, portbdataout, portbre, clk0); +module cycloneiv_ram_block(portaaddr, portadatain, portawe, portbaddr, portbdataout, portbre, clk0); parameter operation_mode = "dual_port"; parameter logical_ram_name = ""; diff --git a/techlibs/intel_le/common/quartus_rename.v b/techlibs/intel_le/common/quartus_rename.v index 3b4628675..047f833f8 100644 --- a/techlibs/intel_le/common/quartus_rename.v +++ b/techlibs/intel_le/common/quartus_rename.v @@ -1,7 +1,7 @@ -`ifdef cyclonev -`define LCELL cyclonev_lcell_comb -`define MAC cyclonev_mac -`define MLAB cyclonev_mlab_cell +`ifdef cycloneiv +`define LCELL cycloneiv_lcell_comb +`define MAC cycloneiv_mac +`define MLAB cycloneiv_mlab_cell `endif `ifdef cyclone10gx `define LCELL cyclone10gx_lcell_comb @@ -140,7 +140,7 @@ output [CFG_DBITS-1:0] B1DATA; // Much like the MLAB, the M10K has mem_init[01234] parameters which would let // you initialise the RAM cell via hex literals. If they were implemented. -cyclonev_ram_block #( +cycloneiv_ram_block #( .operation_mode("dual_port"), .logical_ram_name(_TECHMAP_CELLNAME_), .port_a_address_width(CFG_ABITS), diff --git a/techlibs/intel_le/cycloneiv/cells_sim.v b/techlibs/intel_le/cycloneiv/cells_sim.v index f7abfaf14..60824ef03 100644 --- a/techlibs/intel_le/cycloneiv/cells_sim.v +++ b/techlibs/intel_le/cycloneiv/cells_sim.v @@ -25,21 +25,21 @@ module GND (output G); endmodule // GND /* Altera Cyclone IV devices Input Buffer Primitive */ -module cyclonev_io_ibuf +module cycloneiv_io_ibuf (output o, input i, input ibar); assign ibar = ibar; assign o = i; -endmodule // cyclonev_io_ibuf +endmodule // cycloneiv_io_ibuf /* Altera Cyclone IV devices Output Buffer Primitive */ -module cyclonev_io_obuf +module cycloneiv_io_obuf (output o, input i, input oe); assign o = i; assign oe = oe; -endmodule // cyclonev_io_obuf +endmodule // cycloneiv_io_obuf /* Altera Cyclone V LUT Primitive */ -module cyclonev_lcell_comb +module cycloneiv_lcell_comb (output combout, cout, sumout, shareout, input dataa, datab, datac, datad, input datae, dataf, datag, cin, @@ -47,7 +47,7 @@ module cyclonev_lcell_comb parameter lut_mask = 64'hFFFFFFFFFFFFFFFF; parameter dont_touch = "off"; - parameter lpm_type = "cyclonev_lcell_comb"; + parameter lpm_type = "cycloneiv_lcell_comb"; parameter shared_arith = "off"; parameter extended_lut = "off"; @@ -121,7 +121,7 @@ module cyclonev_lcell_comb initial $display("Advanced ALM lut combine is not implemented yet"); `endif `endif -endmodule // cyclonev_lcell_comb +endmodule // cycloneiv_lcell_comb /* Altera D Flip-Flop Primitive */ diff --git a/techlibs/intel_le/synth_intel_le.cc b/techlibs/intel_le/synth_intel_le.cc index 8c65c43fa..910eed4ad 100644 --- a/techlibs/intel_le/synth_intel_le.cc +++ b/techlibs/intel_le/synth_intel_le.cc @@ -62,9 +62,6 @@ struct SynthIntelLEPass : public ScriptPass { log(" from label is synonymous to 'begin', and empty to label is\n"); log(" synonymous to the end of the command list.\n"); log("\n"); - log(" -nolutram\n"); - log(" do not use LUT RAM cells in output netlist\n"); - log("\n"); log(" -nobram\n"); log(" do not use block RAM cells in output netlist\n"); log("\n"); @@ -77,17 +74,16 @@ struct SynthIntelLEPass : public ScriptPass { } string top_opt, family_opt, bram_type, vout_file; - bool flatten, quartus, nolutram, nobram, dff, nodsp; + bool flatten, quartus, nobram, dff, nodsp; void clear_flags() override { top_opt = "-auto-top"; family_opt = "cycloneiv"; - bram_type = "m10k"; + bram_type = "m9k"; vout_file = ""; flatten = true; quartus = false; - nolutram = false; nobram = false; dff = false; nodsp = false; @@ -125,10 +121,6 @@ struct SynthIntelLEPass : public ScriptPass { quartus = true; continue; } - if (args[argidx] == "-nolutram") { - nolutram = true; - continue; - } if (args[argidx] == "-nobram") { nobram = true; continue; @@ -174,9 +166,9 @@ struct SynthIntelLEPass : public ScriptPass { } if (check_label("begin")) { - if (family_opt == "cyclonev") + if (family_opt == "cycloneiv") run(stringf("read_verilog -sv -lib +/intel_le/%s/cells_sim.v", family_opt.c_str())); - run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/alm_sim.v", family_opt.c_str())); + run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/le_sim.v", family_opt.c_str())); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/dff_sim.v", family_opt.c_str())); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/dsp_sim.v", family_opt.c_str())); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/mem_sim.v", family_opt.c_str())); @@ -204,11 +196,11 @@ struct SynthIntelLEPass : public ScriptPass { run("peepopt"); run("opt_clean"); run("share"); - run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4"); + run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); run("opt_expr"); run("opt_clean"); run("alumacc"); - run("techmap -map +/intel_le/common/arith_alm_map.v -map +/intel_le/common/dsp_map.v"); + run("techmap -map +/intel_le/common/arith_le_map.v -map +/intel_le/common/dsp_map.v"); run("opt"); run("memory -nomap"); run("opt_clean"); @@ -220,10 +212,6 @@ struct SynthIntelLEPass : public ScriptPass { run(stringf("techmap -map +/intel_le/common/bram_%s_map.v", bram_type.c_str())); } - if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { - run("memory_bram -rules +/intel_le/common/lutram_mlab.txt", "(for Cyclone IV )"); - } - if (check_label("map_ffram")) { run("memory_map"); run("opt -full"); @@ -241,7 +229,7 @@ struct SynthIntelLEPass : public ScriptPass { run("techmap -map +/intel_le/common/abc9_map.v"); run(stringf("abc9 %s -maxlut 6 -W 600", help_mode ? "[-dff]" : dff ? "-dff" : "")); run("techmap -map +/intel_le/common/abc9_unmap.v"); - run("techmap -map +/intel_le/common/alm_map.v"); + run("techmap -map +/intel_le/common/le_map.v"); run("opt -fast"); run("autoname"); run("clean"); From 8021773072f0303e64107294aa31cea45178cce2 Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Wed, 14 Oct 2020 00:57:22 +0200 Subject: [PATCH 03/15] continue cleanup of files for intel-le handling --- techlibs/intel_le/common/arith_alm_map.v | 71 ------------------------ techlibs/intel_le/common/bram_m10k.txt | 33 ----------- 2 files changed, 104 deletions(-) delete mode 100644 techlibs/intel_le/common/arith_alm_map.v delete mode 100644 techlibs/intel_le/common/bram_m10k.txt diff --git a/techlibs/intel_le/common/arith_alm_map.v b/techlibs/intel_le/common/arith_alm_map.v deleted file mode 100644 index 8515eeb56..000000000 --- a/techlibs/intel_le/common/arith_alm_map.v +++ /dev/null @@ -1,71 +0,0 @@ -`default_nettype none - -module \$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; - -parameter _TECHMAP_CONSTMSK_CI_ = 0; -parameter _TECHMAP_CONSTVAL_CI_ = 0; - -(* force_downto *) -input [A_WIDTH-1:0] A; -(* force_downto *) -input [B_WIDTH-1:0] B; -input CI, BI; -(* force_downto *) -output [Y_WIDTH-1:0] X, Y, CO; - -(* force_downto *) -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)); - -(* force_downto *) -wire [Y_WIDTH-1:0] AA = A_buf; -(* force_downto *) -wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; -(* force_downto *) -wire [Y_WIDTH-1:0] BX = B_buf; -wire [Y_WIDTH:0] ALM_CARRY; - -// Start of carry chain -generate - if (_TECHMAP_CONSTMSK_CI_ == 1) begin - assign ALM_CARRY[0] = _TECHMAP_CONSTVAL_CI_; - end else begin - MISTRAL_ALUT_ARITH #( - .LUT0(16'b1010_1010_1010_1010), // Q = A - .LUT1(16'b0000_0000_0000_0000), // Q = 0 (LUT1's input to the adder is inverted) - ) alm_start ( - .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1), - .CI(1'b0), - .CO(ALM_CARRY[0]) - ); - end -endgenerate - -// Carry chain -genvar i; -generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice - // TODO: mwk suggests that a pass could merge pre-adder logic into this. - MISTRAL_ALUT_ARITH #( - .LUT0(16'b1010_1010_1010_1010), // Q = A - .LUT1(16'b1100_0011_1100_0011), // Q = C ? B : ~B (LUT1's input to the adder is inverted) - ) alm_i ( - .A(AA[i]), .B(BX[i]), .C(BI), .D0(1'b1), .D1(1'b1), - .CI(ALM_CARRY[i]), - .SO(Y[i]), - .CO(ALM_CARRY[i+1]) - ); - - // ALM carry chain is not directly accessible, so calculate the carry through soft logic if really needed. - assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i])); -end endgenerate - -assign X = AA ^ BB; - -endmodule diff --git a/techlibs/intel_le/common/bram_m10k.txt b/techlibs/intel_le/common/bram_m10k.txt deleted file mode 100644 index e9355fe2c..000000000 --- a/techlibs/intel_le/common/bram_m10k.txt +++ /dev/null @@ -1,33 +0,0 @@ -bram MISTRAL_M10K - init 0 # TODO: Re-enable when I figure out how BRAM init works - abits 13 @D8192x1 - dbits 1 @D8192x1 - abits 12 @D4096x2 - dbits 2 @D4096x2 - abits 11 @D2048x4 @D2048x5 - dbits 4 @D2048x4 - dbits 5 @D2048x5 - abits 10 @D1024x8 @D1024x10 - dbits 8 @D1024x8 - dbits 10 @D1024x10 - abits 9 @D512x16 @D512x20 - dbits 16 @D512x16 - dbits 20 @D512x20 - abits 8 @D256x32 @D256x40 - dbits 32 @D256x32 - dbits 40 @D256x40 - groups 2 - ports 1 1 - wrmode 1 0 - # read enable; write enable + byte enables (only for multiples of 8) - enable 1 1 - transp 0 0 - clocks 1 1 - clkpol 1 1 -endbram - - -match MISTRAL_M10K - min efficiency 5 - make_transp -endmatch From 41f83c19fd93d1bba7503c3af3f52e99a0ff5006 Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Thu, 15 Oct 2020 23:31:16 +0200 Subject: [PATCH 04/15] start modify files to reflect cyclone iv LE - architecture --- techlibs/intel_le/common/arith_le_map.v | 25 +++++++++++++------ techlibs/intel_le/common/le_sim.v | 32 ++++++------------------ techlibs/intel_le/cycloneiv/cells_sim.v | 33 ++++++------------------- 3 files changed, 32 insertions(+), 58 deletions(-) diff --git a/techlibs/intel_le/common/arith_le_map.v b/techlibs/intel_le/common/arith_le_map.v index 8515eeb56..1a177de85 100644 --- a/techlibs/intel_le/common/arith_le_map.v +++ b/techlibs/intel_le/common/arith_le_map.v @@ -30,7 +30,8 @@ wire [Y_WIDTH-1:0] AA = A_buf; wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; (* force_downto *) wire [Y_WIDTH-1:0] BX = B_buf; -wire [Y_WIDTH:0] ALM_CARRY; +wire [Y_WIDTH-1:0] BSUM; +wire [Y_WIDTH:0] LE_CARRY; // Start of carry chain generate @@ -53,15 +54,23 @@ genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice // TODO: mwk suggests that a pass could merge pre-adder logic into this. MISTRAL_ALUT_ARITH #( - .LUT0(16'b1010_1010_1010_1010), // Q = A - .LUT1(16'b1100_0011_1100_0011), // Q = C ? B : ~B (LUT1's input to the adder is inverted) + .LUT0(16'b0110_0110_0110_0110) // Q = A ? ~B : B ) alm_i ( - .A(AA[i]), .B(BX[i]), .C(BI), .D0(1'b1), .D1(1'b1), - .CI(ALM_CARRY[i]), - .SO(Y[i]), - .CO(ALM_CARRY[i+1]) + .A(BI), .B(BX[i]), .C(1'b0), .D(1'b0), + .CI(1'b0), + .SO(BSUM[i]), + .CO() ); - + MISTRAL_ALUT_ARITH #( + .LUT0(16'b1010_1010_1010_1010), // SUM = A xor B xor CI + // CARRYi+1 = A and B or A and CI or B and CI + .sum_lutc_input("cin") + ) alm_start ( + .A(AA[i]), .B(BX[i]), .C(1'b1), .D(1'b1), + .CI(LE_CARRY), + .SO(Y[i]), + .CO(ALM_CARRY[i+1]) + ); // ALM carry chain is not directly accessible, so calculate the carry through soft logic if really needed. assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i])); end endgenerate diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v index 1cd955362..6c6c8b9b9 100644 --- a/techlibs/intel_le/common/le_sim.v +++ b/techlibs/intel_le/common/le_sim.v @@ -231,11 +231,10 @@ assign Q = ~A; endmodule (* abc9_box, lib_whitebox *) -module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, (* abc9_carry *) input CI, output SO, (* abc9_carry *) output CO); - -parameter LUT0 = 16'h0000; -parameter LUT1 = 16'h0000; +module MISTRAL_ALUT_ARITH(input A, B, C, D, (* abc9_carry *) input CI, output , (* abc9_carry *) output CO); +parameter LUT = 16'h0000; +parameter sum_lutc_input = "cin"; `ifdef cycloneiv specify (A => SO) = 1342; @@ -253,30 +252,15 @@ specify (CI => CO) = 36; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM) endspecify `endif -`ifdef cyclone10gx -specify - (A => SO) = 644; - (B => SO) = 477; - (C => SO) = 416; - (D0 => SO) = 380; - (D1 => SO) = 431; - (CI => SO) = 276; - - (A => CO) = 525; - (B => CO) = 433; - (C => CO) = 712; - (D0 => CO) = 653; - (D1 => CO) = 593; - (CI => CO) = 16; -endspecify -`endif wire q0, q1; -assign q0 = LUT0 >> {D0, C, B, A}; -assign q1 = LUT1 >> {D1, C, B, A}; +assign q0 = LUT0 >> sum_lutc_input == "cin" : {D, CI, B, A},{D, C, B, A}; +assign q1 = LUT0 >> sum_lutc_input == "cin" : {'b0, CI, B, A},{'b0, C, B, A}; -assign {CO, SO} = q0 + !q1 + CI; +assign SO = D ? q1 : q0; + +assign CO = q0; endmodule diff --git a/techlibs/intel_le/cycloneiv/cells_sim.v b/techlibs/intel_le/cycloneiv/cells_sim.v index 60824ef03..343648ee2 100644 --- a/techlibs/intel_le/cycloneiv/cells_sim.v +++ b/techlibs/intel_le/cycloneiv/cells_sim.v @@ -38,22 +38,19 @@ module cycloneiv_io_obuf assign oe = oe; endmodule // cycloneiv_io_obuf -/* Altera Cyclone V LUT Primitive */ +/* Altera Cyclone IV LUT Primitive */ module cycloneiv_lcell_comb - (output combout, cout, sumout, shareout, + (output combout, cout, input dataa, datab, datac, datad, - input datae, dataf, datag, cin, - input sharein); + input datae, dataf, datag, cin); - parameter lut_mask = 64'hFFFFFFFFFFFFFFFF; + parameter lut_mask = 16'hFFFF; parameter dont_touch = "off"; parameter lpm_type = "cycloneiv_lcell_comb"; - parameter shared_arith = "off"; - parameter extended_lut = "off"; + // Internal variables - // Sub mask for fragmented LUTs - wire [15:0] mask_a, mask_b, mask_c, mask_d; + // Independent output for fragmented LUTs wire output_0, output_1, output_2, output_3; // Extended mode uses mux to define the output @@ -104,23 +101,7 @@ module cycloneiv_lcell_comb endfunction // lut6 assign {mask_a, mask_b, mask_c, mask_d} = {lut_mask[15:0], lut_mask[31:16], lut_mask[47:32], lut_mask[63:48]}; -`ifdef ADVANCED_ALM - always @(*) begin - if(extended_lut == "on") - shared_lut_alm = datag; - else - shared_lut_alm = datac; - // Build the ALM behaviour - out_0 = lut4(mask_a, dataa, datab, datac, datad); - out_1 = lut4(mask_b, dataa, datab, shared_lut_alm, datad); - out_2 = lut4(mask_c, dataa, datab, datac, datad); - out_3 = lut4(mask_d, dataa, datab, shared_lut_alm, datad); - end -`else - `ifdef DEBUG - initial $display("Advanced ALM lut combine is not implemented yet"); - `endif -`endif + endmodule // cycloneiv_lcell_comb From 309689da5b2233d2470659f6afbf16139e20897f Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Sat, 24 Oct 2020 00:02:05 +0200 Subject: [PATCH 05/15] minor cleanup and fixes --- techlibs/intel_le/Makefile.inc | 3 - techlibs/intel_le/common/arith_le_map.v | 25 +++---- techlibs/intel_le/common/bram_m20k.txt | 33 -------- techlibs/intel_le/common/bram_m20k_map.v | 31 -------- techlibs/intel_le/common/bram_m9k.txt | 17 ++--- techlibs/intel_le/common/dsp_map.v | 51 ------------- techlibs/intel_le/common/dsp_sim.v | 83 --------------------- techlibs/intel_le/common/le_sim.v | 14 ++-- techlibs/intel_le/common/mem_sim.v | 2 +- techlibs/intel_le/common/quartus_rename.v | 91 ++--------------------- techlibs/intel_le/cycloneiv/cells_sim.v | 81 +++++++++++--------- 11 files changed, 76 insertions(+), 355 deletions(-) delete mode 100644 techlibs/intel_le/common/bram_m20k.txt delete mode 100644 techlibs/intel_le/common/bram_m20k_map.v delete mode 100644 techlibs/intel_le/common/dsp_map.v delete mode 100644 techlibs/intel_le/common/dsp_sim.v diff --git a/techlibs/intel_le/Makefile.inc b/techlibs/intel_le/Makefile.inc index 5c5260ea3..06b1c5a84 100644 --- a/techlibs/intel_le/Makefile.inc +++ b/techlibs/intel_le/Makefile.inc @@ -10,15 +10,12 @@ $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/le_s $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/arith_le_map.v)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dff_map.v)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dff_sim.v)) -$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dsp_sim.v)) -$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/dsp_map.v)) $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/mem_sim.v)) $(eval $(call add_share_file,share/intel_le/cycloneiv,techlibs/intel_le/cycloneiv/cells_sim.v)) # RAM $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/bram_m9k.txt)) -$(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/bram_m20k_map.v)) # Miscellaneous $(eval $(call add_share_file,share/intel_le/common,techlibs/intel_le/common/megafunction_bb.v)) diff --git a/techlibs/intel_le/common/arith_le_map.v b/techlibs/intel_le/common/arith_le_map.v index 1a177de85..b6135975d 100644 --- a/techlibs/intel_le/common/arith_le_map.v +++ b/techlibs/intel_le/common/arith_le_map.v @@ -30,21 +30,21 @@ wire [Y_WIDTH-1:0] AA = A_buf; wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; (* force_downto *) wire [Y_WIDTH-1:0] BX = B_buf; -wire [Y_WIDTH-1:0] BSUM; +wire [Y_WIDTH-1:0] BTOADDER; wire [Y_WIDTH:0] LE_CARRY; // Start of carry chain generate if (_TECHMAP_CONSTMSK_CI_ == 1) begin - assign ALM_CARRY[0] = _TECHMAP_CONSTVAL_CI_; + assign LE_CARRY[0] = _TECHMAP_CONSTVAL_CI_; end else begin MISTRAL_ALUT_ARITH #( - .LUT0(16'b1010_1010_1010_1010), // Q = A - .LUT1(16'b0000_0000_0000_0000), // Q = 0 (LUT1's input to the adder is inverted) + .LUT(16'b1010_1010_1010_1010), // Q = A ) alm_start ( .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1), .CI(1'b0), - .CO(ALM_CARRY[0]) + .SO(), + .CO(LE_CARRY[0]) ); end endgenerate @@ -54,25 +54,24 @@ genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice // TODO: mwk suggests that a pass could merge pre-adder logic into this. MISTRAL_ALUT_ARITH #( - .LUT0(16'b0110_0110_0110_0110) // Q = A ? ~B : B + .LUT(16'b0110_0110_0110_0110) // Q = A ? ~B : B ) alm_i ( .A(BI), .B(BX[i]), .C(1'b0), .D(1'b0), .CI(1'b0), - .SO(BSUM[i]), + .SO(BTOADDER[i]), .CO() ); MISTRAL_ALUT_ARITH #( - .LUT0(16'b1010_1010_1010_1010), // SUM = A xor B xor CI + .LUT(16'b1010_1010_1010_1010), // SUM = A xor B xor CI // CARRYi+1 = A and B or A and CI or B and CI .sum_lutc_input("cin") ) alm_start ( - .A(AA[i]), .B(BX[i]), .C(1'b1), .D(1'b1), - .CI(LE_CARRY), + .A(AA[i]), .B(BTOADDER[i]), .C(1'b1), .D(1'b1), + .CI(LE_CARRY[i]), .SO(Y[i]), - .CO(ALM_CARRY[i+1]) + .CO(LE_CARRY[i+1]) ); - // ALM carry chain is not directly accessible, so calculate the carry through soft logic if really needed. - assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i])); + end endgenerate assign X = AA ^ BB; diff --git a/techlibs/intel_le/common/bram_m20k.txt b/techlibs/intel_le/common/bram_m20k.txt deleted file mode 100644 index b4c5a5372..000000000 --- a/techlibs/intel_le/common/bram_m20k.txt +++ /dev/null @@ -1,33 +0,0 @@ -bram __MISTRAL_M20K_SDP - init 1 # TODO: Re-enable when I figure out how BRAM init works - abits 14 @D16384x1 - dbits 1 @D16384x1 - abits 13 @D8192x2 - dbits 2 @D8192x2 - abits 12 @D4096x4 @D4096x5 - dbits 4 @D4096x4 - dbits 5 @D4096x5 - abits 11 @D2048x8 @D2048x10 - dbits 8 @D2048x8 - dbits 10 @D2048x10 - abits 10 @D1024x16 @D1024x20 - dbits 16 @D1024x16 - dbits 20 @D1024x20 - abits 9 @D512x32 @D512x40 - dbits 32 @D512x32 - dbits 40 @D512x40 - groups 2 - ports 1 1 - wrmode 1 0 - # read enable; write enable + byte enables (only for multiples of 8) - enable 1 1 - transp 0 0 - clocks 1 1 - clkpol 1 1 -endbram - - -match __MISTRAL_M20K_SDP - min efficiency 5 - make_transp -endmatch diff --git a/techlibs/intel_le/common/bram_m20k_map.v b/techlibs/intel_le/common/bram_m20k_map.v deleted file mode 100644 index 92f41310f..000000000 --- a/techlibs/intel_le/common/bram_m20k_map.v +++ /dev/null @@ -1,31 +0,0 @@ -module __MISTRAL_M20K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); - -parameter CFG_ABITS = 10; -parameter CFG_DBITS = 20; -parameter CFG_ENABLE_A = 1; -parameter CFG_ENABLE_B = 1; - -input CLK1; -input [CFG_ABITS-1:0] A1ADDR, B1ADDR; -input [CFG_DBITS-1:0] A1DATA; -output [CFG_DBITS-1:0] B1DATA; -input [CFG_ENABLE_A-1:0] A1EN, B1EN; - -altsyncram #( - .operation_mode("dual_port"), - .ram_block_type("m20k"), - .widthad_a(CFG_ABITS), - .width_a(CFG_DBITS), - .widthad_b(CFG_ABITS), - .width_b(CFG_DBITS), -) _TECHMAP_REPLACE_ ( - .address_a(A1ADDR), - .data_a(A1DATA), - .wren_a(A1EN), - .address_b(B1ADDR), - .q_b(B1DATA), - .clock0(CLK1), - .clock1(CLK1) -); - -endmodule diff --git a/techlibs/intel_le/common/bram_m9k.txt b/techlibs/intel_le/common/bram_m9k.txt index e9355fe2c..97a69b11c 100644 --- a/techlibs/intel_le/common/bram_m9k.txt +++ b/techlibs/intel_le/common/bram_m9k.txt @@ -1,21 +1,20 @@ -bram MISTRAL_M10K +bram MISTRAL_M9K init 0 # TODO: Re-enable when I figure out how BRAM init works abits 13 @D8192x1 dbits 1 @D8192x1 abits 12 @D4096x2 dbits 2 @D4096x2 - abits 11 @D2048x4 @D2048x5 + abits 11 @D2048x4 dbits 4 @D2048x4 - dbits 5 @D2048x5 - abits 10 @D1024x8 @D1024x10 + abits 10 @D1024x8 @D1024x9 dbits 8 @D1024x8 - dbits 10 @D1024x10 - abits 9 @D512x16 @D512x20 + dbits 9 @D1024x9 + abits 9 @D512x16 @D512x18 dbits 16 @D512x16 - dbits 20 @D512x20 - abits 8 @D256x32 @D256x40 + dbits 18 @D512x18 + abits 8 @D256x32 @D256x36 dbits 32 @D256x32 - dbits 40 @D256x40 + dbits 36 @D256x36 groups 2 ports 1 1 wrmode 1 0 diff --git a/techlibs/intel_le/common/dsp_map.v b/techlibs/intel_le/common/dsp_map.v deleted file mode 100644 index e12e777a4..000000000 --- a/techlibs/intel_le/common/dsp_map.v +++ /dev/null @@ -1,51 +0,0 @@ -`default_nettype none - -module __MUL27X27(A, B, Y); - -parameter A_SIGNED = 1; -parameter B_SIGNED = 1; -parameter A_WIDTH = 27; -parameter B_WIDTH = 27; -parameter Y_WIDTH = 54; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -MISTRAL_MUL27X27 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); - -endmodule - - -module __MUL18X18(A, B, Y); - -parameter A_SIGNED = 1; -parameter B_SIGNED = 1; -parameter A_WIDTH = 18; -parameter B_WIDTH = 18; -parameter Y_WIDTH = 36; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -MISTRAL_MUL18X18 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); - -endmodule - - -module __MUL9X9(A, B, Y); - -parameter A_SIGNED = 1; -parameter B_SIGNED = 1; -parameter A_WIDTH = 9; -parameter B_WIDTH = 9; -parameter Y_WIDTH = 18; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -MISTRAL_MUL9X9 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); - -endmodule diff --git a/techlibs/intel_le/common/dsp_sim.v b/techlibs/intel_le/common/dsp_sim.v deleted file mode 100644 index bdb6d18d5..000000000 --- a/techlibs/intel_le/common/dsp_sim.v +++ /dev/null @@ -1,83 +0,0 @@ -(* abc9_box *) -module MISTRAL_MUL27X27(input [26:0] A, input [26:0] B, output [53:0] Y); - -parameter A_SIGNED = 1; -parameter B_SIGNED = 1; - -// TODO: Cyclone 10 GX timings; the below are for Cyclone V -specify - (A *> Y) = 3732; - (B *> Y) = 3928; -endspecify - -wire [53:0] A_, B_; - -if (A_SIGNED) - assign A_ = $signed(A); -else - assign A_ = $unsigned(A); - -if (B_SIGNED) - assign B_ = $signed(B); -else - assign B_ = $unsigned(B); - -assign Y = A_ * B_; - -endmodule - -(* abc9_box *) -module MISTRAL_MUL18X18(input [17:0] A, input [17:0] B, output [35:0] Y); - -parameter A_SIGNED = 1; -parameter B_SIGNED = 1; - -// TODO: Cyclone 10 GX timings; the below are for Cyclone V -specify - (A *> Y) = 3180; - (B *> Y) = 3982; -endspecify - -wire [35:0] A_, B_; - -if (A_SIGNED) - assign A_ = $signed(A); -else - assign A_ = $unsigned(A); - -if (B_SIGNED) - assign B_ = $signed(B); -else - assign B_ = $unsigned(B); - -assign Y = A_ * B_; - -endmodule - -(* abc9_box *) -module MISTRAL_MUL9X9(input [8:0] A, input [8:0] B, output [17:0] Y); - -parameter A_SIGNED = 1; -parameter B_SIGNED = 1; - -// TODO: Cyclone 10 GX timings; the below are for Cyclone V -specify - (A *> Y) = 2818; - (B *> Y) = 3051; -endspecify - -wire [17:0] A_, B_; - -if (A_SIGNED) - assign A_ = $signed(A); -else - assign A_ = $unsigned(A); - -if (B_SIGNED) - assign B_ = $signed(B); -else - assign B_ = $unsigned(B); - -assign Y = A_ * B_; - -endmodule diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v index 6c6c8b9b9..bd1a5ae8e 100644 --- a/techlibs/intel_le/common/le_sim.v +++ b/techlibs/intel_le/common/le_sim.v @@ -231,32 +231,30 @@ assign Q = ~A; endmodule (* abc9_box, lib_whitebox *) -module MISTRAL_ALUT_ARITH(input A, B, C, D, (* abc9_carry *) input CI, output , (* abc9_carry *) output CO); +module MISTRAL_ALUT_ARITH(input A, B, C, D, (* abc9_carry *) input CI, output SO, (* abc9_carry *) output CO); parameter LUT = 16'h0000; parameter sum_lutc_input = "cin"; -`ifdef cycloneiv +`ifdef cycloneiv specify (A => SO) = 1342; (B => SO) = 1323; (C => SO) = 927; - (D0 => SO) = 887; - (D1 => SO) = 785; + (D => SO) = 887; (CI => SO) = 368; (A => CO) = 1082; (B => CO) = 1062; (C => CO) = 813; - (D0 => CO) = 866; - (D1 => CO) = 1198; + (D => CO) = 866; (CI => CO) = 36; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM) endspecify `endif wire q0, q1; -assign q0 = LUT0 >> sum_lutc_input == "cin" : {D, CI, B, A},{D, C, B, A}; -assign q1 = LUT0 >> sum_lutc_input == "cin" : {'b0, CI, B, A},{'b0, C, B, A}; +assign q0 = LUT >> sum_lutc_input == "cin" ? {D, CI, B, A}:{D, C, B, A}; +assign q1 = LUT >> sum_lutc_input == "cin" ? {'b1, CI, B, A}:{'b1, C, B, A}; assign SO = D ? q1 : q0; diff --git a/techlibs/intel_le/common/mem_sim.v b/techlibs/intel_le/common/mem_sim.v index e09aafaa2..db5f40fb5 100644 --- a/techlibs/intel_le/common/mem_sim.v +++ b/techlibs/intel_le/common/mem_sim.v @@ -74,7 +74,7 @@ assign B1DATA = mem[B1ADDR]; endmodule -// The M10K +// The M9K // -------- // TODO diff --git a/techlibs/intel_le/common/quartus_rename.v b/techlibs/intel_le/common/quartus_rename.v index 047f833f8..15497b010 100644 --- a/techlibs/intel_le/common/quartus_rename.v +++ b/techlibs/intel_le/common/quartus_rename.v @@ -3,11 +3,6 @@ `define MAC cycloneiv_mac `define MLAB cycloneiv_mlab_cell `endif -`ifdef cyclone10gx -`define LCELL cyclone10gx_lcell_comb -`define MAC cyclone10gx_mac -`define MLAB cyclone10gx_mlab_cell -`endif module __MISTRAL_VCC(output Q); @@ -30,20 +25,6 @@ dffeas #(.power_up("low"), .is_wysiwyg("true")) _TECHMAP_REPLACE_ (.d(DATAIN), . endmodule -module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); -parameter [63:0] LUT = 64'h0000_0000_0000_0000; - -`LCELL #(.lut_mask(LUT)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .dataf(F), .combout(Q)); - -endmodule - - -module MISTRAL_ALUT5(input A, B, C, D, E, output Q); -parameter [31:0] LUT = 32'h0000_0000; - -`LCELL #(.lut_mask({2{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .combout(Q)); - -endmodule module MISTRAL_ALUT4(input A, B, C, D, output Q); @@ -77,11 +58,10 @@ NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q)); endmodule -module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, CI, output SO, CO); -parameter LUT0 = 16'h0000; -parameter LUT1 = 16'h0000; +module MISTRAL_ALUT_ARITH(input A, B, C, D, CI, output SO, CO); +parameter LUT = 16'h0000; -`LCELL #(.lut_mask({16'h0, LUT1, 16'h0, LUT0})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D0), .dataf(D1), .cin(CI), .sumout(SO), .cout(CO)); +`LCELL #(.lut_mask({16'h0, LUT})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .cin(CI), .sumout(SO), .cout(CO)); endmodule @@ -125,7 +105,7 @@ parameter _TECHMAP_CELLNAME_ = ""; endmodule -module MISTRAL_M10K(A1ADDR, A1DATA, A1EN, CLK1, B1ADDR, B1DATA, B1EN); +module MISTRAL_M9K(A1ADDR, A1DATA, A1EN, CLK1, B1ADDR, B1DATA, B1EN); parameter CFG_ABITS = 10; parameter CFG_DBITS = 10; @@ -137,7 +117,7 @@ input [CFG_DBITS-1:0] A1DATA; input CLK1, A1EN, B1EN; output [CFG_DBITS-1:0] B1DATA; -// Much like the MLAB, the M10K has mem_init[01234] parameters which would let +// Much like the MLAB, the M9K has mem_init[01234] parameters which would let // you initialise the RAM cell via hex literals. If they were implemented. cycloneiv_ram_block #( @@ -172,64 +152,3 @@ cycloneiv_ram_block #( endmodule -module MISTRAL_MUL27X27(input [26:0] A, B, output [53:0] Y); - -parameter A_SIGNED = 1; -parameter B_SIGNED = 1; - -`MAC #( - .ax_width(27), - .signed_max(A_SIGNED ? "true" : "false"), - .ay_scan_in_width(27), - .signed_may(B_SIGNED ? "true" : "false"), - .result_a_width(54), - .operation_mode("M27x27") -) _TECHMAP_REPLACE_ ( - .ax(A), - .ay(B), - .resulta(Y) -); - -endmodule - - -module MISTRAL_MUL18X18(input [17:0] A, B, output [35:0] Y); - -parameter A_SIGNED = 1; -parameter B_SIGNED = 1; - -`MAC #( - .ax_width(18), - .signed_max(A_SIGNED ? "true" : "false"), - .ay_scan_in_width(18), - .signed_may(B_SIGNED ? "true" : "false"), - .result_a_width(36), - .operation_mode("M18x18_FULL") -) _TECHMAP_REPLACE_ ( - .ax(A), - .ay(B), - .resulta(Y) -); - -endmodule - - -module MISTRAL_MUL9X9(input [8:0] A, B, output [17:0] Y); - -parameter A_SIGNED = 1; -parameter B_SIGNED = 1; - -`MAC #( - .ax_width(9), - .signed_max(A_SIGNED ? "true" : "false"), - .ay_scan_in_width(9), - .signed_may(B_SIGNED ? "true" : "false"), - .result_a_width(18), - .operation_mode("M9x9") -) _TECHMAP_REPLACE_ ( - .ax(A), - .ay(B), - .resulta(Y) -); - -endmodule diff --git a/techlibs/intel_le/cycloneiv/cells_sim.v b/techlibs/intel_le/cycloneiv/cells_sim.v index 343648ee2..0f7432fc7 100644 --- a/techlibs/intel_le/cycloneiv/cells_sim.v +++ b/techlibs/intel_le/cycloneiv/cells_sim.v @@ -1,4 +1,4 @@ -/* +/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf @@ -41,22 +41,23 @@ endmodule // cycloneiv_io_obuf /* Altera Cyclone IV LUT Primitive */ module cycloneiv_lcell_comb (output combout, cout, - input dataa, datab, datac, datad, - input datae, dataf, datag, cin); + input dataa, datab, datac, datad, cin); parameter lut_mask = 16'hFFFF; parameter dont_touch = "off"; parameter lpm_type = "cycloneiv_lcell_comb"; - + parameter sum_lutc_input = "datac"; - // Internal variables + reg cout_tmp; + reg combout_tmp; + + reg [1:0] isum_lutc_input; - // Independent output for fragmented LUTs - wire output_0, output_1, output_2, output_3; - // Extended mode uses mux to define the output - wire mux_0, mux_1; - // Input for hold the shared LUT mode value - wire shared_lut_alm; + wire dataa_in; + wire datab_in; + wire datac_in; + wire datad_in; + wire cin_in; // Simulation model of 4-input LUT function lut4; @@ -73,35 +74,41 @@ module cycloneiv_lcell_comb end endfunction // lut4 - // Simulation model of 5-input LUT - function lut5; - input [31:0] mask; // wp-01003.pdf, page 3: "a 5-LUT can be built with two 4-LUTs and a multiplexer. - input dataa, datab, datac, datad, datae; - reg upper_lut_value; - reg lower_lut_value; - begin - upper_lut_value = lut4(mask[31:16], dataa, datab, datac, datad); - lower_lut_value = lut4(mask[15:0], dataa, datab, datac, datad); - lut5 = (datae) ? upper_lut_value : lower_lut_value; - end - endfunction // lut5 - // Simulation model of 6-input LUT - function lut6; - input [63:0] mask; - input dataa, datab, datac, datad, datae, dataf; - reg upper_lut_value; - reg lower_lut_value; - reg out_0, out_1, out_2, out_3; - begin - upper_lut_value = lut5(mask[63:32], dataa, datab, datac, datad, datae); - lower_lut_value = lut5(mask[31:0], dataa, datab, datac, datad, datae); - lut6 = (dataf) ? upper_lut_value : lower_lut_value; - end - endfunction // lut6 + initial + begin + if (sum_lutc_input == "datac") + isum_lutc_input = 0; + else if (sum_lutc_input == "cin") + isum_lutc_input = 1; + else + begin + $display ("Error: Invalid sum_lutc_input specified\n"); + $display ("Time: %0t Instance: %m", $time); + isum_lutc_input = 2; + end - assign {mask_a, mask_b, mask_c, mask_d} = {lut_mask[15:0], lut_mask[31:16], lut_mask[47:32], lut_mask[63:48]}; + end + always @(datad_in or datac_in or datab_in or dataa_in or cin_in) + begin + + if (isum_lutc_input == 0) // datac + begin + combout_tmp = lut4(lut_mask, dataa_in, datab_in, + datac_in, datad_in); + end + else if (isum_lutc_input == 1) // cin + begin + combout_tmp = lut4(lut_mask, dataa_in, datab_in, + cin_in, datad_in); + end + + cout_tmp = lut4(lut_mask, dataa_in, datab_in, cin_in, 'b0); + end + + and (combout, combout_tmp, 1'b1) ; + and (cout, cout_tmp, 1'b1) ; endmodule // cycloneiv_lcell_comb From 53a95de62f55c2cb2979e6805e40235b87e75792 Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Wed, 28 Oct 2020 00:25:57 +0100 Subject: [PATCH 06/15] minor progress in mapping --- techlibs/intel_le/common/arith_le_map.v | 17 +++++++++++------ techlibs/intel_le/common/le_sim.v | 11 +++++++---- techlibs/intel_le/synth_intel_le.cc | 7 +++---- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/techlibs/intel_le/common/arith_le_map.v b/techlibs/intel_le/common/arith_le_map.v index b6135975d..75e085520 100644 --- a/techlibs/intel_le/common/arith_le_map.v +++ b/techlibs/intel_le/common/arith_le_map.v @@ -40,7 +40,7 @@ generate end else begin MISTRAL_ALUT_ARITH #( .LUT(16'b1010_1010_1010_1010), // Q = A - ) alm_start ( + ) le_start ( .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1), .CI(1'b0), .SO(), @@ -52,20 +52,25 @@ endgenerate // Carry chain genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice - // TODO: mwk suggests that a pass could merge pre-adder logic into this. + MISTRAL_ALUT_ARITH #( .LUT(16'b0110_0110_0110_0110) // Q = A ? ~B : B - ) alm_i ( + ) le_not_i ( .A(BI), .B(BX[i]), .C(1'b0), .D(1'b0), .CI(1'b0), .SO(BTOADDER[i]), .CO() ); + + + + + MISTRAL_ALUT_ARITH #( - .LUT(16'b1010_1010_1010_1010), // SUM = A xor B xor CI + .LUT(16'b1001_0110_1110_1000), // SUM = A xor B xor CI // CARRYi+1 = A and B or A and CI or B and CI - .sum_lutc_input("cin") - ) alm_start ( + //.sum_lutc_input("cin") + ) le_i ( .A(AA[i]), .B(BTOADDER[i]), .C(1'b1), .D(1'b1), .CI(LE_CARRY[i]), .SO(Y[i]), diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v index bd1a5ae8e..8fbcdf2a7 100644 --- a/techlibs/intel_le/common/le_sim.v +++ b/techlibs/intel_le/common/le_sim.v @@ -234,7 +234,7 @@ endmodule module MISTRAL_ALUT_ARITH(input A, B, C, D, (* abc9_carry *) input CI, output SO, (* abc9_carry *) output CO); parameter LUT = 16'h0000; -parameter sum_lutc_input = "cin"; +//parameter sum_lutc_input = "cin"; `ifdef cycloneiv specify (A => SO) = 1342; @@ -253,10 +253,13 @@ endspecify wire q0, q1; -assign q0 = LUT >> sum_lutc_input == "cin" ? {D, CI, B, A}:{D, C, B, A}; -assign q1 = LUT >> sum_lutc_input == "cin" ? {'b1, CI, B, A}:{'b1, C, B, A}; +//assign q0 = LUT >> sum_lutc_input == "cin" ? {D, CI, B, A}:{D, C, B, A}; +//assign q1 = LUT >> sum_lutc_input == "cin" ? {'b0, CI, B, A}:{'b0, C, B, A}; -assign SO = D ? q1 : q0; +assign q0 = LUT >> {'b0, CI, B, A}; +assign q1 = LUT >> {D, CI, B, A}; + +assign SO = q1; assign CO = q0; diff --git a/techlibs/intel_le/synth_intel_le.cc b/techlibs/intel_le/synth_intel_le.cc index 910eed4ad..84527fab1 100644 --- a/techlibs/intel_le/synth_intel_le.cc +++ b/techlibs/intel_le/synth_intel_le.cc @@ -170,7 +170,6 @@ struct SynthIntelLEPass : public ScriptPass { run(stringf("read_verilog -sv -lib +/intel_le/%s/cells_sim.v", family_opt.c_str())); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/le_sim.v", family_opt.c_str())); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/dff_sim.v", family_opt.c_str())); - run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/dsp_sim.v", family_opt.c_str())); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/mem_sim.v", family_opt.c_str())); run(stringf("read_verilog -specify -lib -D %s -icells +/intel_le/common/abc9_model.v", family_opt.c_str())); @@ -196,11 +195,11 @@ struct SynthIntelLEPass : public ScriptPass { run("peepopt"); run("opt_clean"); run("share"); - run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); + run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4"); run("opt_expr"); run("opt_clean"); run("alumacc"); - run("techmap -map +/intel_le/common/arith_le_map.v -map +/intel_le/common/dsp_map.v"); + run("techmap -map +/intel_le/common/arith_le_map.v"); run("opt"); run("memory -nomap"); run("opt_clean"); @@ -227,7 +226,7 @@ struct SynthIntelLEPass : public ScriptPass { if (check_label("map_luts")) { run("techmap -map +/intel_le/common/abc9_map.v"); - run(stringf("abc9 %s -maxlut 6 -W 600", help_mode ? "[-dff]" : dff ? "-dff" : "")); + run(stringf("abc9 %s -maxlut 4 -W 400", help_mode ? "[-dff]" : dff ? "-dff" : "")); run("techmap -map +/intel_le/common/abc9_unmap.v"); run("techmap -map +/intel_le/common/le_map.v"); run("opt -fast"); From 42c5007cf64b1b3601119496d10afbd62aad9178 Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Thu, 29 Oct 2020 01:19:20 +0100 Subject: [PATCH 07/15] some progress in le mapping --- techlibs/intel_le/common/arith_le_map.v | 9 +- techlibs/intel_le/common/le_sim.v | 369 +--------------------- techlibs/intel_le/common/quartus_rename.v | 18 +- techlibs/intel_le/cycloneiv/cells_sim.v | 60 ---- 4 files changed, 16 insertions(+), 440 deletions(-) diff --git a/techlibs/intel_le/common/arith_le_map.v b/techlibs/intel_le/common/arith_le_map.v index 75e085520..614e343af 100644 --- a/techlibs/intel_le/common/arith_le_map.v +++ b/techlibs/intel_le/common/arith_le_map.v @@ -40,6 +40,7 @@ generate end else begin MISTRAL_ALUT_ARITH #( .LUT(16'b1010_1010_1010_1010), // Q = A + .sum_lutc_input("cin") ) le_start ( .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1), .CI(1'b0), @@ -54,7 +55,8 @@ genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice MISTRAL_ALUT_ARITH #( - .LUT(16'b0110_0110_0110_0110) // Q = A ? ~B : B + .LUT(16'b0110_0110_0110_0110), // Q = A ? ~B : B + .sum_lutc_input("cin") ) le_not_i ( .A(BI), .B(BX[i]), .C(1'b0), .D(1'b0), .CI(1'b0), @@ -63,13 +65,10 @@ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice ); - - - MISTRAL_ALUT_ARITH #( .LUT(16'b1001_0110_1110_1000), // SUM = A xor B xor CI // CARRYi+1 = A and B or A and CI or B and CI - //.sum_lutc_input("cin") + .sum_lutc_input("cin") ) le_i ( .A(AA[i]), .B(BTOADDER[i]), .C(1'b1), .D(1'b1), .CI(LE_CARRY[i]), diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v index 8fbcdf2a7..465c7c14b 100644 --- a/techlibs/intel_le/common/le_sim.v +++ b/techlibs/intel_le/common/le_sim.v @@ -77,65 +77,6 @@ // SUMOUT 368 1342 1323 887 927 - 785 - // CARRYOUT 71 1082 1062 866 813 - 1198 - -(* abc9_lut=2, lib_whitebox *) -module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); - -parameter [63:0] LUT = 64'h0000_0000_0000_0000; - -`ifdef cycloneiv -specify - (A => Q) = 605; - (B => Q) = 583; - (C => Q) = 510; - (D => Q) = 512; - (E => Q) = 400; - (F => Q) = 97; -endspecify -`endif -`ifdef cyclone10gx -specify - (A => Q) = 275; - (B => Q) = 272; - (C => Q) = 175; - (D => Q) = 165; - (E => Q) = 162; - (F => Q) = 53; -endspecify -`endif - -assign Q = LUT >> {F, E, D, C, B, A}; - -endmodule - - -(* abc9_lut=1, lib_whitebox *) -module MISTRAL_ALUT5(input A, B, C, D, E, output Q); - -parameter [31:0] LUT = 32'h0000_0000; - -`ifdef cycloneiv -specify - (A => Q) = 583; - (B => Q) = 510; - (C => Q) = 512; - (D => Q) = 400; - (E => Q) = 97; -endspecify -`endif -`ifdef cyclone10gx -specify - (A => Q) = 272; - (B => Q) = 175; - (C => Q) = 165; - (D => Q) = 162; - (E => Q) = 53; -endspecify -`endif - -assign Q = LUT >> {E, D, C, B, A}; - -endmodule - (* abc9_lut=1, lib_whitebox *) module MISTRAL_ALUT4(input A, B, C, D, output Q); @@ -150,14 +91,6 @@ specify (D => Q) = 97; endspecify `endif -`ifdef cyclone10gx -specify - (A => Q) = 175; - (B => Q) = 165; - (C => Q) = 162; - (D => Q) = 53; -endspecify -`endif assign Q = LUT >> {D, C, B, A}; @@ -176,13 +109,6 @@ specify (C => Q) = 97; endspecify `endif -`ifdef cyclone10gx -specify - (A => Q) = 165; - (B => Q) = 162; - (C => Q) = 53; -endspecify -`endif assign Q = LUT >> {C, B, A}; @@ -200,12 +126,6 @@ specify (B => Q) = 97; endspecify `endif -`ifdef cyclone10gx -specify - (A => Q) = 162; - (B => Q) = 53; -endspecify -`endif assign Q = LUT >> {B, A}; @@ -220,11 +140,6 @@ specify (A => Q) = 97; endspecify `endif -`ifdef cyclone10gx -specify - (A => Q) = 53; -endspecify -`endif assign Q = ~A; @@ -234,7 +149,7 @@ endmodule module MISTRAL_ALUT_ARITH(input A, B, C, D, (* abc9_carry *) input CI, output SO, (* abc9_carry *) output CO); parameter LUT = 16'h0000; -//parameter sum_lutc_input = "cin"; +parameter sum_lutc_input = "cin"; `ifdef cycloneiv specify (A => SO) = 1342; @@ -253,8 +168,8 @@ endspecify wire q0, q1; -//assign q0 = LUT >> sum_lutc_input == "cin" ? {D, CI, B, A}:{D, C, B, A}; -//assign q1 = LUT >> sum_lutc_input == "cin" ? {'b0, CI, B, A}:{'b0, C, B, A}; +//assign q0 = LUT >> sum_lutc_input == "cin" ? {'b0, CI, B, A}:{'b0, C, B, A}; +//assign q1 = LUT >> sum_lutc_input == "cin" ? {D, CI, B, A}:{D, C, B, A}; assign q0 = LUT >> {'b0, CI, B, A}; assign q1 = LUT >> {D, CI, B, A}; @@ -266,281 +181,3 @@ assign CO = q0; endmodule -/* -// A, B, C0, C1, E0, E1, F0, F1: data inputs -// CARRYIN: carry input -// SHAREIN: shared-arithmetic input -// CLK0, CLK1, CLK2: clock inputs -// -// COMB0, COMB1: combinational outputs -// FF0, FF1, FF2, FF3: DFF outputs -// SUM0, SUM1: adder outputs -// CARRYOUT: carry output -// SHAREOUT: shared-arithmetic output -module MISTRAL_ALM( - input A, B, C0, C1, E0, E1, F0, F1, CARRYIN, SHAREIN, // LUT path - input CLK0, CLK1, CLK2, AC0, AC1, // FF path - output COMB0, COMB1, SUM0, SUM1, CARRYOUT, SHAREOUT, - output FF0, FF1, FF2, FF3 -); - -parameter LUT0 = 16'b0000; -parameter LUT1 = 16'b0000; -parameter LUT2 = 16'b0000; -parameter LUT3 = 16'b0000; - -parameter INIT0 = 1'b0; -parameter INIT1 = 1'b0; -parameter INIT2 = 1'b0; -parameter INIT3 = 1'b0; - -parameter C0_MUX = "C0"; -parameter C1_MUX = "C1"; - -parameter F0_MUX = "VCC"; -parameter F1_MUX = "GND"; - -parameter FEEDBACK0 = "FF0"; -parameter FEEDBACK1 = "FF2"; - -parameter ADD_MUX = "LUT"; - -parameter DFF01_DATA_MUX = "COMB"; -parameter DFF23_DATA_MUX = "COMB"; - -parameter DFF0_CLK = "CLK0"; -parameter DFF1_CLK = "CLK0"; -parameter DFF2_CLK = "CLK0"; -parameter DFF3_CLK = "CLK0"; - -parameter DFF0_AC = "AC0"; -parameter DFF1_AC = "AC0"; -parameter DFF2_AC = "AC0"; -parameter DFF3_AC = "AC0"; - -// Feedback muxes from the flip-flop outputs. -wire ff_feedback_mux0, ff_feedback_mux1; - -// C-input muxes which can be set to also use the F-input. -wire c0_input_mux, c1_input_mux; - -// F-input muxes which can be set to a constant to allow LUT5 use. -wire f0_input_mux, f1_input_mux; - -// Adder input muxes to select between shared-arithmetic mode and arithmetic mode. -wire add0_input_mux, add1_input_mux; - -// Combinational-output muxes for LUT #1 and LUT #3 -wire lut1_comb_mux, lut3_comb_mux; - -// Sum-output muxes for LUT #1 and LUT #3 -wire lut1_sum_mux, lut3_sum_mux; - -// DFF data-input muxes -wire dff01_data_mux, dff23_data_mux; - -// DFF clock selectors -wire dff0_clk, dff1_clk, dff2_clk, dff3_clk; - -// DFF asynchronous-clear selectors -wire dff0_ac, dff1_ac, dff2_ac, dff3_ac; - -// LUT, DFF and adder output wires for routing. -wire lut0_out, lut1a_out, lut1b_out, lut2_out, lut3a_out, lut3b_out; -wire dff0_out, dff1_out, dff2_out, dff3_out; -wire add0_sum, add1_sum, add0_carry, add1_carry; - -generate - if (FEEDBACK0 === "FF0") - assign ff_feedback_mux0 = dff0_out; - else if (FEEDBACK0 === "FF1") - assign ff_feedback_mux0 = dff1_out; - else - $error("Invalid FEEDBACK0 setting!"); - - if (FEEDBACK1 == "FF2") - assign ff_feedback_mux1 = dff2_out; - else if (FEEDBACK1 == "FF3") - assign ff_feedback_mux1 = dff3_out; - else - $error("Invalid FEEDBACK1 setting!"); - - if (C0_MUX === "C0") - assign c0_input_mux = C0; - else if (C0_MUX === "F1") - assign c0_input_mux = F1; - else if (C0_MUX === "FEEDBACK1") - assign c0_input_mux = ff_feedback_mux1; - else - $error("Invalid C0_MUX setting!"); - - if (C1_MUX === "C1") - assign c1_input_mux = C1; - else if (C1_MUX === "F0") - assign c1_input_mux = F0; - else if (C1_MUX === "FEEDBACK0") - assign c1_input_mux = ff_feedback_mux0; - else - $error("Invalid C1_MUX setting!"); - - // F0 == VCC is LUT5 - // F0 == F0 is LUT6 - // F0 == FEEDBACK is unknown - if (F0_MUX === "VCC") - assign f0_input_mux = 1'b1; - else if (F0_MUX === "F0") - assign f0_input_mux = F0; - else if (F0_MUX === "FEEDBACK0") - assign f0_input_mux = ff_feedback_mux0; - else - $error("Invalid F0_MUX setting!"); - - // F1 == GND is LUT5 - // F1 == F1 is LUT6 - // F1 == FEEDBACK is unknown - if (F1_MUX === "GND") - assign f1_input_mux = 1'b0; - else if (F1_MUX === "F1") - assign f1_input_mux = F1; - else if (F1_MUX === "FEEDBACK1") - assign f1_input_mux = ff_feedback_mux1; - else - $error("Invalid F1_MUX setting!"); - - if (ADD_MUX === "LUT") begin - assign add0_input_mux = ~lut1_sum_mux; - assign add1_input_mux = ~lut3_sum_mux; - end else if (ADD_MUX === "SHARE") begin - assign add0_input_mux = SHAREIN; - assign add1_input_mux = lut1_comb_mux; - end else - $error("Invalid ADD_MUX setting!"); - - if (DFF01_DATA_MUX === "COMB") - assign dff01_data_mux = COMB0; - else if (DFF01_DATA_MUX === "SUM") - assign dff01_data_mux = SUM0; - else - $error("Invalid DFF01_DATA_MUX setting!"); - - if (DFF23_DATA_MUX === "COMB") - assign dff23_data_mux = COMB0; - else if (DFF23_DATA_MUX === "SUM") - assign dff23_data_mux = SUM0; - else - $error("Invalid DFF23_DATA_MUX setting!"); - - if (DFF0_CLK === "CLK0") - assign dff0_clk = CLK0; - else if (DFF0_CLK === "CLK1") - assign dff0_clk = CLK1; - else if (DFF0_CLK === "CLK2") - assign dff0_clk = CLK2; - else - $error("Invalid DFF0_CLK setting!"); - - if (DFF1_CLK === "CLK0") - assign dff1_clk = CLK0; - else if (DFF1_CLK === "CLK1") - assign dff1_clk = CLK1; - else if (DFF1_CLK === "CLK2") - assign dff1_clk = CLK2; - else - $error("Invalid DFF1_CLK setting!"); - - if (DFF2_CLK === "CLK0") - assign dff2_clk = CLK0; - else if (DFF2_CLK === "CLK1") - assign dff2_clk = CLK1; - else if (DFF2_CLK === "CLK2") - assign dff2_clk = CLK2; - else - $error("Invalid DFF2_CLK setting!"); - - if (DFF3_CLK === "CLK0") - assign dff3_clk = CLK0; - else if (DFF3_CLK === "CLK1") - assign dff3_clk = CLK1; - else if (DFF3_CLK === "CLK2") - assign dff3_clk = CLK2; - else - $error("Invalid DFF3_CLK setting!"); - - if (DFF0_AC === "AC0") - assign dff0_ac = AC0; - else if (DFF0_AC === "AC1") - assign dff0_ac = AC1; - else - $error("Invalid DFF0_AC setting!"); - - if (DFF1_AC === "AC0") - assign dff1_ac = AC0; - else if (DFF1_AC === "AC1") - assign dff1_ac = AC1; - else - $error("Invalid DFF1_AC setting!"); - - if (DFF2_AC === "AC0") - assign dff2_ac = AC0; - else if (DFF2_AC === "AC1") - assign dff2_ac = AC1; - else - $error("Invalid DFF2_AC setting!"); - - if (DFF3_AC === "AC0") - assign dff3_ac = AC0; - else if (DFF3_AC === "AC1") - assign dff3_ac = AC1; - else - $error("Invalid DFF3_AC setting!"); - -endgenerate - -// F0 on the Quartus diagram -MISTRAL_ALUT4 #(.LUT(LUT0)) lut0 (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut0_out)); - -// F2 on the Quartus diagram -MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_comb (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut1_comb_mux)); -MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_sum (.A(A), .B(B), .C(C0), .D(E0), .Q(lut1_sum_mux)); - -// F1 on the Quartus diagram -MISTRAL_ALUT4 #(.LUT(LUT2)) lut2 (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut2_out)); - -// F3 on the Quartus diagram -MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_comb (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut3_comb_mux)); -MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_sum (.A(A), .B(B), .C(C1), .D(E1), .Q(lut3_sum_mux)); - -MISTRAL_FF #(.INIT(INIT0)) dff0 (.D(dff01_data_mux), .CLK(dff0_clk), .ACn(dff0_ac), .Q(dff0_out)); -MISTRAL_FF #(.INIT(INIT1)) dff1 (.D(dff01_data_mux), .CLK(dff1_clk), .ACn(dff1_ac), .Q(dff1_out)); -MISTRAL_FF #(.INIT(INIT2)) dff2 (.D(dff23_data_mux), .CLK(dff2_clk), .ACn(dff2_ac), .Q(dff2_out)); -MISTRAL_FF #(.INIT(INIT3)) dff3 (.D(dff23_data_mux), .CLK(dff3_clk), .ACn(dff3_ac), .Q(dff3_out)); - -// Adders -assign {add0_carry, add0_sum} = CARRYIN + lut0_out + lut1_sum_mux; -assign {add1_carry, add1_sum} = add0_carry + lut2_out + lut3_sum_mux; - -// COMBOUT outputs on the Quartus diagram -assign COMB0 = E0 ? (f0_input_mux ? lut3_comb_mux : lut1_comb_mux) - : (f0_input_mux ? lut2_out : lut0_out); - -assign COMB1 = E1 ? (f1_input_mux ? lut3_comb_mux : lut1_comb_mux) - : (f1_input_mux ? lut2_out : lut0_out); - -// SUMOUT output on the Quartus diagram -assign SUM0 = add0_sum; -assign SUM1 = add1_sum; - -// COUT output on the Quartus diagram -assign CARRYOUT = add1_carry; - -// SHAREOUT output on the Quartus diagram -assign SHAREOUT = lut3_comb_mux; - -// REGOUT outputs on the Quartus diagram -assign FF0 = dff0_out; -assign FF1 = dff1_out; -assign FF2 = dff2_out; -assign FF3 = dff3_out; - -endmodule -*/ diff --git a/techlibs/intel_le/common/quartus_rename.v b/techlibs/intel_le/common/quartus_rename.v index 15497b010..00449d522 100644 --- a/techlibs/intel_le/common/quartus_rename.v +++ b/techlibs/intel_le/common/quartus_rename.v @@ -1,4 +1,4 @@ -`ifdef cycloneiv +`ifdef cycloneiv `define LCELL cycloneiv_lcell_comb `define MAC cycloneiv_mac `define MLAB cycloneiv_mlab_cell @@ -29,24 +29,24 @@ endmodule module MISTRAL_ALUT4(input A, B, C, D, output Q); parameter [15:0] LUT = 16'h0000; - -`LCELL #(.lut_mask({4{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); +parameter sum_lutc_input = "datac"; +`LCELL #(.lut_mask(LUT),.sum_lutc_input(sum_lutc_input)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); endmodule module MISTRAL_ALUT3(input A, B, C, output Q); parameter [7:0] LUT = 8'h00; - -`LCELL #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); +parameter sum_lutc_input = "datac"; +`LCELL #(.lut_mask({2{LUT}}),.sum_lutc_input(sum_lutc_input)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); endmodule module MISTRAL_ALUT2(input A, B, output Q); parameter [3:0] LUT = 4'h0; - -`LCELL #(.lut_mask({16{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); +parameter sum_lutc_input = "datac"; +`LCELL #(.lut_mask({4{LUT}}),.sum_lutc_input(sum_lutc_input)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); endmodule @@ -60,8 +60,8 @@ endmodule module MISTRAL_ALUT_ARITH(input A, B, C, D, CI, output SO, CO); parameter LUT = 16'h0000; - -`LCELL #(.lut_mask({16'h0, LUT})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .cin(CI), .sumout(SO), .cout(CO)); +parameter sum_lutc_input = "datac"; +`LCELL #(.lut_mask({LUT}),.sum_lutc_input(sum_lutc_input)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .cin(CI), .sumout(SO), .cout(CO)); endmodule diff --git a/techlibs/intel_le/cycloneiv/cells_sim.v b/techlibs/intel_le/cycloneiv/cells_sim.v index 0f7432fc7..48b2651b0 100644 --- a/techlibs/intel_le/cycloneiv/cells_sim.v +++ b/techlibs/intel_le/cycloneiv/cells_sim.v @@ -48,67 +48,7 @@ module cycloneiv_lcell_comb parameter lpm_type = "cycloneiv_lcell_comb"; parameter sum_lutc_input = "datac"; - reg cout_tmp; - reg combout_tmp; - reg [1:0] isum_lutc_input; - - wire dataa_in; - wire datab_in; - wire datac_in; - wire datad_in; - wire cin_in; - - // Simulation model of 4-input LUT - function lut4; - input [15:0] mask; - input dataa, datab, datac, datad; - reg [7:0] s3; - reg [3:0] s2; - reg [1:0] s1; - begin - s3 = datad ? mask[15:8] : mask[7:0]; - s2 = datac ? s3[7:4] : s3[3:0]; - s1 = datab ? s2[3:2] : s2[1:0]; - lut4 = dataa ? s1[1] : s1[0]; - end - endfunction // lut4 - - - initial - begin - if (sum_lutc_input == "datac") - isum_lutc_input = 0; - else if (sum_lutc_input == "cin") - isum_lutc_input = 1; - else - begin - $display ("Error: Invalid sum_lutc_input specified\n"); - $display ("Time: %0t Instance: %m", $time); - isum_lutc_input = 2; - end - - end - - always @(datad_in or datac_in or datab_in or dataa_in or cin_in) - begin - - if (isum_lutc_input == 0) // datac - begin - combout_tmp = lut4(lut_mask, dataa_in, datab_in, - datac_in, datad_in); - end - else if (isum_lutc_input == 1) // cin - begin - combout_tmp = lut4(lut_mask, dataa_in, datab_in, - cin_in, datad_in); - end - - cout_tmp = lut4(lut_mask, dataa_in, datab_in, cin_in, 'b0); - end - - and (combout, combout_tmp, 1'b1) ; - and (cout, cout_tmp, 1'b1) ; endmodule // cycloneiv_lcell_comb From 7a8efe9f1be77db80e0ffce4b62ec362baca8c9f Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Sat, 31 Oct 2020 00:59:48 +0100 Subject: [PATCH 08/15] before some refactoring --- techlibs/intel_le/common/le_map.v | 10 ---- techlibs/intel_le/common/le_sim.v | 2 - techlibs/intel_le/common/megafunction_bb.v | 37 ------------- techlibs/intel_le/common/mem_sim.v | 53 +----------------- techlibs/intel_le/common/quartus_rename.v | 64 +++++----------------- 5 files changed, 16 insertions(+), 150 deletions(-) diff --git a/techlibs/intel_le/common/le_map.v b/techlibs/intel_le/common/le_map.v index 6697b2e78..a1881e17a 100644 --- a/techlibs/intel_le/common/le_map.v +++ b/techlibs/intel_le/common/le_map.v @@ -40,16 +40,6 @@ generate MISTRAL_ALUT4 #(.LUT(LUT)) _TECHMAP_REPLACE_( .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .Q(Y) ); - end else - if (WIDTH == 5) begin - MISTRAL_ALUT5 #(.LUT(LUT)) _TECHMAP_REPLACE_ ( - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .Q(Y) - ); - end else - if (WIDTH == 6) begin - MISTRAL_ALUT6 #(.LUT(LUT)) _TECHMAP_REPLACE_ ( - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .F(A[5]), .Q(Y) - ); end else begin wire _TECHMAP_FAIL_ = 1'b1; end diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v index 465c7c14b..95d273c14 100644 --- a/techlibs/intel_le/common/le_sim.v +++ b/techlibs/intel_le/common/le_sim.v @@ -168,8 +168,6 @@ endspecify wire q0, q1; -//assign q0 = LUT >> sum_lutc_input == "cin" ? {'b0, CI, B, A}:{'b0, C, B, A}; -//assign q1 = LUT >> sum_lutc_input == "cin" ? {D, CI, B, A}:{D, C, B, A}; assign q0 = LUT >> {'b0, CI, B, A}; assign q1 = LUT >> {D, CI, B, A}; diff --git a/techlibs/intel_le/common/megafunction_bb.v b/techlibs/intel_le/common/megafunction_bb.v index 0f723f7a1..8eaaa62b8 100644 --- a/techlibs/intel_le/common/megafunction_bb.v +++ b/techlibs/intel_le/common/megafunction_bb.v @@ -538,28 +538,6 @@ output eccstatus; endmodule -(* blackbox *) -module cycloneiv_mlab_cell(portaaddr, portadatain, portbaddr, portbdataout, ena0, clk0, clk1); - -parameter logical_ram_name = ""; -parameter logical_ram_depth = 32; -parameter logical_ram_width = 20; -parameter mixed_port_feed_through_mode = "new"; -parameter first_bit_number = 0; -parameter first_address = 0; -parameter last_address = 31; -parameter address_width = 5; -parameter data_width = 1; -parameter byte_enable_mask_width = 1; -parameter port_b_data_out_clock = "NONE"; -parameter [639:0] mem_init0 = 640'b0; - -input [address_width-1:0] portaaddr, portbaddr; -input [data_width-1:0] portadatain; -output [data_width-1:0] portbdataout; -input ena0, clk0, clk1; - -endmodule (* blackbox *) module cycloneiv_mac(ax, ay, resulta); @@ -577,21 +555,6 @@ output [result_a_width-1:0] resulta; endmodule -(* blackbox *) -module cyclone10gx_mac(ax, ay, resulta); - -parameter ax_width = 18; -parameter signed_max = "true"; -parameter ay_scan_in_width = 18; -parameter signed_may = "true"; -parameter result_a_width = 36; -parameter operation_mode = "M18X18_FULL"; - -input [ax_width-1:0] ax; -input [ay_scan_in_width-1:0] ay; -output [result_a_width-1:0] resulta; - -endmodule (* blackbox *) module cycloneiv_ram_block(portaaddr, portadatain, portawe, portbaddr, portbdataout, portbre, clk0); diff --git a/techlibs/intel_le/common/mem_sim.v b/techlibs/intel_le/common/mem_sim.v index db5f40fb5..adc5c45cb 100644 --- a/techlibs/intel_le/common/mem_sim.v +++ b/techlibs/intel_le/common/mem_sim.v @@ -20,65 +20,14 @@ // a MISTRAL_MLAB cell represents one of these 32 address by 1-bit cells, and // 20 of them represent a physical MLAB. // -// How the MLAB works -// ------------------ -// MLABs are poorly documented, so the following information is based mainly -// on the simulation model and my knowledge of how memories like these work. -// Additionally, note that the ports of MISTRAL_MLAB are the ones auto-generated -// by the Yosys `memory_bram` pass, and it doesn't make sense to me to use -// `techmap` just for the sake of renaming the cell ports. -// -// The MLAB can be initialised to any value, but unfortunately Quartus only -// allows memory initialisation from a file. Since Yosys doesn't preserve input -// file information, or write the contents of an `initial` block to a file, -// Yosys can't currently initialise the MLAB in a way Quartus will accept. -// -// The MLAB takes in data from A1DATA at the rising edge of CLK1, and if A1EN -// is high, writes it to the address in A1ADDR. A1EN can therefore be used to -// conditionally write data to the MLAB. -// -// Simultaneously, the MLAB reads data from B1ADDR, and outputs it to B1DATA, -// asynchronous to CLK1 and ignoring A1EN. If a synchronous read is needed -// then the output can be fed to embedded flops. Presently, Yosys assumes -// Quartus will pack external flops into the MLAB, but this is an assumption -// that needs testing. -// The vendor sim model outputs 'x for a very short period (a few -// combinational delta cycles) after each write. This has been omitted from -// the following model because it's very difficult to trigger this in practice -// as clock cycles will be much longer than any potential blip of 'x, so the -// model can be treated as always returning a defined result. -(* abc9_box, lib_whitebox *) -module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA); - -reg [31:0] mem = 32'b0; - -// TODO: Cyclone 10 GX timings; the below timings are for Cyclone V -specify - $setup(A1ADDR, posedge CLK1, 86); - $setup(A1DATA, posedge CLK1, 86); - $setup(A1EN, posedge CLK1, 86); - - (B1ADDR[0] => B1DATA) = 487; - (B1ADDR[1] => B1DATA) = 475; - (B1ADDR[2] => B1DATA) = 382; - (B1ADDR[3] => B1DATA) = 284; - (B1ADDR[4] => B1DATA) = 96; -endspecify - -always @(posedge CLK1) - if (A1EN) mem[A1ADDR] <= A1DATA; - -assign B1DATA = mem[B1ADDR]; - -endmodule // The M9K // -------- // TODO -module MISTRAL_M10K(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); +module MISTRAL_M9K(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); parameter CFG_ABITS = 10; parameter CFG_DBITS = 10; diff --git a/techlibs/intel_le/common/quartus_rename.v b/techlibs/intel_le/common/quartus_rename.v index 00449d522..39076206a 100644 --- a/techlibs/intel_le/common/quartus_rename.v +++ b/techlibs/intel_le/common/quartus_rename.v @@ -1,8 +1,12 @@ -`ifdef cycloneiv -`define LCELL cycloneiv_lcell_comb -`define MAC cycloneiv_mac -`define MLAB cycloneiv_mlab_cell +`ifdef cycloneiv + `define LCELL cycloneiv_lcell_comb + `define M9K cycloneiv_ram_block `endif +`ifdef cycloneive + `define LCELL cycloneive_lcell_comb + `define M9K cycloneive_ram_block +`endif + module __MISTRAL_VCC(output Q); @@ -53,62 +57,24 @@ endmodule module MISTRAL_NOT(input A, output Q); -NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q)); - +//NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q)); +assign Q = ~A; endmodule module MISTRAL_ALUT_ARITH(input A, B, C, D, CI, output SO, CO); parameter LUT = 16'h0000; parameter sum_lutc_input = "datac"; -`LCELL #(.lut_mask({LUT}),.sum_lutc_input(sum_lutc_input)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .cin(CI), .sumout(SO), .cout(CO)); +`LCELL #(.lut_mask({LUT}),.sum_lutc_input(sum_lutc_input)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .cin(CI), .combout(SO), .cout(CO)); endmodule -module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA); - -parameter _TECHMAP_CELLNAME_ = ""; - -// Here we get to an unfortunate situation. The cell has a mem_init0 parameter, -// which takes in a hexadecimal string that could be used to initialise RAM. -// In the vendor simulation models, this appears to work fine, but Quartus, -// either intentionally or not, forgets about this parameter and initialises the -// RAM to zero. -// -// Because of this, RAM initialisation is presently disabled, but the source -// used to generate mem_init0 is kept (commented out) in case this gets fixed -// or an undocumented way to get Quartus to initialise from mem_init0 is found. - -`MLAB #( - .logical_ram_name(_TECHMAP_CELLNAME_), - .logical_ram_depth(32), - .logical_ram_width(1), - .mixed_port_feed_through_mode("Dont Care"), - .first_bit_number(0), - .first_address(0), - .last_address(31), - .address_width(5), - .data_width(1), - .byte_enable_mask_width(1), - .port_b_data_out_clock("NONE"), - // .mem_init0($sformatf("%08x", INIT)) -) _TECHMAP_REPLACE_ ( - .portaaddr(A1ADDR), - .portadatain(A1DATA), - .portbaddr(B1ADDR), - .portbdataout(B1DATA), - .ena0(A1EN), - .clk0(CLK1) -); - -endmodule - module MISTRAL_M9K(A1ADDR, A1DATA, A1EN, CLK1, B1ADDR, B1DATA, B1EN); -parameter CFG_ABITS = 10; -parameter CFG_DBITS = 10; +parameter CFG_ABITS = 9; +parameter CFG_DBITS = 9; parameter _TECHMAP_CELLNAME_ = ""; @@ -117,10 +83,10 @@ input [CFG_DBITS-1:0] A1DATA; input CLK1, A1EN, B1EN; output [CFG_DBITS-1:0] B1DATA; -// Much like the MLAB, the M9K has mem_init[01234] parameters which would let +// The M9K has mem_init[01234] parameters which would let // you initialise the RAM cell via hex literals. If they were implemented. -cycloneiv_ram_block #( +`M9K #( .operation_mode("dual_port"), .logical_ram_name(_TECHMAP_CELLNAME_), .port_a_address_width(CFG_ABITS), From f7dc93c65239ddadc2dc2d68575550a8ff53e77c Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Sun, 1 Nov 2020 16:09:03 +0100 Subject: [PATCH 09/15] some refactoring --- techlibs/intel_le/common/arith_le_map.v | 14 ++++--- techlibs/intel_le/common/dff_sim.v | 2 +- techlibs/intel_le/common/le_sim.v | 49 ++++++++++++++++++++--- techlibs/intel_le/common/mem_sim.v | 24 ----------- techlibs/intel_le/common/quartus_rename.v | 18 ++++----- techlibs/intel_le/synth_intel_le.cc | 7 ++-- 6 files changed, 66 insertions(+), 48 deletions(-) diff --git a/techlibs/intel_le/common/arith_le_map.v b/techlibs/intel_le/common/arith_le_map.v index 614e343af..07170c4c0 100644 --- a/techlibs/intel_le/common/arith_le_map.v +++ b/techlibs/intel_le/common/arith_le_map.v @@ -33,27 +33,31 @@ wire [Y_WIDTH-1:0] BX = B_buf; wire [Y_WIDTH-1:0] BTOADDER; wire [Y_WIDTH:0] LE_CARRY; + // Start of carry chain generate if (_TECHMAP_CONSTMSK_CI_ == 1) begin assign LE_CARRY[0] = _TECHMAP_CONSTVAL_CI_; end else begin + /* MISTRAL_ALUT_ARITH #( .LUT(16'b1010_1010_1010_1010), // Q = A - .sum_lutc_input("cin") + ) le_start ( .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1), .CI(1'b0), .SO(), .CO(LE_CARRY[0]) ); + */ + assign LE_CARRY[0] = CI; end endgenerate // Carry chain genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice - + /* MISTRAL_ALUT_ARITH #( .LUT(16'b0110_0110_0110_0110), // Q = A ? ~B : B .sum_lutc_input("cin") @@ -63,14 +67,14 @@ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice .SO(BTOADDER[i]), .CO() ); - + */ MISTRAL_ALUT_ARITH #( .LUT(16'b1001_0110_1110_1000), // SUM = A xor B xor CI // CARRYi+1 = A and B or A and CI or B and CI - .sum_lutc_input("cin") + ) le_i ( - .A(AA[i]), .B(BTOADDER[i]), .C(1'b1), .D(1'b1), + .A(AA[i]), .B(BB[i]), .C(1'b1), .D(1'b1), .CI(LE_CARRY[i]), .SO(Y[i]), .CO(LE_CARRY[i+1]) diff --git a/techlibs/intel_le/common/dff_sim.v b/techlibs/intel_le/common/dff_sim.v index 05c3dce86..36a929489 100644 --- a/techlibs/intel_le/common/dff_sim.v +++ b/techlibs/intel_le/common/dff_sim.v @@ -75,7 +75,7 @@ specify if (ACLR === 1'b0) (ACLR => Q) = 282; endspecify `endif -`ifdef cyclone10gx +`ifdef cycloneive specify // TODO (long-term): investigate these numbers. // It seems relying on the Quartus Timing Analyzer was not the best idea; it's too fiddly. diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v index 95d273c14..4e89aaf2e 100644 --- a/techlibs/intel_le/common/le_sim.v +++ b/techlibs/intel_le/common/le_sim.v @@ -91,6 +91,14 @@ specify (D => Q) = 97; endspecify `endif +`ifdef cycloneive + specify + (A => Q) = 510; + (B => Q) = 512; + (C => Q) = 400; + (D => Q) = 97; + endspecify +`endif assign Q = LUT >> {D, C, B, A}; @@ -103,13 +111,19 @@ module MISTRAL_ALUT3(input A, B, C, output Q); parameter [7:0] LUT = 8'h00; `ifdef cycloneiv -specify +specify (A => Q) = 510; (B => Q) = 400; (C => Q) = 97; endspecify `endif - +`ifdef cycloneive + specify + (A => Q) = 510; + (B => Q) = 400; + (C => Q) = 97; + endspecify +`endif assign Q = LUT >> {C, B, A}; endmodule @@ -126,7 +140,12 @@ specify (B => Q) = 97; endspecify `endif - +`ifdef cycloneive + specify + (A => Q) = 400; + (B => Q) = 97; + endspecify +`endif assign Q = LUT >> {B, A}; endmodule @@ -135,12 +154,16 @@ endmodule (* abc9_lut=1, lib_whitebox *) module MISTRAL_NOT(input A, output Q); -`ifdef cycloneiv +`ifdef cycloneiv specify (A => Q) = 97; endspecify `endif - +`ifdef cycloneive + specify + (A => Q) = 97; + endspecify +`endif assign Q = ~A; endmodule @@ -149,7 +172,7 @@ endmodule module MISTRAL_ALUT_ARITH(input A, B, C, D, (* abc9_carry *) input CI, output SO, (* abc9_carry *) output CO); parameter LUT = 16'h0000; -parameter sum_lutc_input = "cin"; + `ifdef cycloneiv specify (A => SO) = 1342; @@ -165,7 +188,21 @@ specify (CI => CO) = 36; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM) endspecify `endif +`ifdef cycloneive + specify + (A => SO) = 1342; + (B => SO) = 1323; + (C => SO) = 927; + (D => SO) = 887; + (CI => SO) = 368; + (A => CO) = 1082; + (B => CO) = 1062; + (C => CO) = 813; + (D => CO) = 866; + (CI => CO) = 36; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM) + endspecify +`endif wire q0, q1; diff --git a/techlibs/intel_le/common/mem_sim.v b/techlibs/intel_le/common/mem_sim.v index adc5c45cb..66bc4f82c 100644 --- a/techlibs/intel_le/common/mem_sim.v +++ b/techlibs/intel_le/common/mem_sim.v @@ -1,27 +1,3 @@ -// The MLAB -// -------- -// In addition to Logic Array Blocks (LABs) that contain ten Adaptive Logic -// Modules (ALMs, see alm_sim.v), the Cyclone V/10GX also contain -// Memory/Logic Array Blocks (MLABs) that can act as either ten ALMs, or utilise -// the memory the ALM uses to store the look-up table data for general usage, -// producing a 32 address by 20-bit block of memory. MLABs are spread out -// around the chip, so they can be placed near where they are needed, rather than -// being comparatively limited in placement for a deep but narrow memory such as -// the M10K memory block. -// -// MLABs are used mainly for shallow but wide memories, such as CPU register -// files (which have perhaps 32 registers that are comparatively wide (16/32-bit)) -// or shift registers (by using the output of the Nth bit as input for the N+1th -// bit). -// -// Oddly, instead of providing a block 32 address by 20-bit cell, Quartus asks -// synthesis tools to build MLABs out of 32 address by 1-bit cells, and tries -// to put these cells in the same MLAB during cell placement. Because of this -// a MISTRAL_MLAB cell represents one of these 32 address by 1-bit cells, and -// 20 of them represent a physical MLAB. -// - - // The M9K // -------- diff --git a/techlibs/intel_le/common/quartus_rename.v b/techlibs/intel_le/common/quartus_rename.v index 39076206a..2fefd2a79 100644 --- a/techlibs/intel_le/common/quartus_rename.v +++ b/techlibs/intel_le/common/quartus_rename.v @@ -2,7 +2,7 @@ `define LCELL cycloneiv_lcell_comb `define M9K cycloneiv_ram_block `endif -`ifdef cycloneive +`ifdef cycloneive `define LCELL cycloneive_lcell_comb `define M9K cycloneive_ram_block `endif @@ -33,24 +33,24 @@ endmodule module MISTRAL_ALUT4(input A, B, C, D, output Q); parameter [15:0] LUT = 16'h0000; -parameter sum_lutc_input = "datac"; -`LCELL #(.lut_mask(LUT),.sum_lutc_input(sum_lutc_input)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); + +`LCELL #(.lut_mask(LUT),.sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); endmodule module MISTRAL_ALUT3(input A, B, C, output Q); parameter [7:0] LUT = 8'h00; -parameter sum_lutc_input = "datac"; -`LCELL #(.lut_mask({2{LUT}}),.sum_lutc_input(sum_lutc_input)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); + +`LCELL #(.lut_mask({2{LUT}}),.sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); endmodule module MISTRAL_ALUT2(input A, B, output Q); parameter [3:0] LUT = 4'h0; -parameter sum_lutc_input = "datac"; -`LCELL #(.lut_mask({4{LUT}}),.sum_lutc_input(sum_lutc_input)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); + +`LCELL #(.lut_mask({4{LUT}}),.sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); endmodule @@ -64,8 +64,8 @@ endmodule module MISTRAL_ALUT_ARITH(input A, B, C, D, CI, output SO, CO); parameter LUT = 16'h0000; -parameter sum_lutc_input = "datac"; -`LCELL #(.lut_mask({LUT}),.sum_lutc_input(sum_lutc_input)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .cin(CI), .combout(SO), .cout(CO)); + +`LCELL #(.lut_mask({LUT}),.sum_lutc_input("cin")) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .cin(CI), .combout(SO), .cout(CO)); endmodule diff --git a/techlibs/intel_le/synth_intel_le.cc b/techlibs/intel_le/synth_intel_le.cc index 84527fab1..dc3cd8ce8 100644 --- a/techlibs/intel_le/synth_intel_le.cc +++ b/techlibs/intel_le/synth_intel_le.cc @@ -43,6 +43,7 @@ struct SynthIntelLEPass : public ScriptPass { log(" -family \n"); log(" target one of:\n"); log(" \"cycloneiv\" - Cyclone IV (default)\n"); + log(" \"cycloneive\" - Cyclone IV E \n"); log("\n"); log(" -vqm \n"); log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n"); @@ -144,7 +145,7 @@ struct SynthIntelLEPass : public ScriptPass { if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); - if (family_opt == "cycloneiv") { + if (family_opt == "cycloneiv" or family_opt == "cycloneive") { bram_type = "m9k"; } else { log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str()); @@ -166,8 +167,8 @@ struct SynthIntelLEPass : public ScriptPass { } if (check_label("begin")) { - if (family_opt == "cycloneiv") - run(stringf("read_verilog -sv -lib +/intel_le/%s/cells_sim.v", family_opt.c_str())); + if (family_opt == "cycloneiv" or family_opt == "cycloneive") + run(stringf("read_verilog -sv -lib +/intel_le/cycloneiv/cells_sim.v")); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/le_sim.v", family_opt.c_str())); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/dff_sim.v", family_opt.c_str())); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/mem_sim.v", family_opt.c_str())); From f8bcb78a3286386ddcedd53a2492c76fe6a5dfc8 Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Tue, 3 Nov 2020 00:35:35 +0100 Subject: [PATCH 10/15] cleanup in le tests --- techlibs/intel_le/synth_intel_le.cc | 2 - tests/arch/intel_le/add_sub.ys | 11 ++++-- tests/arch/intel_le/adffs.ys | 16 ++++---- tests/arch/intel_le/blockram.ys | 8 ++-- tests/arch/intel_le/counter.ys | 5 ++- tests/arch/intel_le/dffs.ys | 8 ++-- tests/arch/intel_le/fsm.ys | 22 +++++------ tests/arch/intel_le/logic.ys | 4 +- tests/arch/intel_le/lutram.ys | 41 -------------------- tests/arch/intel_le/mul.ys | 60 ----------------------------- tests/arch/intel_le/mux.ys | 53 +++++++++++++------------ tests/arch/intel_le/quartus_ice.ys | 4 +- tests/arch/intel_le/shifter.ys | 4 +- tests/arch/intel_le/tribuf.ys | 4 +- 14 files changed, 69 insertions(+), 173 deletions(-) delete mode 100644 tests/arch/intel_le/lutram.ys delete mode 100644 tests/arch/intel_le/mul.ys diff --git a/techlibs/intel_le/synth_intel_le.cc b/techlibs/intel_le/synth_intel_le.cc index dc3cd8ce8..d85495327 100644 --- a/techlibs/intel_le/synth_intel_le.cc +++ b/techlibs/intel_le/synth_intel_le.cc @@ -208,8 +208,6 @@ struct SynthIntelLEPass : public ScriptPass { if (!nobram && check_label("map_bram", "(skip if -nobram)")) { run(stringf("memory_bram -rules +/intel_le/common/bram_%s.txt", bram_type.c_str())); - if (help_mode || bram_type != "m9k") - run(stringf("techmap -map +/intel_le/common/bram_%s_map.v", bram_type.c_str())); } if (check_label("map_ffram")) { diff --git a/tests/arch/intel_le/add_sub.ys b/tests/arch/intel_le/add_sub.ys index ac75935b7..da0f2bcb5 100644 --- a/tests/arch/intel_le/add_sub.ys +++ b/tests/arch/intel_le/add_sub.ys @@ -1,18 +1,21 @@ read_verilog ../common/add_sub.v hierarchy -top top -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module stat select -assert-count 8 t:MISTRAL_ALUT_ARITH -select -assert-none t:MISTRAL_ALUT_ARITH %% t:* %D +select -assert-count 4 t:MISTRAL_NOT +select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH %% t:* %D + design -reset read_verilog ../common/add_sub.v hierarchy -top top -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module stat select -assert-count 8 t:MISTRAL_ALUT_ARITH -select -assert-none t:MISTRAL_ALUT_ARITH %% t:* %D +select -assert-count 4 t:MISTRAL_NOT +select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH %% t:* %D diff --git a/tests/arch/intel_le/adffs.ys b/tests/arch/intel_le/adffs.ys index ec0085d65..2fb313696 100644 --- a/tests/arch/intel_le/adffs.ys +++ b/tests/arch/intel_le/adffs.ys @@ -3,7 +3,7 @@ design -save read hierarchy -top adff proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd adff # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF @@ -15,7 +15,7 @@ select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D design -load read hierarchy -top adff proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd adff # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF @@ -27,7 +27,7 @@ select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D design -load read hierarchy -top adffn proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd adffn # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF @@ -38,7 +38,7 @@ select -assert-none t:MISTRAL_FF %% t:* %D design -load read hierarchy -top adffn proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd adffn # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF @@ -49,7 +49,7 @@ select -assert-none t:MISTRAL_FF %% t:* %D design -load read hierarchy -top dffs proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd dffs # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF @@ -61,7 +61,7 @@ select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 %% t:* %D design -load read hierarchy -top dffs proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd dffs # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF @@ -73,7 +73,7 @@ select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 %% t:* %D design -load read hierarchy -top ndffnr proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd ndffnr # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF @@ -85,7 +85,7 @@ select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D design -load read hierarchy -top ndffnr proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd ndffnr # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF diff --git a/tests/arch/intel_le/blockram.ys b/tests/arch/intel_le/blockram.ys index ce7502571..8d260dbc3 100644 --- a/tests/arch/intel_le/blockram.ys +++ b/tests/arch/intel_le/blockram.ys @@ -1,6 +1,6 @@ read_verilog ../common/blockram.v -chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 10 sync_ram_sdp -synth_intel_le -family cyclonev +chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 9 sync_ram_sdp +synth_intel_le -family cycloneiv cd sync_ram_sdp -select -assert-count 1 t:MISTRAL_M10K -select -assert-none t:MISTRAL_M10K %% t:* %D +select -assert-count 1 t:MISTRAL_M9K +select -assert-none t:MISTRAL_M9K %% t:* %D diff --git a/tests/arch/intel_le/counter.ys b/tests/arch/intel_le/counter.ys index 147b3d4c0..d0a7b1f2d 100644 --- a/tests/arch/intel_le/counter.ys +++ b/tests/arch/intel_le/counter.ys @@ -2,7 +2,7 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten -equiv_opt -async2sync -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -async2sync -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module @@ -13,11 +13,12 @@ select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH t:MISTRAL_FF %% t:* %D design -reset + read_verilog ../common/counter.v hierarchy -top top proc flatten -equiv_opt -async2sync -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -async2sync -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/intel_le/dffs.ys b/tests/arch/intel_le/dffs.ys index 484e4b7ba..89db9e16f 100644 --- a/tests/arch/intel_le/dffs.ys +++ b/tests/arch/intel_le/dffs.ys @@ -3,7 +3,7 @@ design -save read hierarchy -top dff proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd dff # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF @@ -13,7 +13,7 @@ select -assert-none t:MISTRAL_FF %% t:* %D design -load read hierarchy -top dff proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd dff # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF @@ -24,7 +24,7 @@ select -assert-none t:MISTRAL_FF %% t:* %D design -load read hierarchy -top dffe proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd dffe # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF @@ -35,7 +35,7 @@ select -assert-none t:MISTRAL_FF %% t:* %D design -load read hierarchy -top dffe proc -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd dffe # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_FF diff --git a/tests/arch/intel_le/fsm.ys b/tests/arch/intel_le/fsm.ys index 0bccaf549..f2b3d631a 100644 --- a/tests/arch/intel_le/fsm.ys +++ b/tests/arch/intel_le/fsm.ys @@ -3,7 +3,7 @@ hierarchy -top fsm proc flatten -equiv_opt -run :prove -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev +equiv_opt -run :prove -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneiv async2sync miter -equiv -make_assert -flatten gold gate miter sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter @@ -13,12 +13,10 @@ cd fsm # Constrain all select calls below inside the top module select -assert-count 6 t:MISTRAL_FF select -assert-max 1 t:MISTRAL_NOT -select -assert-max 2 t:MISTRAL_ALUT2 # Clang returns 2, GCC returns 1 +select -assert-max 5 t:MISTRAL_ALUT2 # select -assert-max 1 t:MISTRAL_ALUT3 -select -assert-max 2 t:MISTRAL_ALUT4 # Clang returns 0, GCC returns 1 -select -assert-max 6 t:MISTRAL_ALUT5 # Clang returns 5, GCC returns 4 -select -assert-max 2 t:MISTRAL_ALUT6 # Clang returns 1, GCC returns 2 -select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D +select -assert-max 9 t:MISTRAL_ALUT4 # +select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D design -reset read_verilog ../common/fsm.v @@ -26,7 +24,7 @@ hierarchy -top fsm proc flatten -equiv_opt -run :prove -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx +equiv_opt -run :prove -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive async2sync miter -equiv -make_assert -flatten gold gate miter sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter @@ -36,9 +34,7 @@ cd fsm # Constrain all select calls below inside the top module select -assert-count 6 t:MISTRAL_FF select -assert-max 1 t:MISTRAL_NOT -select -assert-max 2 t:MISTRAL_ALUT2 # Clang returns 2, GCC returns 1 -select -assert-max 2 t:MISTRAL_ALUT3 # Clang returns 2, GCC returns 1 -select -assert-max 2 t:MISTRAL_ALUT4 # Clang returns 0, GCC returns 1 -select -assert-max 6 t:MISTRAL_ALUT5 # Clang returns 5, GCC returns 4 -select -assert-max 2 t:MISTRAL_ALUT6 # Clang returns 1, GCC returns 2 -select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D +select -assert-max 5 t:MISTRAL_ALUT2 # +select -assert-max 1 t:MISTRAL_ALUT3 +select -assert-max 9 t:MISTRAL_ALUT4 # +select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D diff --git a/tests/arch/intel_le/logic.ys b/tests/arch/intel_le/logic.ys index 689c9908f..1184558b7 100644 --- a/tests/arch/intel_le/logic.ys +++ b/tests/arch/intel_le/logic.ys @@ -1,7 +1,7 @@ read_verilog ../common/logic.v hierarchy -top top proc -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module @@ -15,7 +15,7 @@ design -reset read_verilog ../common/logic.v hierarchy -top top proc -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/arch/intel_le/lutram.ys b/tests/arch/intel_le/lutram.ys deleted file mode 100644 index f08bb1c7c..000000000 --- a/tests/arch/intel_le/lutram.ys +++ /dev/null @@ -1,41 +0,0 @@ -read_verilog ../common/lutram.v -hierarchy -top lutram_1w1r -proc -memory -nomap -equiv_opt -run :prove -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v -map +/intel_le/common/mem_sim.v synth_intel_le -family cyclonev -nobram -memory -opt -full - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter - -design -load postopt -cd lutram_1w1r -select -assert-count 16 t:MISTRAL_MLAB -select -assert-count 1 t:MISTRAL_NOT -select -assert-count 2 t:MISTRAL_ALUT2 -select -assert-count 8 t:MISTRAL_ALUT3 -select -assert-count 17 t:MISTRAL_FF -select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D - - -design -reset -read_verilog ../common/lutram.v -hierarchy -top lutram_1w1r -proc -memory -nomap -equiv_opt -run :prove -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v -map +/intel_le/common/mem_sim.v synth_intel_le -family cyclonev -nobram -memory -opt -full - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter - -design -load postopt -cd lutram_1w1r -select -assert-count 16 t:MISTRAL_MLAB -select -assert-count 1 t:MISTRAL_NOT -select -assert-count 2 t:MISTRAL_ALUT2 -select -assert-count 8 t:MISTRAL_ALUT3 -select -assert-count 17 t:MISTRAL_FF -select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D diff --git a/tests/arch/intel_le/mul.ys b/tests/arch/intel_le/mul.ys deleted file mode 100644 index e0b8e8142..000000000 --- a/tests/arch/intel_le/mul.ys +++ /dev/null @@ -1,60 +0,0 @@ -read_verilog ../common/mul.v -chparam -set X_WIDTH 8 -set Y_WIDTH 8 -set A_WIDTH 16 -hierarchy -top top -proc -equiv_opt -assert -map +/intel_le/common/dsp_sim.v synth_intel_le -family cyclonev # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module - -select -assert-count 1 t:MISTRAL_MUL9X9 -select -assert-none t:MISTRAL_MUL9X9 %% t:* %D - -# Cyclone 10 GX does not have 9x9 multipliers. - -design -reset -read_verilog ../common/mul.v -chparam -set X_WIDTH 17 -set Y_WIDTH 17 -set A_WIDTH 34 -hierarchy -top top -proc -equiv_opt -assert -map +/intel_le/common/dsp_sim.v synth_intel_le -family cyclonev # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module - -select -assert-count 1 t:MISTRAL_MUL18X18 -select -assert-none t:MISTRAL_MUL18X18 %% t:* %D - -design -reset -read_verilog ../common/mul.v -chparam -set X_WIDTH 17 -set Y_WIDTH 17 -set A_WIDTH 34 -hierarchy -top top -proc -equiv_opt -assert -map +/intel_le/common/dsp_sim.v synth_intel_le -family cyclone10gx # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module - -select -assert-count 1 t:MISTRAL_MUL18X18 -select -assert-none t:MISTRAL_MUL18X18 %% t:* %D - -design -reset -read_verilog ../common/mul.v -chparam -set X_WIDTH 26 -set Y_WIDTH 26 -set A_WIDTH 52 -hierarchy -top top -proc -equiv_opt -assert -map +/intel_le/common/dsp_sim.v synth_intel_le -family cyclonev # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module - -select -assert-count 1 t:MISTRAL_MUL27X27 -select -assert-none t:MISTRAL_MUL27X27 %% t:* %D - -design -reset -read_verilog ../common/mul.v -chparam -set X_WIDTH 26 -set Y_WIDTH 26 -set A_WIDTH 52 -hierarchy -top top -proc -equiv_opt -assert -map +/intel_le/common/dsp_sim.v synth_intel_le -family cyclone10gx # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module - -select -assert-count 1 t:MISTRAL_MUL27X27 -select -assert-none t:MISTRAL_MUL27X27 %% t:* %D diff --git a/tests/arch/intel_le/mux.ys b/tests/arch/intel_le/mux.ys index 67bdabae1..f5afafeb3 100644 --- a/tests/arch/intel_le/mux.ys +++ b/tests/arch/intel_le/mux.ys @@ -4,7 +4,7 @@ design -save read hierarchy -top mux2 proc -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux2 # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_ALUT3 @@ -14,7 +14,7 @@ select -assert-none t:MISTRAL_ALUT3 %% t:* %D design -load read hierarchy -top mux2 proc -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux2 # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_ALUT3 @@ -24,65 +24,64 @@ select -assert-none t:MISTRAL_ALUT3 %% t:* %D design -load read hierarchy -top mux4 proc -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux4 # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_ALUT6 -select -assert-none t:MISTRAL_ALUT6 %% t:* %D +select -assert-count 3 t:MISTRAL_ALUT3 +select -assert-none t:MISTRAL_ALUT3 %% t:* %D design -load read hierarchy -top mux4 proc -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux4 # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_ALUT6 -select -assert-none t:MISTRAL_ALUT6 %% t:* %D +select -assert-count 3 t:MISTRAL_ALUT3 +select -assert-none t:MISTRAL_ALUT3 %% t:* %D design -load read hierarchy -top mux8 proc -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux8 # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_ALUT3 -select -assert-count 2 t:MISTRAL_ALUT6 -select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT6 %% t:* %D +select -assert-count 3 t:MISTRAL_ALUT3 +select -assert-count 3 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D design -load read hierarchy -top mux8 proc -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux8 # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_ALUT3 -select -assert-count 2 t:MISTRAL_ALUT6 -select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT6 %% t:* %D +select -assert-count 3 t:MISTRAL_ALUT3 +select -assert-count 3 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D design -load read hierarchy -top mux16 proc -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_ALUT3 -select -assert-max 2 t:MISTRAL_ALUT5 -select -assert-max 5 t:MISTRAL_ALUT6 -select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D +select -assert-count 1 t:MISTRAL_ALUT2 +select -assert-max 6 t:MISTRAL_ALUT3 +select -assert-max 7 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D design -load read hierarchy -top mux16 proc -equiv_opt -assert -map +/intel_le/common/alm_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_ALUT3 -select -assert-count 2 t:MISTRAL_ALUT5 -select -assert-count 4 t:MISTRAL_ALUT6 - -select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D +select -assert-count 1 t:MISTRAL_ALUT2 +select -assert-max 6 t:MISTRAL_ALUT3 +select -assert-max 7 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D diff --git a/tests/arch/intel_le/quartus_ice.ys b/tests/arch/intel_le/quartus_ice.ys index 0f15f4d86..1855fbcb6 100644 --- a/tests/arch/intel_le/quartus_ice.ys +++ b/tests/arch/intel_le/quartus_ice.ys @@ -8,7 +8,7 @@ module top(); endmodule EOT -synth_intel_le -family cyclonev -quartus +synth_intel_le -family cycloneiv -quartus select -assert-none w:*[* w:*]* design -reset @@ -22,5 +22,5 @@ module top(); endmodule EOT -synth_intel_le -family cyclone10gx -quartus +synth_intel_le -family cycloneive -quartus select -assert-none w:*[* w:*]* diff --git a/tests/arch/intel_le/shifter.ys b/tests/arch/intel_le/shifter.ys index fb7b99c73..059f593d5 100644 --- a/tests/arch/intel_le/shifter.ys +++ b/tests/arch/intel_le/shifter.ys @@ -2,7 +2,7 @@ read_verilog ../common/shifter.v hierarchy -top top proc flatten -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 8 t:MISTRAL_FF @@ -14,7 +14,7 @@ read_verilog ../common/shifter.v hierarchy -top top proc flatten -equiv_opt -async2sync -assert -map +/intel_le/common/alm_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 8 t:MISTRAL_FF diff --git a/tests/arch/intel_le/tribuf.ys b/tests/arch/intel_le/tribuf.ys index 2ec25ad6a..40218ddcb 100644 --- a/tests/arch/intel_le/tribuf.ys +++ b/tests/arch/intel_le/tribuf.ys @@ -4,7 +4,7 @@ proc tribuf flatten synth -equiv_opt -assert -map +/simcells.v synth_intel_le -family cyclonev # equivalency check +equiv_opt -assert -map +/simcells.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd tristate # Constrain all select calls below inside the top module #Internal cell type used. Need support it. @@ -19,7 +19,7 @@ proc tribuf flatten synth -equiv_opt -assert -map +/simcells.v synth_intel_le -family cyclone10gx # equivalency check +equiv_opt -assert -map +/simcells.v synth_intel_le -family cycloneive # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd tristate # Constrain all select calls below inside the top module #Internal cell type used. Need support it. From 1452cd88e897b7609a481cb1cccfc2de7d0345b6 Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Sat, 14 Nov 2020 18:05:14 +0100 Subject: [PATCH 11/15] remove cycloneive --- techlibs/intel_alm/common/alm_sim.v | 2 +- techlibs/intel_le/common/dff_sim.v | 26 +---- techlibs/intel_le/common/le_sim.v | 130 ++++------------------ techlibs/intel_le/common/quartus_rename.v | 4 - techlibs/intel_le/synth_intel_le.cc | 5 +- tests/arch/intel_le/add_sub.ys | 9 -- tests/arch/intel_le/adffs.ys | 45 -------- tests/arch/intel_le/counter.ys | 12 -- tests/arch/intel_le/dffs.ys | 19 ---- tests/arch/intel_le/fsm.ys | 19 ---- tests/arch/intel_le/logic.ys | 11 -- tests/arch/intel_le/mux.ys | 42 ------- tests/arch/intel_le/quartus_ice.ys | 12 -- tests/arch/intel_le/shifter.ys | 9 -- tests/arch/intel_le/tribuf.ys | 12 -- 15 files changed, 24 insertions(+), 333 deletions(-) diff --git a/techlibs/intel_alm/common/alm_sim.v b/techlibs/intel_alm/common/alm_sim.v index 906a95b0b..9689876c3 100644 --- a/techlibs/intel_alm/common/alm_sim.v +++ b/techlibs/intel_alm/common/alm_sim.v @@ -169,7 +169,7 @@ module MISTRAL_ALUT3(input A, B, C, output Q); parameter [7:0] LUT = 8'h00; -`ifdef cyclonev +`ifdef cyclonev specify (A => Q) = 510; (B => Q) = 400; diff --git a/techlibs/intel_le/common/dff_sim.v b/techlibs/intel_le/common/dff_sim.v index 36a929489..cb3a01185 100644 --- a/techlibs/intel_le/common/dff_sim.v +++ b/techlibs/intel_le/common/dff_sim.v @@ -1,10 +1,3 @@ -// The four D flip-flops (DFFs) in a Cyclone V/10GX Adaptive Logic Module (ALM) -// act as one-bit memory cells that can be placed very flexibly (wherever there's -// an ALM); each flop is represented by a MISTRAL_FF cell. -// -// The flops in these chips are rather flexible in some ways, but in practice -// quite crippled by FPGA standards. -// // What the flops can do // --------------------- // The core flop acts as a single-bit memory that initialises to zero at chip @@ -60,7 +53,7 @@ module MISTRAL_FF( output reg Q ); -`ifdef cycloneiv +`ifdef cycloneiv specify if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 731; if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 890; @@ -75,23 +68,6 @@ specify if (ACLR === 1'b0) (ACLR => Q) = 282; endspecify `endif -`ifdef cycloneive -specify - // TODO (long-term): investigate these numbers. - // It seems relying on the Quartus Timing Analyzer was not the best idea; it's too fiddly. - if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 219; - if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 219; - if (ENA && !SCLR && SLOAD) (posedge CLK => (Q : SDATA)) = 219; - - $setup(DATAIN, posedge CLK, 268); - $setup(ENA, posedge CLK, 268); - $setup(SCLR, posedge CLK, 268); - $setup(SLOAD, posedge CLK, 268); - $setup(SDATA, posedge CLK, 268); - - if (ACLR === 1'b0) (ACLR => Q) = 0; -endspecify -`endif initial begin // Altera flops initialise to zero. diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v index 4e89aaf2e..4ac39e617 100644 --- a/techlibs/intel_le/common/le_sim.v +++ b/techlibs/intel_le/common/le_sim.v @@ -1,81 +1,32 @@ -// The core logic primitive of the Cyclone V/10GX is the Adaptive Logic Module -// (ALM). Each ALM is made up of an 8-input, 2-output look-up table, covered -// in this file, connected to combinational outputs, a carry chain, and four -// D flip-flops (which are covered as MISTRAL_FF in dff_sim.v). +// The core logic primitive of the Cyclone IVE/IVGX is the Logic Element +// (LE). Each LE is made up of an 4-input, 1-output look-up table, covered +// in this file, connected to combinational outputs, a carry chain, and one +// D flip-flop (which are covered as MISTRAL_FF in dff_sim.v). // -// The ALM is vertically symmetric, so I find it helps to think in terms of -// half-ALMs, as that's predominantly the unit that synth_intel_alm uses. -// -// ALMs are quite flexible, having multiple modes. +// LEs are have two modes of operation // // Normal (combinational) mode // --------------------------- -// The ALM can implement: -// - a single 6-input function (with the other inputs usable for flip-flop access) -// - two 5-input functions that share two inputs -// - a 5-input and a 4-input function that share one input -// - a 5-input and a 3-or-less-input function that share no inputs -// - two 4-or-less-input functions that share no inputs +// The LE can implement: +// - a single 4-input(or less) function // // Normal-mode functions are represented as MISTRAL_ALUTN cells with N inputs. -// It would be possible to represent a normal mode function as a single cell - -// the vendor cyclone{v,10gx}_lcell_comb cell does exactly that - but I felt -// it was more user-friendly to print out the specific function sizes -// separately. -// -// With the exception of MISTRAL_ALUT6, you can think of two normal-mode cells -// fitting inside a single ALM. -// -// Extended (7-input) mode -// ----------------------- -// The ALM can also fit a 7-input function made of two 5-input functions that -// share four inputs, multiplexed by another input. -// -// Because this can't accept arbitrary 7-input functions, Yosys can't handle -// it, so it doesn't have a cell, but I would likely call it MISTRAL_ALUT7(E?) -// if it did, and it would take up a full ALM. -// -// It might be possible to add an extraction pass to examine all ALUT5 cells -// that feed into ALUT3 cells to see if they can be combined into an extended -// ALM, but I don't think it will be worth it. // // Arithmetic mode // --------------- -// In arithmetic mode, each half-ALM uses its carry chain to perform fast addition -// of two four-input functions that share three inputs. Oddly, the result of -// one of the functions is inverted before being added (you can see this as -// the dot on a full-adder input of Figure 1-8 in the Handbook). +// In arithmetic mode, LE implements two bit adder and carry chain +// It can drive either registered or unregistered output. // -// The cell for an arithmetic-mode half-ALM is MISTRAL_ALM_ARITH. One idea -// I've had (or rather was suggested by mwk) is that functions that feed into -// arithmetic-mode cells could be packed directly into the arithmetic-mode -// cell as a function, which reduces the number of ALMs needed. +// The cell for an arithmetic-mode is MISTRAL_ALM_ARITH. // -// Shared arithmetic mode -// ---------------------- -// Shared arithmetic mode looks a lot like arithmetic mode, but here the -// output of every other four-input function goes to the input of the adder -// the next bit along. What this means is that adding three bits together can -// be done in an ALM, because functions can be used to implement addition that -// then feeds into the carry chain. This means that three bits can be added per -// ALM, as opposed to two in the arithmetic mode. -// -// Shared arithmetic mode doesn't currently have a cell, but I intend to add -// it as MISTRAL_ALM_SHARED, and have it occupy a full ALM. Because it adds -// three bits per cell, it makes addition shorter and use less ALMs, but -// I don't know enough to tell whether it's more efficient to use shared -// arithmetic mode to shorten the carry chain, or plain arithmetic mode with -// the functions packed in. `default_nettype none // Cyclone V LUT output timings (picoseconds): // -// CARRY A B C D E F G -// COMBOUT - 605 583 510 512 - 97 400 (LUT6) -// COMBOUT - 602 583 457 510 302 93 483 (LUT7) -// SUMOUT 368 1342 1323 887 927 - 785 - -// CARRYOUT 71 1082 1062 866 813 - 1198 - +// CARRY A B C D +// COMBOUT ?408? 319 323 211 114 +// CARRYOUT 200 376 385 ? - (* abc9_lut=1, lib_whitebox *) @@ -83,22 +34,14 @@ module MISTRAL_ALUT4(input A, B, C, D, output Q); parameter [15:0] LUT = 16'h0000; -`ifdef cycloneiv +`ifdef cycloneiv specify - (A => Q) = 510; - (B => Q) = 512; - (C => Q) = 400; - (D => Q) = 97; + (A => Q) = 319; + (B => Q) = 323; + (C => Q) = 211; + (D => Q) = 114; endspecify `endif -`ifdef cycloneive - specify - (A => Q) = 510; - (B => Q) = 512; - (C => Q) = 400; - (D => Q) = 97; - endspecify -`endif assign Q = LUT >> {D, C, B, A}; @@ -110,20 +53,13 @@ module MISTRAL_ALUT3(input A, B, C, output Q); parameter [7:0] LUT = 8'h00; -`ifdef cycloneiv +`ifdef cycloneiv specify (A => Q) = 510; (B => Q) = 400; (C => Q) = 97; endspecify `endif -`ifdef cycloneive - specify - (A => Q) = 510; - (B => Q) = 400; - (C => Q) = 97; - endspecify -`endif assign Q = LUT >> {C, B, A}; endmodule @@ -134,18 +70,12 @@ module MISTRAL_ALUT2(input A, B, output Q); parameter [3:0] LUT = 4'h0; -`ifdef cycloneiv +`ifdef cycloneiv specify (A => Q) = 400; (B => Q) = 97; endspecify `endif -`ifdef cycloneive - specify - (A => Q) = 400; - (B => Q) = 97; - endspecify -`endif assign Q = LUT >> {B, A}; endmodule @@ -159,11 +89,6 @@ specify (A => Q) = 97; endspecify `endif -`ifdef cycloneive - specify - (A => Q) = 97; - endspecify -`endif assign Q = ~A; endmodule @@ -188,21 +113,6 @@ specify (CI => CO) = 36; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM) endspecify `endif -`ifdef cycloneive - specify - (A => SO) = 1342; - (B => SO) = 1323; - (C => SO) = 927; - (D => SO) = 887; - (CI => SO) = 368; - - (A => CO) = 1082; - (B => CO) = 1062; - (C => CO) = 813; - (D => CO) = 866; - (CI => CO) = 36; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM) - endspecify -`endif wire q0, q1; diff --git a/techlibs/intel_le/common/quartus_rename.v b/techlibs/intel_le/common/quartus_rename.v index 2fefd2a79..da76a347b 100644 --- a/techlibs/intel_le/common/quartus_rename.v +++ b/techlibs/intel_le/common/quartus_rename.v @@ -2,10 +2,6 @@ `define LCELL cycloneiv_lcell_comb `define M9K cycloneiv_ram_block `endif -`ifdef cycloneive - `define LCELL cycloneive_lcell_comb - `define M9K cycloneive_ram_block -`endif module __MISTRAL_VCC(output Q); diff --git a/techlibs/intel_le/synth_intel_le.cc b/techlibs/intel_le/synth_intel_le.cc index d85495327..044a826bf 100644 --- a/techlibs/intel_le/synth_intel_le.cc +++ b/techlibs/intel_le/synth_intel_le.cc @@ -43,7 +43,6 @@ struct SynthIntelLEPass : public ScriptPass { log(" -family \n"); log(" target one of:\n"); log(" \"cycloneiv\" - Cyclone IV (default)\n"); - log(" \"cycloneive\" - Cyclone IV E \n"); log("\n"); log(" -vqm \n"); log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n"); @@ -145,7 +144,7 @@ struct SynthIntelLEPass : public ScriptPass { if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); - if (family_opt == "cycloneiv" or family_opt == "cycloneive") { + if (family_opt == "cycloneiv") { bram_type = "m9k"; } else { log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str()); @@ -167,7 +166,7 @@ struct SynthIntelLEPass : public ScriptPass { } if (check_label("begin")) { - if (family_opt == "cycloneiv" or family_opt == "cycloneive") + if (family_opt == "cycloneiv") run(stringf("read_verilog -sv -lib +/intel_le/cycloneiv/cells_sim.v")); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/le_sim.v", family_opt.c_str())); run(stringf("read_verilog -specify -lib -D %s +/intel_le/common/dff_sim.v", family_opt.c_str())); diff --git a/tests/arch/intel_le/add_sub.ys b/tests/arch/intel_le/add_sub.ys index da0f2bcb5..f6d3af729 100644 --- a/tests/arch/intel_le/add_sub.ys +++ b/tests/arch/intel_le/add_sub.ys @@ -10,12 +10,3 @@ select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH %% t:* %D design -reset -read_verilog ../common/add_sub.v -hierarchy -top top -equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -stat -select -assert-count 8 t:MISTRAL_ALUT_ARITH -select -assert-count 4 t:MISTRAL_NOT -select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH %% t:* %D diff --git a/tests/arch/intel_le/adffs.ys b/tests/arch/intel_le/adffs.ys index 2fb313696..0086220f9 100644 --- a/tests/arch/intel_le/adffs.ys +++ b/tests/arch/intel_le/adffs.ys @@ -12,18 +12,6 @@ select -assert-count 1 t:MISTRAL_NOT select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D -design -load read -hierarchy -top adff -proc -equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd adff # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_FF -select -assert-count 1 t:MISTRAL_NOT - -select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D - - design -load read hierarchy -top adffn proc @@ -35,17 +23,6 @@ select -assert-count 1 t:MISTRAL_FF select -assert-none t:MISTRAL_FF %% t:* %D -design -load read -hierarchy -top adffn -proc -equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd adffn # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_FF - -select -assert-none t:MISTRAL_FF %% t:* %D - - design -load read hierarchy -top dffs proc @@ -58,18 +35,6 @@ select -assert-count 1 t:MISTRAL_ALUT2 select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 %% t:* %D -design -load read -hierarchy -top dffs -proc -equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd dffs # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_FF -select -assert-count 1 t:MISTRAL_ALUT2 - -select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 %% t:* %D - - design -load read hierarchy -top ndffnr proc @@ -82,13 +47,3 @@ select -assert-count 2 t:MISTRAL_NOT select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D -design -load read -hierarchy -top ndffnr -proc -equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd ndffnr # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_FF -select -assert-count 2 t:MISTRAL_NOT - -select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D diff --git a/tests/arch/intel_le/counter.ys b/tests/arch/intel_le/counter.ys index d0a7b1f2d..13295a747 100644 --- a/tests/arch/intel_le/counter.ys +++ b/tests/arch/intel_le/counter.ys @@ -14,15 +14,3 @@ select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH t:MISTRAL_FF %% t:* %D design -reset -read_verilog ../common/counter.v -hierarchy -top top -proc -flatten -equiv_opt -async2sync -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module - -select -assert-count 2 t:MISTRAL_NOT -select -assert-count 8 t:MISTRAL_ALUT_ARITH -select -assert-count 8 t:MISTRAL_FF -select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH t:MISTRAL_FF %% t:* %D diff --git a/tests/arch/intel_le/dffs.ys b/tests/arch/intel_le/dffs.ys index 89db9e16f..03d40efc2 100644 --- a/tests/arch/intel_le/dffs.ys +++ b/tests/arch/intel_le/dffs.ys @@ -10,16 +10,6 @@ select -assert-count 1 t:MISTRAL_FF select -assert-none t:MISTRAL_FF %% t:* %D -design -load read -hierarchy -top dff -proc -equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd dff # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_FF - -select -assert-none t:MISTRAL_FF %% t:* %D - design -load read hierarchy -top dffe @@ -32,12 +22,3 @@ select -assert-count 1 t:MISTRAL_FF select -assert-none t:MISTRAL_FF %% t:* %D -design -load read -hierarchy -top dffe -proc -equiv_opt -async2sync -assert -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd dffe # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_FF - -select -assert-none t:MISTRAL_FF %% t:* %D diff --git a/tests/arch/intel_le/fsm.ys b/tests/arch/intel_le/fsm.ys index f2b3d631a..f26165ff8 100644 --- a/tests/arch/intel_le/fsm.ys +++ b/tests/arch/intel_le/fsm.ys @@ -19,22 +19,3 @@ select -assert-max 9 t:MISTRAL_ALUT4 # select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D design -reset -read_verilog ../common/fsm.v -hierarchy -top fsm -proc -flatten - -equiv_opt -run :prove -map +/intel_le/common/le_sim.v -map +/intel_le/common/dff_sim.v synth_intel_le -family cycloneive -async2sync -miter -equiv -make_assert -flatten gold gate miter -sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter - -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd fsm # Constrain all select calls below inside the top module - -select -assert-count 6 t:MISTRAL_FF -select -assert-max 1 t:MISTRAL_NOT -select -assert-max 5 t:MISTRAL_ALUT2 # -select -assert-max 1 t:MISTRAL_ALUT3 -select -assert-max 9 t:MISTRAL_ALUT4 # -select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D diff --git a/tests/arch/intel_le/logic.ys b/tests/arch/intel_le/logic.ys index 1184558b7..0e7beff53 100644 --- a/tests/arch/intel_le/logic.ys +++ b/tests/arch/intel_le/logic.ys @@ -12,14 +12,3 @@ select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D design -reset -read_verilog ../common/logic.v -hierarchy -top top -proc -equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module - -select -assert-count 1 t:MISTRAL_NOT -select -assert-count 6 t:MISTRAL_ALUT2 -select -assert-count 2 t:MISTRAL_ALUT4 -select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D \ No newline at end of file diff --git a/tests/arch/intel_le/mux.ys b/tests/arch/intel_le/mux.ys index f5afafeb3..5dd5c8e84 100644 --- a/tests/arch/intel_le/mux.ys +++ b/tests/arch/intel_le/mux.ys @@ -11,16 +11,6 @@ select -assert-count 1 t:MISTRAL_ALUT3 select -assert-none t:MISTRAL_ALUT3 %% t:* %D -design -load read -hierarchy -top mux2 -proc -equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd mux2 # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_ALUT3 -select -assert-none t:MISTRAL_ALUT3 %% t:* %D - - design -load read hierarchy -top mux4 proc @@ -31,16 +21,6 @@ select -assert-count 3 t:MISTRAL_ALUT3 select -assert-none t:MISTRAL_ALUT3 %% t:* %D -design -load read -hierarchy -top mux4 -proc -equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd mux4 # Constrain all select calls below inside the top module -select -assert-count 3 t:MISTRAL_ALUT3 -select -assert-none t:MISTRAL_ALUT3 %% t:* %D - - design -load read hierarchy -top mux8 proc @@ -52,17 +32,6 @@ select -assert-count 3 t:MISTRAL_ALUT4 select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D -design -load read -hierarchy -top mux8 -proc -equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd mux8 # Constrain all select calls below inside the top module -select -assert-count 3 t:MISTRAL_ALUT3 -select -assert-count 3 t:MISTRAL_ALUT4 -select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D - - design -load read hierarchy -top mux16 proc @@ -74,14 +43,3 @@ select -assert-max 6 t:MISTRAL_ALUT3 select -assert-max 7 t:MISTRAL_ALUT4 select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D - -design -load read -hierarchy -top mux16 -proc -equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneive # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd mux16 # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_ALUT2 -select -assert-max 6 t:MISTRAL_ALUT3 -select -assert-max 7 t:MISTRAL_ALUT4 -select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D diff --git a/tests/arch/intel_le/quartus_ice.ys b/tests/arch/intel_le/quartus_ice.ys index 1855fbcb6..ef843f1c3 100644 --- a/tests/arch/intel_le/quartus_ice.ys +++ b/tests/arch/intel_le/quartus_ice.ys @@ -12,15 +12,3 @@ synth_intel_le -family cycloneiv -quartus select -assert-none w:*[* w:*]* design -reset -read_verilog < Date: Sun, 6 Dec 2020 12:24:44 +0100 Subject: [PATCH 12/15] minor changes --- techlibs/intel_le/common/arith_le_map.v | 23 +---------------------- techlibs/intel_le/common/le_sim.v | 12 +++++------- techlibs/intel_le/common/mem_sim.v | 4 ++-- tests/arch/intel_le/mux.ys | 19 ++++++++++--------- 4 files changed, 18 insertions(+), 40 deletions(-) diff --git a/techlibs/intel_le/common/arith_le_map.v b/techlibs/intel_le/common/arith_le_map.v index 07170c4c0..2a3c7cebe 100644 --- a/techlibs/intel_le/common/arith_le_map.v +++ b/techlibs/intel_le/common/arith_le_map.v @@ -39,17 +39,7 @@ generate if (_TECHMAP_CONSTMSK_CI_ == 1) begin assign LE_CARRY[0] = _TECHMAP_CONSTVAL_CI_; end else begin - /* - MISTRAL_ALUT_ARITH #( - .LUT(16'b1010_1010_1010_1010), // Q = A - ) le_start ( - .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1), - .CI(1'b0), - .SO(), - .CO(LE_CARRY[0]) - ); - */ assign LE_CARRY[0] = CI; end endgenerate @@ -57,21 +47,10 @@ endgenerate // Carry chain genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice - /* - MISTRAL_ALUT_ARITH #( - .LUT(16'b0110_0110_0110_0110), // Q = A ? ~B : B - .sum_lutc_input("cin") - ) le_not_i ( - .A(BI), .B(BX[i]), .C(1'b0), .D(1'b0), - .CI(1'b0), - .SO(BTOADDER[i]), - .CO() - ); - */ MISTRAL_ALUT_ARITH #( .LUT(16'b1001_0110_1110_1000), // SUM = A xor B xor CI - // CARRYi+1 = A and B or A and CI or B and CI + // CARRYi+1 = A and B or A and CI or B and CI ) le_i ( .A(AA[i]), .B(BB[i]), .C(1'b1), .D(1'b1), diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v index 4ac39e617..eeaafaa32 100644 --- a/techlibs/intel_le/common/le_sim.v +++ b/techlibs/intel_le/common/le_sim.v @@ -34,7 +34,7 @@ module MISTRAL_ALUT4(input A, B, C, D, output Q); parameter [15:0] LUT = 16'h0000; -`ifdef cycloneiv +`ifdef cycloneiv specify (A => Q) = 319; (B => Q) = 323; @@ -98,7 +98,7 @@ module MISTRAL_ALUT_ARITH(input A, B, C, D, (* abc9_carry *) input CI, output SO parameter LUT = 16'h0000; -`ifdef cycloneiv +`ifdef cycloneiv specify (A => SO) = 1342; (B => SO) = 1323; @@ -106,11 +106,9 @@ specify (D => SO) = 887; (CI => SO) = 368; - (A => CO) = 1082; - (B => CO) = 1062; - (C => CO) = 813; - (D => CO) = 866; - (CI => CO) = 36; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM) + (A => CO) = 376; + (B => CO) = 385; + (CI => CO) = 200; endspecify `endif wire q0, q1; diff --git a/techlibs/intel_le/common/mem_sim.v b/techlibs/intel_le/common/mem_sim.v index 66bc4f82c..b2734b161 100644 --- a/techlibs/intel_le/common/mem_sim.v +++ b/techlibs/intel_le/common/mem_sim.v @@ -5,8 +5,8 @@ module MISTRAL_M9K(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); -parameter CFG_ABITS = 10; -parameter CFG_DBITS = 10; +parameter CFG_ABITS = 9; +parameter CFG_DBITS = 9; input CLK1; input [CFG_ABITS-1:0] A1ADDR, B1ADDR; diff --git a/tests/arch/intel_le/mux.ys b/tests/arch/intel_le/mux.ys index 5dd5c8e84..7c4a4bb33 100644 --- a/tests/arch/intel_le/mux.ys +++ b/tests/arch/intel_le/mux.ys @@ -17,8 +17,10 @@ proc equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux4 # Constrain all select calls below inside the top module -select -assert-count 3 t:MISTRAL_ALUT3 -select -assert-none t:MISTRAL_ALUT3 %% t:* %D +select -assert-count 1 t:MISTRAL_ALUT3 +select -assert-count 2 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D + design -load read @@ -27,9 +29,9 @@ proc equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux8 # Constrain all select calls below inside the top module -select -assert-count 3 t:MISTRAL_ALUT3 -select -assert-count 3 t:MISTRAL_ALUT4 -select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D +select -assert-count 2 t:MISTRAL_ALUT2 +select -assert-count 5 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D design -load read @@ -38,8 +40,7 @@ proc equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_ALUT2 -select -assert-max 6 t:MISTRAL_ALUT3 -select -assert-max 7 t:MISTRAL_ALUT4 -select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D +select -assert-max 4 t:MISTRAL_ALUT3 +select -assert-max 9 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D From 8e893dbf23500dc6105330e77bb9571af8924655 Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Sun, 6 Dec 2020 12:32:30 +0100 Subject: [PATCH 13/15] minor fix --- techlibs/intel_le/common/bram_m9k.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/intel_le/common/bram_m9k.txt b/techlibs/intel_le/common/bram_m9k.txt index 97a69b11c..2a19ccf3b 100644 --- a/techlibs/intel_le/common/bram_m9k.txt +++ b/techlibs/intel_le/common/bram_m9k.txt @@ -26,7 +26,7 @@ bram MISTRAL_M9K endbram -match MISTRAL_M10K +match MISTRAL_M9K min efficiency 5 make_transp endmatch From dd9c11c035c5e1c13d430ba8bf6bf30cae95e937 Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Sun, 6 Dec 2020 14:07:41 +0100 Subject: [PATCH 14/15] fix input -> output timings --- techlibs/intel_le/common/le_sim.v | 43 ++++++++++++++++--------------- tests/arch/intel_le/mux.ys | 11 ++++---- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/techlibs/intel_le/common/le_sim.v b/techlibs/intel_le/common/le_sim.v index eeaafaa32..50a25cb4b 100644 --- a/techlibs/intel_le/common/le_sim.v +++ b/techlibs/intel_le/common/le_sim.v @@ -25,7 +25,7 @@ // Cyclone V LUT output timings (picoseconds): // // CARRY A B C D -// COMBOUT ?408? 319 323 211 114 +// COMBOUT ?408? 332 337 220 119 // CARRYOUT 200 376 385 ? - @@ -36,10 +36,10 @@ parameter [15:0] LUT = 16'h0000; `ifdef cycloneiv specify - (A => Q) = 319; - (B => Q) = 323; - (C => Q) = 211; - (D => Q) = 114; + (A => Q) = 337; + (B => Q) = 332; + (C => Q) = 220; + (D => Q) = 119; endspecify `endif @@ -55,9 +55,9 @@ parameter [7:0] LUT = 8'h00; `ifdef cycloneiv specify - (A => Q) = 510; - (B => Q) = 400; - (C => Q) = 97; + (A => Q) = 332; + (B => Q) = 220; + (C => Q) = 119; endspecify `endif assign Q = LUT >> {C, B, A}; @@ -72,8 +72,8 @@ parameter [3:0] LUT = 4'h0; `ifdef cycloneiv specify - (A => Q) = 400; - (B => Q) = 97; + (A => Q) = 220; + (B => Q) = 119; endspecify `endif assign Q = LUT >> {B, A}; @@ -84,9 +84,9 @@ endmodule (* abc9_lut=1, lib_whitebox *) module MISTRAL_NOT(input A, output Q); -`ifdef cycloneiv +`ifdef cycloneiv specify - (A => Q) = 97; + (A => Q) = 119; endspecify `endif assign Q = ~A; @@ -98,16 +98,17 @@ module MISTRAL_ALUT_ARITH(input A, B, C, D, (* abc9_carry *) input CI, output SO parameter LUT = 16'h0000; -`ifdef cycloneiv -specify - (A => SO) = 1342; - (B => SO) = 1323; - (C => SO) = 927; - (D => SO) = 887; - (CI => SO) = 368; - (A => CO) = 376; - (B => CO) = 385; +`ifdef cycloneiv +specify + (A => SO) = 337; + (B => SO) = 332; + (C => SO) = 220; + (D => SO) = 119; + (CI => SO) = 08; + + (A => CO) = 385; + (B => CO) = 376; (CI => CO) = 200; endspecify `endif diff --git a/tests/arch/intel_le/mux.ys b/tests/arch/intel_le/mux.ys index 7c4a4bb33..169cef00c 100644 --- a/tests/arch/intel_le/mux.ys +++ b/tests/arch/intel_le/mux.ys @@ -17,9 +17,8 @@ proc equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux4 # Constrain all select calls below inside the top module -select -assert-count 1 t:MISTRAL_ALUT3 -select -assert-count 2 t:MISTRAL_ALUT4 -select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D +select -assert-count 3 t:MISTRAL_ALUT3 +select -assert-none t:MISTRAL_ALUT3 %% t:* %D @@ -29,7 +28,7 @@ proc equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux8 # Constrain all select calls below inside the top module -select -assert-count 2 t:MISTRAL_ALUT2 +select -assert-count 3 t:MISTRAL_ALUT2 select -assert-count 5 t:MISTRAL_ALUT4 select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D @@ -40,7 +39,7 @@ proc equiv_opt -assert -map +/intel_le/common/le_sim.v synth_intel_le -family cycloneiv # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module -select -assert-max 4 t:MISTRAL_ALUT3 -select -assert-max 9 t:MISTRAL_ALUT4 +select -assert-max 3 t:MISTRAL_ALUT3 +select -assert-max 10 t:MISTRAL_ALUT4 select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 %% t:* %D From 349fc479cb275de1f02de9e42ce8bd1114c18752 Mon Sep 17 00:00:00 2001 From: Artur Swiderski Date: Wed, 9 Dec 2020 14:35:01 +0100 Subject: [PATCH 15/15] changes related to some pull request remarks --- techlibs/intel_alm/common/alm_sim.v | 2 +- techlibs/intel_le/common/quartus_rename.v | 2 +- techlibs/intel_le/cycloneiv/cells_sim.v | 19 +------------------ 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/techlibs/intel_alm/common/alm_sim.v b/techlibs/intel_alm/common/alm_sim.v index 9689876c3..906a95b0b 100644 --- a/techlibs/intel_alm/common/alm_sim.v +++ b/techlibs/intel_alm/common/alm_sim.v @@ -169,7 +169,7 @@ module MISTRAL_ALUT3(input A, B, C, output Q); parameter [7:0] LUT = 8'h00; -`ifdef cyclonev +`ifdef cyclonev specify (A => Q) = 510; (B => Q) = 400; diff --git a/techlibs/intel_le/common/quartus_rename.v b/techlibs/intel_le/common/quartus_rename.v index da76a347b..7ad5c6283 100644 --- a/techlibs/intel_le/common/quartus_rename.v +++ b/techlibs/intel_le/common/quartus_rename.v @@ -58,7 +58,7 @@ assign Q = ~A; endmodule -module MISTRAL_ALUT_ARITH(input A, B, C, D, CI, output SO, CO); +module MISTRAL_LE_LUT_ARITH(input A, B, C, D, CI, output SO, CO); parameter LUT = 16'h0000; `LCELL #(.lut_mask({LUT}),.sum_lutc_input("cin")) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .cin(CI), .combout(SO), .cout(CO)); diff --git a/techlibs/intel_le/cycloneiv/cells_sim.v b/techlibs/intel_le/cycloneiv/cells_sim.v index 48b2651b0..7be70eef5 100644 --- a/techlibs/intel_le/cycloneiv/cells_sim.v +++ b/techlibs/intel_le/cycloneiv/cells_sim.v @@ -1,21 +1,4 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ + module VCC (output V); assign V = 1'b1; endmodule // VCC