mirror of https://github.com/YosysHQ/yosys.git
synth_intel_alm: alternative synthesis for Intel FPGAs
By operating at a layer of abstraction over the rather clumsy Intel primitives, we can avoid special hacks like `dffinit -highlow` in favour of simple techmapping. This also makes the primitives much easier to manipulate, and more descriptive (no more cyclonev_lcell_comb to mean anything from a LUT2 to a LUT6).
This commit is contained in:
parent
4c52691a58
commit
2e37e62e6b
1
Makefile
1
Makefile
|
@ -737,6 +737,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)
|
||||||
+cd tests/arch/efinix && bash run-test.sh $(SEEDOPT)
|
+cd tests/arch/efinix && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT)
|
+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT)
|
+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT)
|
||||||
|
+cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/rpc && bash run-test.sh
|
+cd tests/rpc && bash run-test.sh
|
||||||
+cd tests/memfile && bash run-test.sh
|
+cd tests/memfile && bash run-test.sh
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
|
@ -11,4 +11,3 @@ families := max10 arria10gx cyclonev cyclone10lp cycloneiv cycloneive
|
||||||
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v)))
|
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v)))
|
||||||
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.v)))
|
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.v)))
|
||||||
#$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v))
|
#$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
OBJS += techlibs/intel_alm/synth_intel_alm.o
|
||||||
|
|
||||||
|
# Techmap
|
||||||
|
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_map.v))
|
||||||
|
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_sim.v))
|
||||||
|
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/arith_alm_map.v))
|
||||||
|
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_map.v))
|
||||||
|
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_sim.v))
|
||||||
|
|
||||||
|
# RAM
|
||||||
|
bramtypes := m10k m20k
|
||||||
|
$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype).txt)))
|
||||||
|
$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype)_map.v)))
|
||||||
|
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab.txt))
|
||||||
|
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab_map.v))
|
||||||
|
|
||||||
|
families := cyclonev cyclone10gx
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/megafunction_bb.v))
|
||||||
|
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/quartus_rename.v))
|
||||||
|
$(foreach family, $(families), $(eval $(call add_share_file,share/intel_alm/$(family),techlibs/intel_alm/$(family)/quartus_rename.v)))
|
|
@ -0,0 +1,56 @@
|
||||||
|
module \$lut (A, Y);
|
||||||
|
|
||||||
|
parameter WIDTH = 1;
|
||||||
|
parameter LUT = 0;
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,482 @@
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
(* 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) = 602;
|
||||||
|
(B => Q) = 584;
|
||||||
|
(C => Q) = 510;
|
||||||
|
(D => Q) = 510;
|
||||||
|
(E => Q) = 339;
|
||||||
|
(F => Q) = 94;
|
||||||
|
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) = 584;
|
||||||
|
(B => Q) = 510;
|
||||||
|
(C => Q) = 510;
|
||||||
|
(D => Q) = 339;
|
||||||
|
(E => Q) = 94;
|
||||||
|
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) = 510;
|
||||||
|
(C => Q) = 339;
|
||||||
|
(D => Q) = 94;
|
||||||
|
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) = 339;
|
||||||
|
(C => Q) = 94;
|
||||||
|
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) = 339;
|
||||||
|
(B => Q) = 94;
|
||||||
|
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) = 94;
|
||||||
|
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) = 1283;
|
||||||
|
(B => SO) = 1167;
|
||||||
|
(C => SO) = 866;
|
||||||
|
(D0 => SO) = 756;
|
||||||
|
(D1 => SO) = 756;
|
||||||
|
(CI => SO) = 355;
|
||||||
|
(A => CO) = 950;
|
||||||
|
(B => CO) = 1039;
|
||||||
|
(C => CO) = 820;
|
||||||
|
(D0 => CO) = 1006;
|
||||||
|
(D1 => CO) = 1006;
|
||||||
|
(CI => CO) = 23;
|
||||||
|
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
|
||||||
|
*/
|
|
@ -0,0 +1,64 @@
|
||||||
|
`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;
|
||||||
|
|
||||||
|
input [A_WIDTH-1:0] A;
|
||||||
|
input [B_WIDTH-1:0] B;
|
||||||
|
input CI, BI;
|
||||||
|
output [Y_WIDTH-1:0] X, Y, CO;
|
||||||
|
|
||||||
|
wire [Y_WIDTH-1:0] A_buf, B_buf;
|
||||||
|
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
|
||||||
|
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
|
||||||
|
|
||||||
|
wire [Y_WIDTH-1:0] AA = A_buf;
|
||||||
|
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
||||||
|
wire [Y_WIDTH-1:0] 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
|
|
@ -0,0 +1,33 @@
|
||||||
|
bram __MISTRAL_M10K_SDP
|
||||||
|
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_SDP
|
||||||
|
min efficiency 5
|
||||||
|
make_transp
|
||||||
|
endmatch
|
|
@ -0,0 +1,31 @@
|
||||||
|
module __MISTRAL_M10K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
||||||
|
|
||||||
|
parameter CFG_ABITS = 10;
|
||||||
|
parameter CFG_DBITS = 10;
|
||||||
|
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("m10k"),
|
||||||
|
.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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,124 @@
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
// D flip-flops
|
||||||
|
module \$_DFF_P_ (input D, C, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
|
||||||
|
end else $error("Unsupported flop: $_DFF_P_ with INIT=1");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_N_ (input D, C, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
|
||||||
|
end else $error("Unsupported flop: $_DFF_N_ with INIT=1");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// D flip-flops with reset
|
||||||
|
module \$_DFF_PP0_ (input D, C, R, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
|
||||||
|
end else $error("Unsupported flop: $_DFF_PP0_ with INIT=1");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_PN0_ (input D, C, R, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
|
||||||
|
end else $error("Unsupported flop: $_DFF_PN0_ with INIT=1");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NP0_ (input D, C, R, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
|
||||||
|
end else $error("Unsupported flop: $_DFF_NP0_ with INIT=1");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NN0_ (input D, C, R, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
|
||||||
|
end else $error("Unsupported flop: $_DFF_NN0_ with INIT=1");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// D flip-flops with set
|
||||||
|
module \$_DFF_PP1_ (input D, C, R, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
wire Q_tmp;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
|
||||||
|
assign Q = ~Q_tmp;
|
||||||
|
end else $error("Unsupported flop: $_DFF_PP1_ with INIT=0");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_PN1_ (input D, C, R, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
wire Q_tmp;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
|
||||||
|
end else $error("Unsupported flop: $_DFF_PN1_ with INIT=0");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NP1_ (input D, C, R, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
wire Q_tmp;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
|
||||||
|
assign Q = ~Q_tmp;
|
||||||
|
end else $error("Unsupported flop: $_DFF_NP1_ with INIT=0");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NN1_ (input D, C, R, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
wire Q_tmp;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
|
||||||
|
assign Q = ~Q_tmp;
|
||||||
|
end else $error("Unsupported flop: $_DFF_NN1_ with INIT=0");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// D flip-flops with clock enable
|
||||||
|
module \$_DFFE_PP_ (input D, C, E, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
|
||||||
|
end else $error("Unsupported flop: $_DFFE_PP_ with INIT=1");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFFE_PN_ (input D, C, E, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
|
||||||
|
end else $error("Unsupported flop: $_DFFE_PN_ with INIT=1");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFFE_NP_ (input D, C, E, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
|
||||||
|
end else $error("Unsupported flop: $_DFFE_NP_ with INIT=1");
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFFE_NN_ (input D, C, E, output Q);
|
||||||
|
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
|
||||||
|
if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
|
||||||
|
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
|
||||||
|
MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
|
||||||
|
end else $error("Unsupported flop: $_DFFE_NN_ with INIT=1");
|
||||||
|
endmodule
|
|
@ -0,0 +1,48 @@
|
||||||
|
// 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.
|
||||||
|
module MISTRAL_FF(
|
||||||
|
input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA,
|
||||||
|
output reg Q
|
||||||
|
);
|
||||||
|
|
||||||
|
`ifdef cyclonev
|
||||||
|
specify
|
||||||
|
(posedge CLK => (Q : DATAIN)) = 262;
|
||||||
|
$setup(DATAIN, posedge CLK, 522);
|
||||||
|
endspecify
|
||||||
|
`endif
|
||||||
|
`ifdef cyclone10gx
|
||||||
|
specify
|
||||||
|
(posedge CLK => (Q : DATAIN)) = 219;
|
||||||
|
$setup(DATAIN, posedge CLK, 268);
|
||||||
|
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
|
|
@ -0,0 +1,20 @@
|
||||||
|
bram __MISTRAL_MLAB
|
||||||
|
init 0 # TODO: Re-enable when I figure out how LUTRAM init works
|
||||||
|
abits 5
|
||||||
|
dbits 16 @D32x16
|
||||||
|
dbits 18 @D32x18
|
||||||
|
dbits 20 @D32x20
|
||||||
|
groups 2
|
||||||
|
ports 1 1
|
||||||
|
wrmode 1 0
|
||||||
|
# read enable
|
||||||
|
enable 1 0
|
||||||
|
transp 1 0
|
||||||
|
clocks 1 2
|
||||||
|
clkpol 1 1
|
||||||
|
endbram
|
||||||
|
|
||||||
|
match __MISTRAL_MLAB
|
||||||
|
min efficiency 5
|
||||||
|
make_outreg
|
||||||
|
endmatch
|
|
@ -0,0 +1,29 @@
|
||||||
|
module __MISTRAL_MLAB(CLK1, CLK2, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA);
|
||||||
|
|
||||||
|
parameter CFG_ABITS = 5;
|
||||||
|
parameter CFG_DBITS = 20;
|
||||||
|
|
||||||
|
input CLK1, CLK2;
|
||||||
|
input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
|
||||||
|
input [CFG_DBITS-1:0] A1DATA;
|
||||||
|
input A1EN;
|
||||||
|
output [CFG_DBITS-1:0] B1DATA;
|
||||||
|
|
||||||
|
altsyncram #(
|
||||||
|
.operation_mode("dual_port"),
|
||||||
|
.ram_block_type("mlab"),
|
||||||
|
.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
|
|
@ -0,0 +1,108 @@
|
||||||
|
// Intel megafunction declarations, to avoid Yosys complaining.
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
(* 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 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
|
|
@ -0,0 +1,23 @@
|
||||||
|
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 D, CLK, ACn, ALD, AD, EN, output reg Q);
|
||||||
|
|
||||||
|
parameter INIT = 1'b0;
|
||||||
|
|
||||||
|
localparam [1023:0] INIT_STR = (INIT !== 1'b1) ? "low" : "high";
|
||||||
|
|
||||||
|
dffeas #(.power_up(INIT_STR), .is_wysiwyg("true")) _TECHMAP_REPLACE_ (.d(D), .clk(CLK), .clrn(ACn), .aload(ALD), .asdata(AD), .ena(EN), .q(Q));
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,54 @@
|
||||||
|
module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q);
|
||||||
|
parameter LUT = 64'h0000_0000_0000_0000;
|
||||||
|
|
||||||
|
cyclone10gx_lcell_comb #(.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 LUT = 32'h0000_0000;
|
||||||
|
|
||||||
|
cyclone10gx_lcell_comb #(.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 LUT = 16'h0000;
|
||||||
|
|
||||||
|
cyclone10gx_lcell_comb #(.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 LUT = 8'h00;
|
||||||
|
|
||||||
|
cyclone10gx_lcell_comb #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q));
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
module MISTRAL_ALUT2(input A, B, output Q);
|
||||||
|
parameter LUT = 4'h0;
|
||||||
|
|
||||||
|
cyclone10gx_lcell_comb #(.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;
|
||||||
|
|
||||||
|
cyclone10gx_lcell_comb #(.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
|
|
@ -0,0 +1,54 @@
|
||||||
|
module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q);
|
||||||
|
parameter LUT = 64'h0000_0000_0000_0000;
|
||||||
|
|
||||||
|
cyclonev_lcell_comb #(.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 LUT = 32'h0000_0000;
|
||||||
|
|
||||||
|
cyclonev_lcell_comb #(.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 LUT = 16'h0000;
|
||||||
|
|
||||||
|
cyclonev_lcell_comb #(.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 LUT = 8'h00;
|
||||||
|
|
||||||
|
cyclonev_lcell_comb #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q));
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
module MISTRAL_ALUT2(input A, B, output Q);
|
||||||
|
parameter LUT = 4'h0;
|
||||||
|
|
||||||
|
cyclonev_lcell_comb #(.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;
|
||||||
|
|
||||||
|
cyclonev_lcell_comb #(.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
|
|
@ -0,0 +1,240 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Claire Wolf <claire@symbioticeda.com>
|
||||||
|
* Copyright (C) 2019 Dan Ravensloft <dan.ravensloft@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kernel/celltypes.h"
|
||||||
|
#include "kernel/log.h"
|
||||||
|
#include "kernel/register.h"
|
||||||
|
#include "kernel/rtlil.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct SynthIntelALMPass : public ScriptPass {
|
||||||
|
SynthIntelALMPass() : ScriptPass("synth_intel_alm", "synthesis for ALM-based Intel (Altera) FPGAs.") {}
|
||||||
|
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" synth_intel_alm [options]\n");
|
||||||
|
log("\n");
|
||||||
|
log("This command runs synthesis for ALM-based Intel FPGAs.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -top <module>\n");
|
||||||
|
log(" use the specified module as top module (default='top')\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -family <family>\n");
|
||||||
|
log(" target one of:\n");
|
||||||
|
log(" \"cyclonev\" - Cyclone V (default)\n");
|
||||||
|
log(" \"cyclone10gx\" - Cyclone 10GX\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -quartus\n");
|
||||||
|
log(" output a netlist using Quartus cells instead of MISTRAL_* cells\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -vqm <file>\n");
|
||||||
|
log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
|
||||||
|
log(" output file is omitted if this parameter is not specified. Implies -quartus.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -run <from_label>:<to_label>\n");
|
||||||
|
log(" only run the commands between the labels (see below). an empty\n");
|
||||||
|
log(" from label is synonymous to 'begin', and empty to label is\n");
|
||||||
|
log(" synonymous to the end of the command list.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -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(" -noflatten\n");
|
||||||
|
log(" do not flatten design before synthesis\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;
|
||||||
|
|
||||||
|
void clear_flags() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
top_opt = "-auto-top";
|
||||||
|
family_opt = "cyclonev";
|
||||||
|
bram_type = "m10k";
|
||||||
|
vout_file = "";
|
||||||
|
flatten = true;
|
||||||
|
quartus = false;
|
||||||
|
nolutram = false;
|
||||||
|
nobram = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
string run_from, run_to;
|
||||||
|
clear_flags();
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||||
|
if (args[argidx] == "-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] == "-noflatten") {
|
||||||
|
flatten = false;
|
||||||
|
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 == "cyclonev") {
|
||||||
|
bram_type = "m10k";
|
||||||
|
} else if (family_opt == "cyclone10gx") {
|
||||||
|
bram_type = "m20k";
|
||||||
|
} else {
|
||||||
|
log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
log_header(design, "Executing SYNTH_INTEL_ALM pass.\n");
|
||||||
|
log_push();
|
||||||
|
|
||||||
|
run_script(design, run_from, run_to);
|
||||||
|
|
||||||
|
log_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void script() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
if (help_mode) {
|
||||||
|
family_opt = "<family>";
|
||||||
|
bram_type = "<bram_type>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("begin")) {
|
||||||
|
run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str()));
|
||||||
|
run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str()));
|
||||||
|
run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str()));
|
||||||
|
|
||||||
|
// Misc and common cells
|
||||||
|
run("read_verilog -lib +/intel/common/altpll_bb.v");
|
||||||
|
run("read_verilog -lib +/intel_alm/common/megafunction_bb.v");
|
||||||
|
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flatten && check_label("flatten", "(unless -noflatten)")) {
|
||||||
|
run("proc");
|
||||||
|
run("flatten");
|
||||||
|
run("tribuf -logic");
|
||||||
|
run("deminout");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("coarse")) {
|
||||||
|
run("synth -run coarse -lut 6");
|
||||||
|
run("techmap -map +/intel_alm/common/arith_alm_map.v");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
|
||||||
|
run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type.c_str()));
|
||||||
|
run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) {
|
||||||
|
run("memory_bram -rules +/intel_alm/common/lutram_mlab.txt", "(for Cyclone V / Cyclone 10GX)");
|
||||||
|
run("techmap -map +/intel_alm/common/lutram_mlab_map.v", "(for Cyclone V / Cyclone 10GX)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_ffram")) {
|
||||||
|
run("memory_map");
|
||||||
|
run("opt -full");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_ffs")) {
|
||||||
|
run("dff2dffe -direct-match $_DFF_*");
|
||||||
|
run("zinit");
|
||||||
|
run("techmap -map +/techmap.v -map +/intel_alm/common/dff_map.v");
|
||||||
|
run("opt -full -undriven -mux_undef");
|
||||||
|
run("clean -purge");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_luts")) {
|
||||||
|
run("read_verilog -icells -specify -lib +/abc9_model.v");
|
||||||
|
run("abc9 -maxlut 6 -W 200");
|
||||||
|
run("techmap -map +/intel_alm/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) {
|
||||||
|
run("hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q");
|
||||||
|
run("techmap -map +/intel_alm/common/quartus_rename.v");
|
||||||
|
run(stringf("techmap -map +/intel_alm/%s/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 ? "<file-name>" : vout_file.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} SynthIntelALMPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -0,0 +1,8 @@
|
||||||
|
read_verilog ../common/add_sub.v
|
||||||
|
hierarchy -top top
|
||||||
|
equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -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
|
|
@ -0,0 +1,48 @@
|
||||||
|
read_verilog ../common/adffs.v
|
||||||
|
design -save read
|
||||||
|
|
||||||
|
hierarchy -top adff
|
||||||
|
proc
|
||||||
|
equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -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 adffn
|
||||||
|
proc
|
||||||
|
equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -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 dffs
|
||||||
|
proc
|
||||||
|
equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -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 ndffnr
|
||||||
|
proc
|
||||||
|
equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -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 1 t:MISTRAL_NOT
|
||||||
|
select -assert-count 1 t:MISTRAL_ALUT2
|
||||||
|
|
||||||
|
select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 %% t:* %D
|
|
@ -0,0 +1,13 @@
|
||||||
|
read_verilog ../common/counter.v
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
flatten
|
||||||
|
equiv_opt -async2sync -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -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
|
|
@ -0,0 +1,22 @@
|
||||||
|
read_verilog ../common/dffs.v
|
||||||
|
design -save read
|
||||||
|
|
||||||
|
hierarchy -top dff
|
||||||
|
proc
|
||||||
|
equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -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 dffe
|
||||||
|
proc
|
||||||
|
equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -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-count 1 t:MISTRAL_ALUT3
|
||||||
|
|
||||||
|
select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT3 %% t:* %D
|
|
@ -0,0 +1,18 @@
|
||||||
|
read_verilog ../common/fsm.v
|
||||||
|
hierarchy -top fsm
|
||||||
|
proc
|
||||||
|
flatten
|
||||||
|
|
||||||
|
equiv_opt -run :prove -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -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 2 t:MISTRAL_ALUT2 # Clang returns 2, GCC returns 1
|
||||||
|
select -assert-count 5 t:MISTRAL_ALUT5
|
||||||
|
select -assert-count 1 t:MISTRAL_ALUT6
|
||||||
|
select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D
|
|
@ -0,0 +1,11 @@
|
||||||
|
read_verilog ../common/logic.v
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -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
|
|
@ -0,0 +1,45 @@
|
||||||
|
read_verilog ../common/mux.v
|
||||||
|
design -save read
|
||||||
|
|
||||||
|
hierarchy -top mux2
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -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 mux4
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -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 mux8
|
||||||
|
proc
|
||||||
|
equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -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 1 t:MISTRAL_ALUT5
|
||||||
|
select -assert-count 2 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_alm/common/alm_sim.v synth_intel_alm -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-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
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
{
|
||||||
|
echo "all::"
|
||||||
|
for x in *.ys; do
|
||||||
|
echo "all:: run-$x"
|
||||||
|
echo "run-$x:"
|
||||||
|
echo " @echo 'Running $x..'"
|
||||||
|
echo " @../../../yosys -ql ${x%.ys}.log -w 'Yosys has only limited support for tri-state logic at the moment.' $x"
|
||||||
|
done
|
||||||
|
for s in *.sh; do
|
||||||
|
if [ "$s" != "run-test.sh" ]; then
|
||||||
|
echo "all:: run-$s"
|
||||||
|
echo "run-$s:"
|
||||||
|
echo " @echo 'Running $s..'"
|
||||||
|
echo " @bash $s"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
} > run-test.mk
|
||||||
|
exec ${MAKE:-make} -f run-test.mk
|
|
@ -0,0 +1,10 @@
|
||||||
|
read_verilog ../common/shifter.v
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
flatten
|
||||||
|
equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -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 8 t:MISTRAL_FF
|
||||||
|
|
||||||
|
select -assert-none t:MISTRAL_FF %% t:* %D
|
|
@ -0,0 +1,13 @@
|
||||||
|
read_verilog ../common/tribuf.v
|
||||||
|
hierarchy -top tristate
|
||||||
|
proc
|
||||||
|
tribuf
|
||||||
|
flatten
|
||||||
|
synth
|
||||||
|
equiv_opt -assert -map +/simcells.v synth_intel_alm -family cyclonev # 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.
|
||||||
|
select -assert-count 1 t:$_TBUF_
|
||||||
|
|
||||||
|
select -assert-none t:$_TBUF_ %% t:* %D
|
Loading…
Reference in New Issue