3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-24 01:25:33 +00:00

Merge remote-tracking branch 'origin/master' into xaig_dff

This commit is contained in:
Eddie Hung 2019-12-30 14:31:42 -08:00
commit 405e974fe5
42 changed files with 1727 additions and 207 deletions

View file

@ -1,5 +1,6 @@
// ---------------------------------------
(* lib_whitebox *)
module LUT4(input A, B, C, D, output Z);
parameter [15:0] INIT = 16'h0000;
wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0];
@ -31,13 +32,8 @@ module CCU2C(
// First half
wire LUT4_0, LUT2_0;
`ifdef _ABC
assign LUT4_0 = INIT0[{D0, C0, B0, A0}];
assign LUT2_0 = INIT0[{2'b00, B0, A0}];
`else
LUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0));
LUT2 #(.INIT(INIT0[3:0])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0));
`endif
wire gated_cin_0 = (INJECT1_0 == "YES") ? 1'b0 : CIN;
assign S0 = LUT4_0 ^ gated_cin_0;
@ -46,13 +42,8 @@ module CCU2C(
// Second half
wire LUT4_1, LUT2_1;
`ifdef _ABC
assign LUT4_1 = INIT1[{D1, C1, B1, A1}];
assign LUT2_1 = INIT1[{2'b00, B1, A1}];
`else
LUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1));
LUT2 #(.INIT(INIT1[3:0])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1));
`endif
wire gated_cin_1 = (INJECT1_1 == "YES") ? 1'b0 : cout_0;
assign S1 = LUT4_1 ^ gated_cin_1;
@ -209,6 +200,7 @@ endmodule
// ---------------------------------------
(* lib_whitebox *)
module LUT2(input A, B, output Z);
parameter [3:0] INIT = 4'h0;
wire [1:0] s1 = B ? INIT[ 3:2] : INIT[1:0];

View file

@ -230,7 +230,7 @@ struct SynthEcp5Pass : public ScriptPass
{
if (check_label("begin"))
{
run("read_verilog -D_ABC -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v");
run("read_verilog -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
}

View file

@ -2107,7 +2107,7 @@ always @* begin
2'b00: XMUX <= 0;
2'b01: XMUX <= M;
2'b10: XMUX <= P;
2'b11: XMUX <= {D_OUT[11:0], B1_OUT, A1_OUT};
2'b11: XMUX <= {D_OUT[11:0], A1_OUT, B1_OUT};
default: XMUX <= 48'hxxxxxxxxxxxx;
endcase
end
@ -2125,8 +2125,8 @@ end
// The post-adder.
wire signed [48:0] X_EXT;
wire signed [48:0] Z_EXT;
assign X_EXT = XMUX;
assign Z_EXT = ZMUX;
assign X_EXT = {1'b0, XMUX};
assign Z_EXT = {1'b0, ZMUX};
assign {CARRYOUT_IN, P_IN} = OPMODE_OUT[7] ? (Z_EXT - (X_EXT + CARRYIN_OUT)) : (Z_EXT + X_EXT + CARRYIN_OUT);
// Cascade outputs.

View file

@ -64,7 +64,7 @@ struct SynthXilinxPass : public ScriptPass
log(" (this feature is experimental and incomplete)\n");
log("\n");
log(" -ise\n");
log(" generate an output netlist suitable for ISE (enables -iopad)\n");
log(" generate an output netlist suitable for ISE\n");
log("\n");
log(" -nobram\n");
log(" do not use block RAM cells in output netlist\n");
@ -84,11 +84,9 @@ struct SynthXilinxPass : public ScriptPass
log(" -nodsp\n");
log(" do not use DSP48E1s to implement multipliers and associated logic\n");
log("\n");
log(" -iopad\n");
log(" enable I/O buffer insertion (selected automatically by -ise)\n");
log("\n");
log(" -noiopad\n");
log(" disable I/O buffer insertion (only useful with -ise)\n");
log(" disable I/O buffer insertion (useful for hierarchical or \n");
log(" out-of-context flows)\n");
log("\n");
log(" -noclkbuf\n");
log(" disable automatic clock buffer insertion\n");
@ -125,7 +123,7 @@ struct SynthXilinxPass : public ScriptPass
}
std::string top_opt, edif_file, blif_file, family;
bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram;
bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram;
bool abc9, dff_mode;
bool flatten_before_abc;
int widemux;
@ -140,7 +138,6 @@ struct SynthXilinxPass : public ScriptPass
retime = false;
vpr = false;
ise = false;
iopad = false;
noiopad = false;
noclkbuf = false;
nocarry = false;
@ -218,7 +215,6 @@ struct SynthXilinxPass : public ScriptPass
continue;
}
if (args[argidx] == "-iopad") {
iopad = true;
continue;
}
if (args[argidx] == "-noiopad") {
@ -291,7 +287,6 @@ struct SynthXilinxPass : public ScriptPass
void script() YS_OVERRIDE
{
bool do_iopad = iopad || (ise && !noiopad);
std::string ff_map_file;
if (help_mode)
ff_map_file = "+/xilinx/{family}_ff_map.v";
@ -397,7 +392,10 @@ struct SynthXilinxPass : public ScriptPass
run("opt_expr -fine");
run("wreduce");
run("select -clear");
run("xilinx_dsp");
if (help_mode)
run("xilinx_dsp -family <family>");
else
run("xilinx_dsp -family " + family);
run("chtype -set $mul t:$__soft_mul");
}
}
@ -524,8 +522,8 @@ struct SynthXilinxPass : public ScriptPass
if (check_label("map_cells")) {
// Needs to be done before logic optimization, so that inverters (OE vs T) are handled.
if (help_mode || do_iopad)
run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top", "(only if '-iopad' or '-ise' and not '-noiopad')");
if (help_mode || !noiopad)
run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top", "(only if not '-noiopad')");
std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v";
if (widemux > 0)
techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux);

View file

@ -8,4 +8,8 @@ dsp_work*/
test_dsp_model_ref.v
test_dsp_model_uut.v
test_dsp_model
test_dsp48a_model_ref.v
test_dsp48a1_model_ref.v
test_dsp48a1_model_uut.v
test_dsp48a1_model
*.vcd

View file

@ -0,0 +1,17 @@
#!/bin/bash
set -ex
if [ -z $ISE_DIR ]; then
ISE_DIR=/opt/Xilinx/ISE/14.7
fi
sed 's/DSP48A1/MARKER1/; s/DSP48A/DSP48A_UUT/; s/MARKER1/DSP48A1_UUT/; /module DSP48A_UUT/,/endmodule/ p; /module DSP48A1_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp48a1_model_uut.v
if [ ! -f "test_dsp48a1_model_ref.v" ]; then
cp $ISE_DIR/ISE_DS/ISE/verilog/src/unisims/DSP48A1.v test_dsp48a1_model_ref.v
fi
if [ ! -f "test_dsp48a_model_ref.v" ]; then
cp $ISE_DIR/ISE_DS/ISE/verilog/src/unisims/DSP48A.v test_dsp48a_model_ref.v
fi
for tb in mult_allreg mult_noreg mult_inreg
do
iverilog -s $tb -s glbl -o test_dsp48a1_model test_dsp48a1_model.v test_dsp48a1_model_uut.v test_dsp48a1_model_ref.v test_dsp48a_model_ref.v $ISE_DIR/ISE_DS/ISE/verilog/src/glbl.v
vvp -N ./test_dsp48a1_model
done

View file

@ -0,0 +1,331 @@
`timescale 1ns / 1ps
module testbench;
parameter integer A0REG = 1;
parameter integer A1REG = 1;
parameter integer B0REG = 1;
parameter integer B1REG = 1;
parameter integer CREG = 1;
parameter integer DREG = 1;
parameter integer MREG = 1;
parameter integer PREG = 1;
parameter integer CARRYINREG = 1;
parameter integer CARRYOUTREG = 1;
parameter integer OPMODEREG = 1;
parameter CARRYINSEL = "OPMODE5";
parameter RSTTYPE = "SYNC";
reg CLK;
reg CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE;
reg RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE;
reg [17:0] A;
reg [17:0] B;
reg [47:0] C;
reg [17:0] D;
reg [47:0] PCIN;
reg [7:0] OPMODE;
reg CARRYIN;
output CARRYOUTF, REF_CARRYOUTF;
output CARRYOUT, REF_CARRYOUT, REF_OLD_CARRYOUT;
output [35:0] M, REF_M;
output [47:0] P, REF_P, REF_OLD_P;
output [17:0] BCOUT, REF_BCOUT, REF_OLD_BCOUT;
output [47:0] PCOUT, REF_PCOUT, REF_OLD_PCOUT;
integer errcount = 0;
reg ERROR_FLAG = 0;
task clkcycle;
begin
#5;
CLK = ~CLK;
#10;
CLK = ~CLK;
#2;
ERROR_FLAG = 0;
if (REF_BCOUT !== BCOUT || REF_OLD_BCOUT != BCOUT) begin
$display("ERROR at %1t: REF_BCOUT=%b REF_OLD_BCOUT=%b UUT_BCOUT=%b DIFF=%b", $time, REF_BCOUT, REF_OLD_BCOUT, BCOUT, REF_BCOUT ^ BCOUT);
errcount = errcount + 1;
ERROR_FLAG = 1;
end
if (REF_M !== M) begin
$display("ERROR at %1t: REF_M=%b UUT_M=%b DIFF=%b", $time, REF_M, M, REF_M ^ M);
errcount = errcount + 1;
ERROR_FLAG = 1;
end
if (REF_P !== P || REF_OLD_P != P) begin
$display("ERROR at %1t: REF_P=%b REF_OLD_P=%b UUT_P=%b DIFF=%b", $time, REF_P, REF_OLD_P, P, REF_P ^ P);
errcount = errcount + 1;
ERROR_FLAG = 1;
end
if (REF_PCOUT !== PCOUT || REF_OLD_PCOUT != PCOUT) begin
$display("ERROR at %1t: REF_PCOUT=%b REF_OLD_PCOUT=%b UUT_PCOUT=%b DIFF=%b", $time, REF_PCOUT, REF_OLD_PCOUT, PCOUT, REF_PCOUT ^ PCOUT);
errcount = errcount + 1;
ERROR_FLAG = 1;
end
if (REF_CARRYOUT !== CARRYOUT || (REF_OLD_CARRYOUT != CARRYOUT && !CARRYOUTREG)) begin
$display("ERROR at %1t: REF_CARRYOUT=%b REF_OLD_CARRYOUT=%b UUT_CARRYOUT=%b DIFF=%b", $time, REF_CARRYOUT, REF_OLD_CARRYOUT, CARRYOUT, REF_CARRYOUT ^ CARRYOUT);
errcount = errcount + 1;
ERROR_FLAG = 1;
end
if (REF_CARRYOUTF !== CARRYOUTF) begin
$display("ERROR at %1t: REF_CARRYOUTF=%b UUT_CARRYOUTF=%b", $time, REF_CARRYOUTF, CARRYOUTF);
errcount = errcount + 1;
ERROR_FLAG = 1;
end
#3;
end
endtask
reg config_valid = 0;
task drc;
begin
config_valid = 1;
if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0;
if (OPMODE[3:2] == 2'b10 && PREG != 1) config_valid = 0;
end
endtask
initial begin
$dumpfile("test_dsp48a1_model.vcd");
$dumpvars(0, testbench);
#2;
CLK = 1'b0;
{CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE} = 8'b11111111;
{A, B, C, D, PCIN, OPMODE, CARRYIN} = 0;
{RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = 8'b11111111;
repeat (10) begin
#10;
CLK = 1'b1;
#10;
CLK = 1'b0;
#10;
CLK = 1'b1;
#10;
CLK = 1'b0;
end
{RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = 0;
repeat (10000) begin
clkcycle;
config_valid = 0;
while (!config_valid) begin
A = $urandom;
B = $urandom;
C = {$urandom, $urandom};
D = $urandom;
PCIN = {$urandom, $urandom};
{CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE} = $urandom | $urandom | $urandom;
{RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom;
{CARRYIN, OPMODE} = $urandom;
drc;
end
end
if (errcount == 0) begin
$display("All tests passed.");
$finish;
end else begin
$display("Caught %1d errors.", errcount);
$stop;
end
end
DSP48A #(
.A0REG (A0REG),
.A1REG (A1REG),
.B0REG (B0REG),
.B1REG (B1REG),
.CREG (CREG),
.DREG (DREG),
.MREG (MREG),
.PREG (PREG),
.CARRYINREG (CARRYINREG),
.OPMODEREG (OPMODEREG),
.CARRYINSEL (CARRYINSEL),
.RSTTYPE (RSTTYPE)
) ref_old (
.A (A),
.B (B),
.C (C),
.D (D),
.PCIN (PCIN),
.CARRYIN (CARRYIN),
.OPMODE (OPMODE),
.BCOUT (REF_OLD_BCOUT),
.CARRYOUT (REF_OLD_CARRYOUT),
.P (REF_OLD_P),
.PCOUT (REF_OLD_PCOUT),
.CEA (CEA),
.CEB (CEB),
.CEC (CEC),
.CED (CED),
.CEM (CEM),
.CEP (CEP),
.CECARRYIN (CECARRYIN),
.CEOPMODE (CEOPMODE),
.CLK (CLK),
.RSTA (RSTA),
.RSTB (RSTB),
.RSTC (RSTC),
.RSTD (RSTD),
.RSTM (RSTM),
.RSTP (RSTP),
.RSTCARRYIN (RSTCARRYIN),
.RSTOPMODE (RSTOPMODE)
);
DSP48A1 #(
.A0REG (A0REG),
.A1REG (A1REG),
.B0REG (B0REG),
.B1REG (B1REG),
.CREG (CREG),
.DREG (DREG),
.MREG (MREG),
.PREG (PREG),
.CARRYINREG (CARRYINREG),
.CARRYOUTREG (CARRYOUTREG),
.OPMODEREG (OPMODEREG),
.CARRYINSEL (CARRYINSEL),
.RSTTYPE (RSTTYPE)
) ref (
.A (A),
.B (B),
.C (C),
.D (D),
.PCIN (PCIN),
.CARRYIN (CARRYIN),
.OPMODE (OPMODE),
.BCOUT (REF_BCOUT),
.CARRYOUTF (REF_CARRYOUTF),
.CARRYOUT (REF_CARRYOUT),
.P (REF_P),
.M (REF_M),
.PCOUT (REF_PCOUT),
.CEA (CEA),
.CEB (CEB),
.CEC (CEC),
.CED (CED),
.CEM (CEM),
.CEP (CEP),
.CECARRYIN (CECARRYIN),
.CEOPMODE (CEOPMODE),
.CLK (CLK),
.RSTA (RSTA),
.RSTB (RSTB),
.RSTC (RSTC),
.RSTD (RSTD),
.RSTM (RSTM),
.RSTP (RSTP),
.RSTCARRYIN (RSTCARRYIN),
.RSTOPMODE (RSTOPMODE)
);
DSP48A1_UUT #(
.A0REG (A0REG),
.A1REG (A1REG),
.B0REG (B0REG),
.B1REG (B1REG),
.CREG (CREG),
.DREG (DREG),
.MREG (MREG),
.PREG (PREG),
.CARRYINREG (CARRYINREG),
.CARRYOUTREG (CARRYOUTREG),
.OPMODEREG (OPMODEREG),
.CARRYINSEL (CARRYINSEL),
.RSTTYPE (RSTTYPE)
) uut (
.A (A),
.B (B),
.C (C),
.D (D),
.PCIN (PCIN),
.CARRYIN (CARRYIN),
.OPMODE (OPMODE),
.BCOUT (BCOUT),
.CARRYOUTF (CARRYOUTF),
.CARRYOUT (CARRYOUT),
.P (P),
.M (M),
.PCOUT (PCOUT),
.CEA (CEA),
.CEB (CEB),
.CEC (CEC),
.CED (CED),
.CEM (CEM),
.CEP (CEP),
.CECARRYIN (CECARRYIN),
.CEOPMODE (CEOPMODE),
.CLK (CLK),
.RSTA (RSTA),
.RSTB (RSTB),
.RSTC (RSTC),
.RSTD (RSTD),
.RSTM (RSTM),
.RSTP (RSTP),
.RSTCARRYIN (RSTCARRYIN),
.RSTOPMODE (RSTOPMODE)
);
endmodule
module mult_noreg;
testbench #(
.A0REG (0),
.A1REG (0),
.B0REG (0),
.B1REG (0),
.CREG (0),
.DREG (0),
.MREG (0),
.PREG (0),
.CARRYINREG (0),
.CARRYOUTREG (0),
.OPMODEREG (0),
.CARRYINSEL ("CARRYIN"),
.RSTTYPE ("SYNC")
) testbench ();
endmodule
module mult_allreg;
testbench #(
.A0REG (1),
.A1REG (1),
.B0REG (1),
.B1REG (1),
.CREG (1),
.DREG (1),
.MREG (1),
.PREG (1),
.CARRYINREG (1),
.CARRYOUTREG (1),
.OPMODEREG (1),
.CARRYINSEL ("OPMODE5"),
.RSTTYPE ("SYNC")
) testbench ();
endmodule
module mult_inreg;
testbench #(
.A0REG (1),
.A1REG (1),
.B0REG (1),
.B1REG (1),
.CREG (1),
.DREG (1),
.MREG (0),
.PREG (0),
.CARRYINREG (1),
.CARRYOUTREG (0),
.OPMODEREG (0),
.CARRYINSEL ("CARRYIN"),
.RSTTYPE ("SYNC")
) testbench ();
endmodule

View file

@ -1,14 +1,17 @@
#!/bin/bash
set -ex
if [ -z $VIVADO_DIR ]; then
VIVADO_DIR=/opt/Xilinx/Vivado/2019.1
fi
sed 's/DSP48E1/DSP48E1_UUT/; /DSP48E1_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp_model_uut.v
if [ ! -f "test_dsp_model_ref.v" ]; then
cat /opt/Xilinx/Vivado/2019.1/data/verilog/src/unisims/DSP48E1.v > test_dsp_model_ref.v
cp $VIVADO_DIR/data/verilog/src/unisims/DSP48E1.v test_dsp_model_ref.v
fi
for tb in macc_overflow_underflow \
simd24_preadd_noreg_nocasc simd12_preadd_noreg_nocasc \
mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc \
simd24_preadd_noreg_nocasc simd12_preadd_noreg_nocasc \
mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc \
mult_allreg_preadd_nocasc mult_noreg_preadd_nocasc mult_inreg_preadd_nocasc
do
iverilog -s $tb -s glbl -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v /opt/Xilinx/Vivado/2019.1/data/verilog/src/glbl.v
iverilog -s $tb -s glbl -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v $VIVADO_DIR/data/verilog/src/glbl.v
vvp -N ./test_dsp_model
done

View file

@ -27,7 +27,7 @@ module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
.D(18'b0),
.P(P_48),
.OPMODE(8'b0000010)
.OPMODE(8'b0000001)
);
assign Y = P_48;
endmodule

View file

@ -27,7 +27,7 @@ module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
.D(18'b0),
.P(P_48),
.OPMODE(8'b0000010)
.OPMODE(8'b0000001)
);
assign Y = P_48;
endmodule