From 269ff450f55f4354c82db1b98f8eb722317d9250 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 8 Jul 2019 15:40:12 +0100 Subject: [PATCH 001/356] Add mul2dsp multiplier splitting rule and ECP5 mapping Signed-off-by: David Shah --- techlibs/common/Makefile.inc | 1 + techlibs/common/mul2dsp.v | 237 +++++++++++++++++++++++++++++++++++ techlibs/ecp5/Makefile.inc | 1 + techlibs/ecp5/dsp_map.v | 10 ++ techlibs/ecp5/synth_ecp5.cc | 33 ++++- 5 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 techlibs/common/mul2dsp.v create mode 100644 techlibs/ecp5/dsp_map.v diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 0e05620bc..e6d1c2f29 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -28,3 +28,4 @@ $(eval $(call add_share_file,share,techlibs/common/dff2ff.v)) $(eval $(call add_share_file,share,techlibs/common/gate2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cells.lib)) +$(eval $(call add_share_file,share,techlibs/common/mul2dsp.v)) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v new file mode 100644 index 000000000..37ce2e485 --- /dev/null +++ b/techlibs/common/mul2dsp.v @@ -0,0 +1,237 @@ +// From Eddie Hung +// extracted from: https://github.com/eddiehung/vtr-with-yosys/blob/vtr7-with-yosys/vtr_flow/misc/yosys_models.v#L220 +// revised by Andre DeHon +// further revised by David Shah +`ifndef DSP_A_MAXWIDTH +`define DSP_A_MAXWIDTH 18 +`endif +`ifndef DSP_A_MAXWIDTH +`define DSP_B_MAXWIDTH 25 +`endif + +`ifndef ADDER_MINWIDTH +`define ADDER_MINWIDTH AAA +`endif + +`ifndef DSP_NAME +`define DSP_NAME M18x25 +`endif + +`define MAX(a,b) (a > b ? a : b) +`define MIN(a,b) (a < b ? a : b) + +(* techmap_celltype = "$mul" *) +module \$mul (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire [1023:0] _TECHMAP_DO_ = "proc; clean"; + + generate + if (A_WIDTH `DSP_A_MAXWIDTH) begin + localparam n_floored = A_WIDTH/`DSP_A_MAXWIDTH; + localparam n = n_floored + (n_floored*`DSP_A_MAXWIDTH < A_WIDTH ? 1 : 0); + wire [`DSP_A_MAXWIDTH+B_WIDTH-1:0] partial [n-1:1]; + wire [Y_WIDTH-1:0] partial_sum [n-2:0]; + + \$__mul_gen #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(`DSP_A_MAXWIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(B_WIDTH+`DSP_A_MAXWIDTH) + ) mul_slice_first ( + .A(A[`DSP_A_MAXWIDTH-1:0]), + .B(B), + .Y(partial_sum[0][B_WIDTH+`DSP_A_MAXWIDTH-1:0]) + ); + assign partial_sum[0][Y_WIDTH-1:B_WIDTH+`DSP_A_MAXWIDTH]=0; + + genvar i; + generate + for (i = 1; i < n-1; i=i+1) begin:slice + \$__mul_gen #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(`DSP_A_MAXWIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(B_WIDTH+`DSP_A_MAXWIDTH) + ) mul_slice ( + .A(A[(i+1)*`DSP_A_MAXWIDTH-1:i*`DSP_A_MAXWIDTH]), + .B(B), + .Y(partial[i][B_WIDTH+`DSP_A_MAXWIDTH-1:0]) + ); + //assign partial_sum[i] = (partial[i] << i*`DSP_A_MAXWIDTH) + partial_sum[i-1]; + assign partial_sum[i] = { + partial[i][B_WIDTH+`DSP_A_MAXWIDTH-1:0] + + partial_sum[i-1][Y_WIDTH-1:(i*`DSP_A_MAXWIDTH)], + partial_sum[i-1][(i*`DSP_A_MAXWIDTH)-1:0] + }; + end + endgenerate + + \$__mul_gen #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH-(n-1)*`DSP_A_MAXWIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH), + ) mul_slice_last ( + .A(A[A_WIDTH-1:(n-1)*`DSP_A_MAXWIDTH]), + .B(B), + .Y(partial[n-1][A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH-1:0]) + ); + //assign Y = (partial[n-1] << (n-1)*`DSP_A_MAXWIDTH) + partial_sum[n-2]; + assign Y = { + partial[n-1][A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH:0] + + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_A_MAXWIDTH)], + partial_sum[n-2][((n-1)*`DSP_A_MAXWIDTH)-1:0] + }; + end + else if (B_WIDTH > `DSP_B_MAXWIDTH) begin + localparam n_floored = B_WIDTH/`DSP_B_MAXWIDTH; + localparam n = n_floored + (n_floored*`DSP_B_MAXWIDTH < B_WIDTH ? 1 : 0); + wire [A_WIDTH+`DSP_B_MAXWIDTH-1:0] partial [n-1:1]; + wire [Y_WIDTH-1:0] partial_sum [n-2:0]; + + \$__mul_gen #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(`DSP_B_MAXWIDTH), + .Y_WIDTH(A_WIDTH+`DSP_B_MAXWIDTH) + ) mul_first ( + .A(A), + .B(B[`DSP_B_MAXWIDTH-1:0]), + .Y(partial_sum[0][A_WIDTH+`DSP_B_MAXWIDTH-1:0]) + ); + assign partial_sum[0][Y_WIDTH-1:A_WIDTH+`DSP_B_MAXWIDTH]=0; + + genvar i; + generate + for (i = 1; i < n-1; i=i+1) begin:slice + \$__mul_gen #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(`DSP_B_MAXWIDTH), + .Y_WIDTH(A_WIDTH+`DSP_B_MAXWIDTH) + ) mul ( + .A(A), + .B(B[(i+1)*`DSP_B_MAXWIDTH-1:i*`DSP_B_MAXWIDTH]), + .Y(partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:0]) + ); + //assign partial_sum[i] = (partial[i] << i*`DSP_B_MAXWIDTH) + partial_sum[i-1]; + // was: + //assign partial_sum[i] = { + // partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH], + // partial[i][`DSP_B_MAXWIDTH-1:0] + partial_sum[i-1][A_WIDTH+(i*`DSP_B_MAXWIDTH)-1:A_WIDTH+((i-1)*`DSP_B_MAXWIDTH)], + // partial_sum[i-1][A_WIDTH+((i-1)*`DSP_B_MAXWIDTH):0] + assign partial_sum[i] = { + partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:0] + + partial_sum[i-1][Y_WIDTH-1:(i*`DSP_B_MAXWIDTH)], + partial_sum[i-1][(i*`DSP_B_MAXWIDTH)-1:0] + }; + end + endgenerate + + \$__mul_gen #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH-(n-1)*`DSP_B_MAXWIDTH), + .Y_WIDTH(A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH) + ) mul_last ( + .A(A), + .B(B[B_WIDTH-1:(n-1)*`DSP_B_MAXWIDTH]), + .Y(partial[n-1][A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH-1:0]) + ); + // AMD: this came comment out -- looks closer to right answer + //assign Y = (partial[n-1] << (n-1)*`DSP_B_MAXWIDTH) + partial_sum[n-2]; + // was (looks broken) + //assign Y = { + // partial[n-1][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH], + // partial[n-1][`DSP_B_MAXWIDTH-1:0] + partial_sum[n-2][A_WIDTH+((n-1)*`DSP_B_MAXWIDTH)-1:A_WIDTH+((n-2)*`DSP_B_MAXWIDTH)], + // partial_sum[n-2][A_WIDTH+((n-2)*`DSP_B_MAXWIDTH):0] + assign Y = { + partial[n-1][A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH-1:0] + + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_B_MAXWIDTH)], + partial_sum[n-2][((n-1)*`DSP_B_MAXWIDTH)-1:0] + }; + end + else begin + wire [A_WIDTH+B_WIDTH-1:0] out; + wire [(`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH)-(A_WIDTH+B_WIDTH)-1:0] dummy; + wire Asign, Bsign; + assign Asign = (A_SIGNED ? A[A_WIDTH-1] : 1'b0); + assign Bsign = (B_SIGNED ? B[B_WIDTH-1] : 1'b0); + `DSP_NAME _TECHMAP_REPLACE_ ( + .A({ {{`DSP_A_MAXWIDTH-A_WIDTH}{Asign}}, A }), + .B({ {{`DSP_B_MAXWIDTH-B_WIDTH}{Bsign}}, B }), + .OUT({dummy, out}) + ); + if (Y_WIDTH < A_WIDTH+B_WIDTH) + assign Y = out[Y_WIDTH-1:0]; + else begin + wire Ysign = (A_SIGNED || B_SIGNED ? out[A_WIDTH+BWIDTH-1] : 1'b0); + assign Y = { {{Y_WIDTH-(A_WIDTH+B_WIDTH)}{Ysign}}, out[A_WIDTH+B_WIDTH-1:0] }; + end + end + endgenerate +endmodule + + diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index ff39ba4fe..a2f5cadee 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -10,6 +10,7 @@ $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dsp_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.box)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.lut)) diff --git a/techlibs/ecp5/dsp_map.v b/techlibs/ecp5/dsp_map.v new file mode 100644 index 000000000..22e30574c --- /dev/null +++ b/techlibs/ecp5/dsp_map.v @@ -0,0 +1,10 @@ +module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] OUT); + MULT18X18D mult_i( + .A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .A4(A[4]), .A5(A[5]), .A6(A[6]), .A7(A[7]), .A8(A[8]), .A9(A[9]), .A10(A[10]), .A11(A[11]), .A12(A[12]), .A13(A[13]), .A14(A[14]), .A15(A[15]), .A16(A[16]), .A17(A[17]), + .B0(B[0]), .B1(B[1]), .B2(B[2]), .B3(B[3]), .B4(B[4]), .B5(B[5]), .B6(B[6]), .B7(B[7]), .B8(B[8]), .B9(B[9]), .B10(B[10]), .B11(B[11]), .B12(B[12]), .B13(B[13]), .B14(B[14]), .B15(B[15]), .B16(B[16]), .B17(B[17]), + .C17(1'b0), .C16(1'b0), .C15(1'b0), .C14(1'b0), .C13(1'b0), .C12(1'b0), .C11(1'b0), .C10(1'b0), .C9(1'b0), .C8(1'b0), .C7(1'b0), .C6(1'b0), .C5(1'b0), .C4(1'b0), .C3(1'b0), .C2(1'b0), .C1(1'b0), .C0(1'b0), + .SIGNEDA(1'b0), .SIGNEDB(1'b0), .SOURCEA(1'b0), .SOURCEB(1'b0), + + .P0(OUT[0]), .P1(OUT[1]), .P2(OUT[2]), .P3(OUT[3]), .P4(OUT[4]), .P5(OUT[5]), .P6(OUT[6]), .P7(OUT[7]), .P8(OUT[8]), .P9(OUT[9]), .P10(OUT[10]), .P11(OUT[11]), .P12(OUT[12]), .P13(OUT[13]), .P14(OUT[14]), .P15(OUT[15]), .P16(OUT[16]), .P17(OUT[17]), .P18(OUT[18]), .P19(OUT[19]), .P20(OUT[20]), .P21(OUT[21]), .P22(OUT[22]), .P23(OUT[23]), .P24(OUT[24]), .P25(OUT[25]), .P26(OUT[26]), .P27(OUT[27]), .P28(OUT[28]), .P29(OUT[29]), .P30(OUT[30]), .P31(OUT[31]), .P32(OUT[32]), .P33(OUT[33]), .P34(OUT[34]), .P35(OUT[35]) + ); +endmodule \ No newline at end of file diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index f16a47f01..3b4185930 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -89,6 +89,9 @@ struct SynthEcp5Pass : public ScriptPass log(" generate an output netlist (and BLIF file) suitable for VPR\n"); log(" (this feature is experimental and incomplete)\n"); log("\n"); + log(" -dsp\n"); + log(" map multipliers to MULT18X18D (EXPERIMENTAL)\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -96,7 +99,7 @@ struct SynthEcp5Pass : public ScriptPass } string top_opt, blif_file, edif_file, json_file; - bool noccu2, nodffe, nobram, nodram, nowidelut, flatten, retime, abc2, abc9, vpr; + bool noccu2, nodffe, nobram, nodram, nowidelut, flatten, retime, abc2, abc9, dsp, vpr; void clear_flags() YS_OVERRIDE { @@ -114,6 +117,7 @@ struct SynthEcp5Pass : public ScriptPass abc2 = false; vpr = false; abc9 = false; + dsp = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -192,6 +196,10 @@ struct SynthEcp5Pass : public ScriptPass abc9 = true; continue; } + if (args[argidx] == "-dsp") { + dsp = true; + continue; + } break; } extra_args(args, argidx, design); @@ -225,7 +233,28 @@ struct SynthEcp5Pass : public ScriptPass if (check_label("coarse")) { - run("synth -run coarse"); + run("opt_expr"); + run("opt_clean"); + run("check"); + 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"); + if (dsp) { + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_NAME=$__MUL18X18"); + run("clean"); + run("techmap -map +/ecp5/dsp_map.v"); + } + run("alumacc"); + run("opt"); + run("fsm"); + run("opt -fast"); + run("memory -nomap"); + run("opt_clean"); } if (!nobram && check_label("bram", "(skip if -nobram)")) From e78864993adab41492670c089f6365088426726f Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 8 Jul 2019 15:43:48 +0100 Subject: [PATCH 002/356] mul2dsp: Fix typo Signed-off-by: David Shah --- techlibs/common/mul2dsp.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 37ce2e485..ece45db79 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -227,7 +227,7 @@ module \$__mul_gen (A, B, Y); if (Y_WIDTH < A_WIDTH+B_WIDTH) assign Y = out[Y_WIDTH-1:0]; else begin - wire Ysign = (A_SIGNED || B_SIGNED ? out[A_WIDTH+BWIDTH-1] : 1'b0); + wire Ysign = (A_SIGNED || B_SIGNED ? out[A_WIDTH+B_WIDTH-1] : 1'b0); assign Y = { {{Y_WIDTH-(A_WIDTH+B_WIDTH)}{Ysign}}, out[A_WIDTH+B_WIDTH-1:0] }; end end From c865559f9540c29cb9c6302edc8b4a2620c0b49d Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 8 Jul 2019 19:15:25 +0100 Subject: [PATCH 003/356] xc7: Map combinational DSP48E1s Signed-off-by: David Shah --- techlibs/ecp5/dsp_map.v | 4 ++-- techlibs/xilinx/Makefile.inc | 1 + techlibs/xilinx/dsp_map.v | 40 +++++++++++++++++++++++++++++++++ techlibs/xilinx/synth_xilinx.cc | 39 +++++++++++++++++++++++++++----- 4 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 techlibs/xilinx/dsp_map.v diff --git a/techlibs/ecp5/dsp_map.v b/techlibs/ecp5/dsp_map.v index 22e30574c..5f7755afb 100644 --- a/techlibs/ecp5/dsp_map.v +++ b/techlibs/ecp5/dsp_map.v @@ -1,5 +1,5 @@ module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] OUT); - MULT18X18D mult_i( + MULT18X18D _TECHMAP_REPLACE_ ( .A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .A4(A[4]), .A5(A[5]), .A6(A[6]), .A7(A[7]), .A8(A[8]), .A9(A[9]), .A10(A[10]), .A11(A[11]), .A12(A[12]), .A13(A[13]), .A14(A[14]), .A15(A[15]), .A16(A[16]), .A17(A[17]), .B0(B[0]), .B1(B[1]), .B2(B[2]), .B3(B[3]), .B4(B[4]), .B5(B[5]), .B6(B[6]), .B7(B[7]), .B8(B[8]), .B9(B[9]), .B10(B[10]), .B11(B[11]), .B12(B[12]), .B13(B[13]), .B14(B[14]), .B15(B[15]), .B16(B[16]), .B17(B[17]), .C17(1'b0), .C16(1'b0), .C15(1'b0), .C14(1'b0), .C13(1'b0), .C12(1'b0), .C11(1'b0), .C10(1'b0), .C9(1'b0), .C8(1'b0), .C7(1'b0), .C6(1'b0), .C5(1'b0), .C4(1'b0), .C3(1'b0), .C2(1'b0), .C1(1'b0), .C0(1'b0), @@ -7,4 +7,4 @@ module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] OUT); .P0(OUT[0]), .P1(OUT[1]), .P2(OUT[2]), .P3(OUT[3]), .P4(OUT[4]), .P5(OUT[5]), .P6(OUT[6]), .P7(OUT[7]), .P8(OUT[8]), .P9(OUT[9]), .P10(OUT[10]), .P11(OUT[11]), .P12(OUT[12]), .P13(OUT[13]), .P14(OUT[14]), .P15(OUT[15]), .P16(OUT[16]), .P17(OUT[17]), .P18(OUT[18]), .P19(OUT[19]), .P20(OUT[20]), .P21(OUT[21]), .P22(OUT[22]), .P23(OUT[23]), .P24(OUT[24]), .P25(OUT[25]), .P26(OUT[26]), .P27(OUT[27]), .P28(OUT[28]), .P29(OUT[29]), .P30(OUT[30]), .P31(OUT[31]), .P32(OUT[32]), .P33(OUT[33]), .P34(OUT[34]), .P35(OUT[35]) ); -endmodule \ No newline at end of file +endmodule diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 17c5df37d..c41015e94 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -31,6 +31,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/dsp_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.box)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut)) diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v new file mode 100644 index 000000000..4faa204aa --- /dev/null +++ b/techlibs/xilinx/dsp_map.v @@ -0,0 +1,40 @@ +module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] OUT); + wire [47:0] P_48; + DSP48E1 #( + // Disable all registers + .ACASCREG(0), + .ADREG(0), + .A_INPUT("DIRECT"), + .ALUMODEREG(0), + .AREG(0), + .BCASCREG(0), + .B_INPUT("DIRECT"), + .BREG(0), + .CARRYINREG(0), + .CARRYINSELREG(0), + .CREG(0), + .DREG(0), + .INMODEREG(0), + .MREG(0), + .OPMODEREG(0), + .PREG(0) + ) _TECHMAP_REPLACE_ ( + //Data path + .A({5'b0, A}), + .B(B), + .C(48'b0), + .D(24'b0), + .P(P_48), + + .INMODE(4'b0000), + .ALUMODE(4'b0000), + .OPMODE(7'b000101), + .CARRYINSEL(3'b000), + + .ACIN(30'b0), + .BCIN(18'b0), + .PCIN(48'b0), + .CARRYIN(1'b0) + ); + assign OUT = P_48; +endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 0a30848aa..db0cbb644 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -77,6 +77,9 @@ struct SynthXilinxPass : public ScriptPass log(" -nowidelut\n"); log(" do not use MUXF[78] resources to implement LUTs larger than LUT6s\n"); log("\n"); + log(" -nodsp\n"); + log(" do not use DSP48E1s to implement multipliers and associated logic\n"); + log("\n"); log(" -widemux \n"); log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); log(" above this number of inputs (minimum value 5).\n"); @@ -103,7 +106,7 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, family; - bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, abc9; + bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, nodsp, abc9; int widemux; void clear_flags() YS_OVERRIDE @@ -121,6 +124,7 @@ struct SynthXilinxPass : public ScriptPass nosrl = false; nocarry = false; nowidelut = false; + nodsp = false; abc9 = false; widemux = 0; } @@ -201,6 +205,10 @@ struct SynthXilinxPass : public ScriptPass abc9 = true; continue; } + if (args[argidx] == "-nodsp") { + nodsp = true; + continue; + } break; } extra_args(args, argidx, design); @@ -239,10 +247,31 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("coarse")) { - if (help_mode) - run("synth -run coarse [-flatten]", "(with '-flatten')"); - else - run("synth -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); + run("proc"); + if (flatten || help_mode) + run("flatten", "(with '-flatten')"); + run("opt_expr"); + run("opt_clean"); + run("check"); + 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"); + if (!nodsp || help_mode) { + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_NAME=$__MUL25X18"); + run("clean"); + run("techmap -map +/xilinx/dsp_map.v"); + } + run("alumacc"); + run("opt"); + run("fsm"); + run("opt -fast"); + run("memory -nomap"); + run("opt_clean"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); From b33ecd2a746b734fda33d8535afecf76bd35f59c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 16:00:03 -0700 Subject: [PATCH 004/356] Move dsp_map.v into cells_map.v; cleanup synth_xilinx a little --- techlibs/xilinx/Makefile.inc | 1 - techlibs/xilinx/cells_map.v | 41 +++++++++++++++++++++++++++++++++ techlibs/xilinx/dsp_map.v | 40 -------------------------------- techlibs/xilinx/synth_xilinx.cc | 5 +--- 4 files changed, 42 insertions(+), 45 deletions(-) delete mode 100644 techlibs/xilinx/dsp_map.v diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index c41015e94..17c5df37d 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -31,7 +31,6 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/dsp_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.box)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut)) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 2eb9fa2c1..6ebca0d54 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -365,3 +365,44 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif + +module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] OUT); + wire [47:0] P_48; + DSP48E1 #( + // Disable all registers + .ACASCREG(0), + .ADREG(0), + .A_INPUT("DIRECT"), + .ALUMODEREG(0), + .AREG(0), + .BCASCREG(0), + .B_INPUT("DIRECT"), + .BREG(0), + .CARRYINREG(0), + .CARRYINSELREG(0), + .CREG(0), + .DREG(0), + .INMODEREG(0), + .MREG(0), + .OPMODEREG(0), + .PREG(0) + ) _TECHMAP_REPLACE_ ( + //Data path + .A({5'b0, A}), + .B(B), + .C(48'b0), + .D(24'b0), + .P(P_48), + + .INMODE(4'b0000), + .ALUMODE(4'b0000), + .OPMODE(7'b000101), + .CARRYINSEL(3'b000), + + .ACIN(30'b0), + .BCIN(18'b0), + .PCIN(48'b0), + .CARRYIN(1'b0) + ); + assign OUT = P_48; +endmodule diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v deleted file mode 100644 index 4faa204aa..000000000 --- a/techlibs/xilinx/dsp_map.v +++ /dev/null @@ -1,40 +0,0 @@ -module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] OUT); - wire [47:0] P_48; - DSP48E1 #( - // Disable all registers - .ACASCREG(0), - .ADREG(0), - .A_INPUT("DIRECT"), - .ALUMODEREG(0), - .AREG(0), - .BCASCREG(0), - .B_INPUT("DIRECT"), - .BREG(0), - .CARRYINREG(0), - .CARRYINSELREG(0), - .CREG(0), - .DREG(0), - .INMODEREG(0), - .MREG(0), - .OPMODEREG(0), - .PREG(0) - ) _TECHMAP_REPLACE_ ( - //Data path - .A({5'b0, A}), - .B(B), - .C(48'b0), - .D(24'b0), - .P(P_48), - - .INMODE(4'b0000), - .ALUMODE(4'b0000), - .OPMODE(7'b000101), - .CARRYINSEL(3'b000), - - .ACIN(30'b0), - .BCIN(18'b0), - .PCIN(48'b0), - .CARRYIN(1'b0) - ); - assign OUT = P_48; -endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 3da35db75..9199fbb53 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -279,11 +279,8 @@ struct SynthXilinxPass : public ScriptPass run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); - if (!nodsp || help_mode) { + if (!nodsp || help_mode) run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_NAME=$__MUL25X18"); - run("clean"); - run("techmap -map +/xilinx/dsp_map.v"); - } run("alumacc"); run("share"); From 20e3d2d9b0857dae9b03a7fc50b2cce4bced27f0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 11:13:22 -0700 Subject: [PATCH 005/356] Move DSP48E1 model out of cells_xtra, initial multiply one in cells_sim --- techlibs/xilinx/cells_sim.v | 131 +++++++++++++++++++++++++++++++++++ techlibs/xilinx/cells_xtra.v | 82 ---------------------- 2 files changed, 131 insertions(+), 82 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 05e46b4e7..99120452c 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -378,3 +378,134 @@ module SRLC32E ( always @(posedge CLK) if (CE) r <= { r[30:0], D }; endgenerate endmodule + +module DSP48E1 ( + output [29:0] ACOUT, + output [17:0] BCOUT, + output CARRYCASCOUT, + output [3:0] CARRYOUT, + output MULTSIGNOUT, + output OVERFLOW, + output reg [47:0] P, + output PATTERNBDETECT, + output PATTERNDETECT, + output [47:0] PCOUT, + output UNDERFLOW, + input [29:0] A, + input [29:0] ACIN, + input [3:0] ALUMODE, + input [17:0] B, + input [17:0] BCIN, + input [47:0] C, + input CARRYCASCIN, + input CARRYIN, + input [2:0] CARRYINSEL, + input CEA1, + input CEA2, + input CEAD, + input CEALUMODE, + input CEB1, + input CEB2, + input CEC, + input CECARRYIN, + input CECTRL, + input CED, + input CEINMODE, + input CEM, + input CEP, + input CLK, + input [24:0] D, + input [4:0] INMODE, + input MULTSIGNIN, + input [6:0] OPMODE, + input [47:0] PCIN, + input RSTA, + input RSTALLCARRYIN, + input RSTALUMODE, + input RSTB, + input RSTC, + input RSTCTRL, + input RSTD, + input RSTINMODE, + input RSTM, + input RSTP +); + parameter integer ACASCREG = 1; + parameter integer ADREG = 1; + parameter integer ALUMODEREG = 1; + parameter integer AREG = 1; + parameter AUTORESET_PATDET = "NO_RESET"; + parameter A_INPUT = "DIRECT"; + parameter integer BCASCREG = 1; + parameter integer BREG = 1; + parameter B_INPUT = "DIRECT"; + parameter integer CARRYINREG = 1; + parameter integer CARRYINSELREG = 1; + parameter integer CREG = 1; + parameter integer DREG = 1; + parameter integer INMODEREG = 1; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter SEL_MASK = "MASK"; + parameter SEL_PATTERN = "PATTERN"; + parameter USE_DPORT = "FALSE"; + parameter USE_MULT = "MULTIPLY"; + parameter USE_PATTERN_DETECT = "NO_PATDET"; + parameter USE_SIMD = "ONE48"; + parameter [47:0] MASK = 48'h3FFFFFFFFFFF; + parameter [47:0] PATTERN = 48'h000000000000; + parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; + parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + parameter [4:0] IS_INMODE_INVERTED = 5'b0; + parameter [6:0] IS_OPMODE_INVERTED = 7'b0; + + initial begin +`ifdef __ICARUS__ + if (ACASCREG != 0) $fatal(1, "Unsupported ACASCREG value"); + if (ADREG != 0) $fatal(1, "Unsupported ADREG value"); + if (ALUMODEREG != 0) $fatal(1, "Unsupported ALUMODEREG value"); + if (AREG != 0) $fatal(1, "Unsupported AREG value"); + if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value"); + if (A_INPUT != "DIRECT") $fatal(1, "Unsupported A_INPUT value"); + if (BCASCREG != 0) $fatal(1, "Unsupported BCASCREG value"); + if (BREG != 0) $fatal(1, "Unsupported BREG value"); + if (B_INPUT != "DIRECT") $fatal(1, "Unsupported B_INPUT value"); + if (CARRYINREG != 0) $fatal(1, "Unsupported CARRYINREG value"); + if (CARRYINSELREG != 0) $fatal(1, "Unsupported CARRYINSELREG value"); + if (CREG != 0) $fatal(1, "Unsupported CREG value"); + if (DREG != 0) $fatal(1, "Unsupported DREG value"); + if (INMODEREG != 0) $fatal(1, "Unsupported INMODEREG value"); + if (MREG != 0) $fatal(1, "Unsupported MREG value"); + if (OPMODEREG != 0) $fatal(1, "Unsupported OPMODEREG value"); + if (PREG != 0) $fatal(1, "Unsupported PREG value"); + if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value"); + if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value"); + if (USE_DPORT != "FALSE") $fatal(1, "Unsupported USE_DPORT value"); + if (USE_MULT != "MULTIPLY") $fatal(1, "Unsupported USE_MULT value"); + if (USE_PATTERN_DETECT != "NO_PATDET") $fatal(1, "Unsupported USE_PATTERN_DETECT value"); + if (USE_SIMD != "ONE48") $fatal(1, "Unsupported USE_SIMD value"); + if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value"); + if (IS_CARRYIN_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CARRYIN_INVERTED value"); + if (IS_CLK_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CLK_INVERTED value"); + if (IS_INMODE_INVERTED != 5'b0) $fatal(1, "Unsupported IS_INMODE_INVERTED value"); + if (IS_OPMODE_INVERTED != 7'b0) $fatal(1, "Unsupported IS_OPMODE_INVERTED value"); +`endif + end + + always @* begin + P <= {48{1'bx}}; +`ifdef __ICARUS__ + if (INMODE != 4'b0000) $fatal(1, "Unsupported INMODE value"); + if (ALUMODE != 4'b0000) $fatal(1, "Unsupported ALUMODE value"); + if (OPMODE != 7'b000101) $fatal(1, "Unsupported OPMODE value"); + if (CARRYINSEL != 3'b000) $fatal(1, "Unsupported CARRYINSEL value"); + if (ACIN != 30'b0) $fatal(1, "Unsupported ACIN value"); + if (BCIN != 18'b0) $fatal(1, "Unsupported BCIN value"); + if (PCIN != 48'b0) $fatal(1, "Unsupported PCIN value"); + if (CARRYIN != 1'b0) $fatal(1, "Unsupported CARRYIN value"); +`endif + P[42:0] <= A[24:0] * B; + end +endmodule diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index 15fa1b63a..d79349225 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -111,88 +111,6 @@ module DNA_PORT (...); input CLK, DIN, READ, SHIFT; endmodule -module DSP48E1 (...); - parameter integer ACASCREG = 1; - parameter integer ADREG = 1; - parameter integer ALUMODEREG = 1; - parameter integer AREG = 1; - parameter AUTORESET_PATDET = "NO_RESET"; - parameter A_INPUT = "DIRECT"; - parameter integer BCASCREG = 1; - parameter integer BREG = 1; - parameter B_INPUT = "DIRECT"; - parameter integer CARRYINREG = 1; - parameter integer CARRYINSELREG = 1; - parameter integer CREG = 1; - parameter integer DREG = 1; - parameter integer INMODEREG = 1; - parameter integer MREG = 1; - parameter integer OPMODEREG = 1; - parameter integer PREG = 1; - parameter SEL_MASK = "MASK"; - parameter SEL_PATTERN = "PATTERN"; - parameter USE_DPORT = "FALSE"; - parameter USE_MULT = "MULTIPLY"; - parameter USE_PATTERN_DETECT = "NO_PATDET"; - parameter USE_SIMD = "ONE48"; - parameter [47:0] MASK = 48'h3FFFFFFFFFFF; - parameter [47:0] PATTERN = 48'h000000000000; - parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; - parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - parameter [4:0] IS_INMODE_INVERTED = 5'b0; - parameter [6:0] IS_OPMODE_INVERTED = 7'b0; - output [29:0] ACOUT; - output [17:0] BCOUT; - output CARRYCASCOUT; - output [3:0] CARRYOUT; - output MULTSIGNOUT; - output OVERFLOW; - output [47:0] P; - output PATTERNBDETECT; - output PATTERNDETECT; - output [47:0] PCOUT; - output UNDERFLOW; - input [29:0] A; - input [29:0] ACIN; - input [3:0] ALUMODE; - input [17:0] B; - input [17:0] BCIN; - input [47:0] C; - input CARRYCASCIN; - input CARRYIN; - input [2:0] CARRYINSEL; - input CEA1; - input CEA2; - input CEAD; - input CEALUMODE; - input CEB1; - input CEB2; - input CEC; - input CECARRYIN; - input CECTRL; - input CED; - input CEINMODE; - input CEM; - input CEP; - input CLK; - input [24:0] D; - input [4:0] INMODE; - input MULTSIGNIN; - input [6:0] OPMODE; - input [47:0] PCIN; - input RSTA; - input RSTALLCARRYIN; - input RSTALUMODE; - input RSTB; - input RSTC; - input RSTCTRL; - input RSTD; - input RSTINMODE; - input RSTM; - input RSTP; -endmodule - module EFUSE_USR (...); parameter [31:0] SIM_EFUSE_VALUE = 32'h00000000; output [31:0] EFUSEUSR; From 1793e6018a37af674a356769779674e095fae261 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 11:19:54 -0700 Subject: [PATCH 006/356] Tidy up --- techlibs/common/mul2dsp.v | 65 ++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index ece45db79..d2e68987b 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -32,40 +32,32 @@ module \$mul (A, B, Y); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; - wire [1023:0] _TECHMAP_DO_ = "proc; clean"; - - generate - if (A_WIDTH `DSP_A_MAXWIDTH) begin + if (A_WIDTH > `DSP_A_MAXWIDTH) begin localparam n_floored = A_WIDTH/`DSP_A_MAXWIDTH; localparam n = n_floored + (n_floored*`DSP_A_MAXWIDTH < A_WIDTH ? 1 : 0); wire [`DSP_A_MAXWIDTH+B_WIDTH-1:0] partial [n-1:1]; @@ -101,8 +94,6 @@ module \$__mul_gen (A, B, Y); ); assign partial_sum[0][Y_WIDTH-1:B_WIDTH+`DSP_A_MAXWIDTH]=0; - genvar i; - generate for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( .A_SIGNED(A_SIGNED), @@ -122,7 +113,6 @@ module \$__mul_gen (A, B, Y); partial_sum[i-1][(i*`DSP_A_MAXWIDTH)-1:0] }; end - endgenerate \$__mul_gen #( .A_SIGNED(A_SIGNED), @@ -161,8 +151,6 @@ module \$__mul_gen (A, B, Y); ); assign partial_sum[0][Y_WIDTH-1:A_WIDTH+`DSP_B_MAXWIDTH]=0; - genvar i; - generate for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( .A_SIGNED(A_SIGNED), @@ -187,7 +175,6 @@ module \$__mul_gen (A, B, Y); partial_sum[i-1][(i*`DSP_B_MAXWIDTH)-1:0] }; end - endgenerate \$__mul_gen #( .A_SIGNED(A_SIGNED), From 91fcf034bceecd50f1aaf96c3cdc270250ab9597 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 11:24:11 -0700 Subject: [PATCH 007/356] Only swap if B_WIDTH > A_WIDTH --- techlibs/common/mul2dsp.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index d2e68987b..0eec4cc82 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -33,7 +33,7 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - if (A_WIDTH < B_WIDTH) + if (B_WIDTH < A_WIDTH) \$__mul_gen #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), From 0c7ee6d0fa14b634ffbde5ad79983cb89372a697 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 14:18:44 -0700 Subject: [PATCH 008/356] Move DSP mapping back out to dsp_map.v --- techlibs/xilinx/cells_map.v | 41 ------------------------------------- techlibs/xilinx/dsp_map.v | 40 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 41 deletions(-) create mode 100644 techlibs/xilinx/dsp_map.v diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 6ebca0d54..2eb9fa2c1 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -365,44 +365,3 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif - -module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] OUT); - wire [47:0] P_48; - DSP48E1 #( - // Disable all registers - .ACASCREG(0), - .ADREG(0), - .A_INPUT("DIRECT"), - .ALUMODEREG(0), - .AREG(0), - .BCASCREG(0), - .B_INPUT("DIRECT"), - .BREG(0), - .CARRYINREG(0), - .CARRYINSELREG(0), - .CREG(0), - .DREG(0), - .INMODEREG(0), - .MREG(0), - .OPMODEREG(0), - .PREG(0) - ) _TECHMAP_REPLACE_ ( - //Data path - .A({5'b0, A}), - .B(B), - .C(48'b0), - .D(24'b0), - .P(P_48), - - .INMODE(4'b0000), - .ALUMODE(4'b0000), - .OPMODE(7'b000101), - .CARRYINSEL(3'b000), - - .ACIN(30'b0), - .BCIN(18'b0), - .PCIN(48'b0), - .CARRYIN(1'b0) - ); - assign OUT = P_48; -endmodule diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v new file mode 100644 index 000000000..da1d6f3a9 --- /dev/null +++ b/techlibs/xilinx/dsp_map.v @@ -0,0 +1,40 @@ +module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); + wire [47:0] P_48; + DSP48E1 #( + // Disable all registers + .ACASCREG(0), + .ADREG(0), + .A_INPUT("DIRECT"), + .ALUMODEREG(0), + .AREG(0), + .BCASCREG(0), + .B_INPUT("DIRECT"), + .BREG(0), + .CARRYINREG(0), + .CARRYINSELREG(0), + .CREG(0), + .DREG(0), + .INMODEREG(0), + .MREG(0), + .OPMODEREG(0), + .PREG(0) + ) _TECHMAP_REPLACE_ ( + //Data path + .A({5'b0, A}), + .B(B), + .C(48'b0), + .D(24'b0), + .P(P_48), + + .INMODE(4'b0000), + .ALUMODE(4'b0000), + .OPMODE(7'b000101), + .CARRYINSEL(3'b000), + + .ACIN(30'b0), + .BCIN(18'b0), + .PCIN(48'b0), + .CARRYIN(1'b0) + ); + assign Y = P_48; +endmodule From 42f8e68e76a3717cf4ad29c36f0a9a801cde52c1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 14:45:47 -0700 Subject: [PATCH 009/356] OUT port to Y in generic DSP --- techlibs/common/mul2dsp.v | 2 +- techlibs/ecp5/dsp_map.v | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 0eec4cc82..0a87716d9 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -209,7 +209,7 @@ module \$__mul_gen (A, B, Y); `DSP_NAME _TECHMAP_REPLACE_ ( .A({ {{`DSP_A_MAXWIDTH-A_WIDTH}{Asign}}, A }), .B({ {{`DSP_B_MAXWIDTH-B_WIDTH}{Bsign}}, B }), - .OUT({dummy, out}) + .Y({dummy, out}) ); if (Y_WIDTH < A_WIDTH+B_WIDTH) assign Y = out[Y_WIDTH-1:0]; diff --git a/techlibs/ecp5/dsp_map.v b/techlibs/ecp5/dsp_map.v index 5f7755afb..24e28869e 100644 --- a/techlibs/ecp5/dsp_map.v +++ b/techlibs/ecp5/dsp_map.v @@ -1,10 +1,10 @@ -module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] OUT); +module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); MULT18X18D _TECHMAP_REPLACE_ ( .A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .A4(A[4]), .A5(A[5]), .A6(A[6]), .A7(A[7]), .A8(A[8]), .A9(A[9]), .A10(A[10]), .A11(A[11]), .A12(A[12]), .A13(A[13]), .A14(A[14]), .A15(A[15]), .A16(A[16]), .A17(A[17]), .B0(B[0]), .B1(B[1]), .B2(B[2]), .B3(B[3]), .B4(B[4]), .B5(B[5]), .B6(B[6]), .B7(B[7]), .B8(B[8]), .B9(B[9]), .B10(B[10]), .B11(B[11]), .B12(B[12]), .B13(B[13]), .B14(B[14]), .B15(B[15]), .B16(B[16]), .B17(B[17]), .C17(1'b0), .C16(1'b0), .C15(1'b0), .C14(1'b0), .C13(1'b0), .C12(1'b0), .C11(1'b0), .C10(1'b0), .C9(1'b0), .C8(1'b0), .C7(1'b0), .C6(1'b0), .C5(1'b0), .C4(1'b0), .C3(1'b0), .C2(1'b0), .C1(1'b0), .C0(1'b0), .SIGNEDA(1'b0), .SIGNEDB(1'b0), .SOURCEA(1'b0), .SOURCEB(1'b0), - .P0(OUT[0]), .P1(OUT[1]), .P2(OUT[2]), .P3(OUT[3]), .P4(OUT[4]), .P5(OUT[5]), .P6(OUT[6]), .P7(OUT[7]), .P8(OUT[8]), .P9(OUT[9]), .P10(OUT[10]), .P11(OUT[11]), .P12(OUT[12]), .P13(OUT[13]), .P14(OUT[14]), .P15(OUT[15]), .P16(OUT[16]), .P17(OUT[17]), .P18(OUT[18]), .P19(OUT[19]), .P20(OUT[20]), .P21(OUT[21]), .P22(OUT[22]), .P23(OUT[23]), .P24(OUT[24]), .P25(OUT[25]), .P26(OUT[26]), .P27(OUT[27]), .P28(OUT[28]), .P29(OUT[29]), .P30(OUT[30]), .P31(OUT[31]), .P32(OUT[32]), .P33(OUT[33]), .P34(OUT[34]), .P35(OUT[35]) + .P0(Y[0]), .P1(Y[1]), .P2(Y[2]), .P3(Y[3]), .P4(Y[4]), .P5(Y[5]), .P6(Y[6]), .P7(Y[7]), .P8(Y[8]), .P9(Y[9]), .P10(Y[10]), .P11(Y[11]), .P12(Y[12]), .P13(Y[13]), .P14(Y[14]), .P15(Y[15]), .P16(Y[16]), .P17(Y[17]), .P18(Y[18]), .P19(Y[19]), .P20(Y[20]), .P21(Y[21]), .P22(Y[22]), .P23(Y[23]), .P24(Y[24]), .P25(Y[25]), .P26(Y[26]), .P27(Y[27]), .P28(Y[28]), .P29(Y[29]), .P30(Y[30]), .P31(Y[31]), .P32(Y[32]), .P33(Y[33]), .P34(Y[34]), .P35(Y[35]) ); endmodule From dd59375a66b6463df9cc371b30249324b47399aa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 14:46:31 -0700 Subject: [PATCH 010/356] Add xilinx_dsp for register packing --- passes/pmgen/.gitignore | 3 +- passes/pmgen/xilinx_dsp.cc | 120 ++++++++++++++++++++++++++++++++++++ passes/pmgen/xilinx_dsp.pmg | 71 +++++++++++++++++++++ 3 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 passes/pmgen/xilinx_dsp.cc create mode 100644 passes/pmgen/xilinx_dsp.pmg diff --git a/passes/pmgen/.gitignore b/passes/pmgen/.gitignore index 0ad36ea2c..10e245e00 100644 --- a/passes/pmgen/.gitignore +++ b/passes/pmgen/.gitignore @@ -1,2 +1 @@ -/ice40_dsp_pm.h -/peepopt_pm.h +/%_pm.h diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc new file mode 100644 index 000000000..b98703de3 --- /dev/null +++ b/passes/pmgen/xilinx_dsp.cc @@ -0,0 +1,120 @@ +/* + * 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. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +#include "passes/pmgen/xilinx_dsp_pm.h" + +void create_xilinx_dsp(xilinx_dsp_pm &pm) +{ + auto &st = pm.st_xilinx_dsp; + +#if 0 + log("\n"); + log("ffA: %s\n", log_id(st.ffA, "--")); + log("ffB: %s\n", log_id(st.ffB, "--")); + log("mul: %s\n", log_id(st.mul, "--")); + log("ffY: %s\n", log_id(st.ffY, "--")); +#endif + + log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.mul)); + + Cell *cell = st.mul; + log_assert(cell); + + // Input Interface + + cell->setPort("\\A", st.sigA); + cell->setPort("\\B", st.sigB); + + cell->setParam("\\AREG", st.ffA ? State::S1 : State::S0); + cell->setParam("\\BREG", st.ffB ? State::S1 : State::S0); + + if (st.clock != SigBit()) + { + cell->setPort("\\CLK", st.clock); + + if (st.ffA) { + cell->setParam("\\AREG", State::S1); + cell->setPort("\\CEA2", State::S1); + } + if (st.ffB) { + cell->setParam("\\BREG", State::S1); + cell->setPort("\\CEA2", State::S1); + } + if (st.ffY) { + cell->setPort("\\PREG", State::S1); + cell->setPort("\\CEP", State::S1); + } + + log(" clock: %s (%s)", log_signal(st.clock), "posedge"); + + if (st.ffA) + log(" ffA:%s", log_id(st.ffA)); + + if (st.ffB) + log(" ffB:%s", log_id(st.ffB)); + + if (st.ffY) + log(" ffY:%s", log_id(st.ffY)); + + log("\n"); + } + + // Output Interface + + pm.autoremove(st.ffY); +} + +struct Ice40DspPass : public Pass { + Ice40DspPass() : Pass("xilinx_dsp", "Xilinx: pack DSP registers") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" xilinx_dsp [options] [selection]\n"); + log("\n"); + log("Pack registers into Xilinx DSPs\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing ICE40_DSP pass (map multipliers).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-singleton") { + // singleton_mode = true; + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + xilinx_dsp_pm(module, module->selected_cells()).run_xilinx_dsp(create_xilinx_dsp); + } +} Ice40DspPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg new file mode 100644 index 000000000..6bb4e7bd8 --- /dev/null +++ b/passes/pmgen/xilinx_dsp.pmg @@ -0,0 +1,71 @@ +pattern xilinx_dsp + +state clock +state sigA sigB sigY sigS +state addAB muxAB + +match mul + select mul->type.in($__MUL25X18) +endmatch + +match ffA + select ffA->type.in($dff) /* TODO: $dffe */ + // select nusers(port(ffA, \Q)) == 2 + index port(ffA, \Q) === port(mul, \A) + // DSP48E1 does not support clock inversion + index port(ffA, \CLK_POLARITY) === State::S1 + optional +endmatch + +code sigA clock + sigA = port(mul, \A); + + if (ffA) { + sigA = port(ffA, \D); + clock = port(ffA, \CLK).as_bit(); + } +endcode + +match ffB + select ffB->type.in($dff) + // select nusers(port(ffB, \Q)) == 2 + index port(ffB, \Q) === port(mul, \B) + index port(ffB, \CLK_POLARITY) === State::S1 + optional +endmatch + +code sigB clock + sigB = port(mul, \B); + + if (ffB) { + sigB = port(ffB, \D); + SigBit c = port(ffB, \CLK).as_bit(); + + if (clock != SigBit() && c != clock) + reject; + + clock = c; + } +endcode + +match ffY + select ffY->type.in($dff) + select nusers(port(ffY, \D)) == 2 + index port(ffY, \D) === port(mul, \Y) + index port(ffY, \CLK_POLARITY) === State::S1 + optional +endmatch + +code sigY clock + sigY = port(mul, \Y); + + if (ffY) { + sigY = port(ffY, \Q); + SigBit c = port(ffY, \CLK).as_bit(); + + if (clock != SigBit() && c != clock) + reject; + + clock = c; + } +endcode From 5f00d335d4861fc03dd7b6cee68fd79505bd3d41 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 15:03:15 -0700 Subject: [PATCH 011/356] Oops forgot these files --- passes/pmgen/Makefile.inc | 9 +++++++-- techlibs/xilinx/Makefile.inc | 1 + techlibs/xilinx/synth_xilinx.cc | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 7911132db..e33866670 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -1,14 +1,19 @@ OBJS += passes/pmgen/ice40_dsp.o +OBJS += passes/pmgen/xilinx_dsp.o OBJS += passes/pmgen/peepopt.o # -------------------------------------- +passes/pmgen/%.o: passes/pmgen/%_pm.h passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h +passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h +EXTRA_OBJS += passes/pmgen/xilinx_dsp_pm.h .SECONDARY: passes/pmgen/ice40_dsp_pm.h +.SECONDARY: passes/pmgen/xilinx_dsp_pm.h -passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg - $(P) mkdir -p passes/pmgen && python3 $< -o $@ -p ice40_dsp $(filter-out $<,$^) +passes/pmgen/%_pm.h: passes/pmgen/pmgen.py passes/pmgen/%.pmg + $(P) mkdir -p passes/pmgen && python3 $< -o $@ -p $* $(filter-out $<,$^) # -------------------------------------- diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 2c6e7432e..b0251d621 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -38,6 +38,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/dsp_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.box)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut)) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 01e75b50e..796615211 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -329,6 +329,10 @@ struct SynthXilinxPass : public ScriptPass run("memory_map"); run("dffsr2dff"); run("dff2dffe"); + if (help_mode || !nodsp) { + run("techmap -map +/xilinx/dsp_map.v", "(skip if '-nodsp')"); + run("xilinx_dsp", " (skip if '-nodsp')"); + } if (help_mode) { run("simplemap t:$mux", " ('-widemux' only)"); run("muxcover , ('-widemux' only)"); From b29f26f6c7d880b9a446f6eacfa988c2018a1e30 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 16:23:12 -0700 Subject: [PATCH 012/356] SigSpec::extend_u0() to return *this --- kernel/rtlil.cc | 3 ++- kernel/rtlil.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a09f4a0d1..ebb6f5bf6 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3426,7 +3426,7 @@ void RTLIL::SigSpec::append_bit(const RTLIL::SigBit &bit) check(); } -void RTLIL::SigSpec::extend_u0(int width, bool is_signed) +RTLIL::SigSpec& RTLIL::SigSpec::extend_u0(int width, bool is_signed) { cover("kernel.rtlil.sigspec.extend_u0"); @@ -3443,6 +3443,7 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed) append(padding); } + return *this; } RTLIL::SigSpec RTLIL::SigSpec::repeat(int num) const diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 82cbfaf28..8d88cc97c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -776,7 +776,7 @@ public: void append(const RTLIL::SigSpec &signal); void append_bit(const RTLIL::SigBit &bit); - void extend_u0(int width, bool is_signed = false); + RTLIL::SigSpec& extend_u0(int width, bool is_signed = false); RTLIL::SigSpec repeat(int num) const; From fd5b3593d8496578c0879fc024bf81737be3702f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 16:52:37 -0700 Subject: [PATCH 013/356] Do not swap if equals --- techlibs/common/mul2dsp.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 0a87716d9..046f84320 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -33,7 +33,7 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - if (B_WIDTH < A_WIDTH) + if (A_WIDTH >= B_WIDTH) \$__mul_gen #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), From 7a75f5f3ac82aa764f41e8fbb93475ab729750dc Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 16 Jul 2019 16:19:32 +0100 Subject: [PATCH 014/356] mul2dsp: Fix indentation Signed-off-by: David Shah --- techlibs/common/mul2dsp.v | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 0eec4cc82..69de74cad 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -92,7 +92,7 @@ module \$__mul_gen (A, B, Y); .B(B), .Y(partial_sum[0][B_WIDTH+`DSP_A_MAXWIDTH-1:0]) ); - assign partial_sum[0][Y_WIDTH-1:B_WIDTH+`DSP_A_MAXWIDTH]=0; + assign partial_sum[0][Y_WIDTH-1:B_WIDTH+`DSP_A_MAXWIDTH]=0; for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( @@ -149,7 +149,7 @@ module \$__mul_gen (A, B, Y); .B(B[`DSP_B_MAXWIDTH-1:0]), .Y(partial_sum[0][A_WIDTH+`DSP_B_MAXWIDTH-1:0]) ); - assign partial_sum[0][Y_WIDTH-1:A_WIDTH+`DSP_B_MAXWIDTH]=0; + assign partial_sum[0][Y_WIDTH-1:A_WIDTH+`DSP_B_MAXWIDTH]=0; for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( @@ -157,14 +157,14 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH), - .Y_WIDTH(A_WIDTH+`DSP_B_MAXWIDTH) + .Y_WIDTH(A_WIDTH+`DSP_B_MAXWIDTH) ) mul ( .A(A), .B(B[(i+1)*`DSP_B_MAXWIDTH-1:i*`DSP_B_MAXWIDTH]), .Y(partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:0]) ); //assign partial_sum[i] = (partial[i] << i*`DSP_B_MAXWIDTH) + partial_sum[i-1]; - // was: + // was: //assign partial_sum[i] = { // partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH], // partial[i][`DSP_B_MAXWIDTH-1:0] + partial_sum[i-1][A_WIDTH+(i*`DSP_B_MAXWIDTH)-1:A_WIDTH+((i-1)*`DSP_B_MAXWIDTH)], @@ -187,14 +187,14 @@ module \$__mul_gen (A, B, Y); .B(B[B_WIDTH-1:(n-1)*`DSP_B_MAXWIDTH]), .Y(partial[n-1][A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH-1:0]) ); - // AMD: this came comment out -- looks closer to right answer + // AMD: this came comment out -- looks closer to right answer //assign Y = (partial[n-1] << (n-1)*`DSP_B_MAXWIDTH) + partial_sum[n-2]; - // was (looks broken) + // was (looks broken) //assign Y = { // partial[n-1][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH], // partial[n-1][`DSP_B_MAXWIDTH-1:0] + partial_sum[n-2][A_WIDTH+((n-1)*`DSP_B_MAXWIDTH)-1:A_WIDTH+((n-2)*`DSP_B_MAXWIDTH)], // partial_sum[n-2][A_WIDTH+((n-2)*`DSP_B_MAXWIDTH):0] - assign Y = { + assign Y = { partial[n-1][A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH-1:0] + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_B_MAXWIDTH)], partial_sum[n-2][((n-1)*`DSP_B_MAXWIDTH)-1:0] From 8da4c1ad8262216c5204c735f5297da33fed01fa Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 16 Jul 2019 16:44:40 +0100 Subject: [PATCH 015/356] mul2dsp: Fix edge case where Y_WIDTH is less than B_WIDTH+`DSP_A_MAXWIDTH Signed-off-by: David Shah --- techlibs/common/mul2dsp.v | 40 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 69de74cad..262e29986 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -80,19 +80,21 @@ module \$__mul_gen (A, B, Y); localparam n = n_floored + (n_floored*`DSP_A_MAXWIDTH < A_WIDTH ? 1 : 0); wire [`DSP_A_MAXWIDTH+B_WIDTH-1:0] partial [n-1:1]; wire [Y_WIDTH-1:0] partial_sum [n-2:0]; + localparam int_yw = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH); \$__mul_gen #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), - .Y_WIDTH(B_WIDTH+`DSP_A_MAXWIDTH) + .Y_WIDTH(int_yw) ) mul_slice_first ( .A(A[`DSP_A_MAXWIDTH-1:0]), .B(B), - .Y(partial_sum[0][B_WIDTH+`DSP_A_MAXWIDTH-1:0]) + .Y(partial_sum[0][int_yw-1:0]) ); - assign partial_sum[0][Y_WIDTH-1:B_WIDTH+`DSP_A_MAXWIDTH]=0; + if (Y_WIDTH > int_yw) + assign partial_sum[0][Y_WIDTH-1:int_yw]=0; for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( @@ -100,15 +102,15 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), - .Y_WIDTH(B_WIDTH+`DSP_A_MAXWIDTH) + .Y_WIDTH(int_yw) ) mul_slice ( .A(A[(i+1)*`DSP_A_MAXWIDTH-1:i*`DSP_A_MAXWIDTH]), .B(B), - .Y(partial[i][B_WIDTH+`DSP_A_MAXWIDTH-1:0]) + .Y(partial[i][int_yw-1:0]) ); //assign partial_sum[i] = (partial[i] << i*`DSP_A_MAXWIDTH) + partial_sum[i-1]; assign partial_sum[i] = { - partial[i][B_WIDTH+`DSP_A_MAXWIDTH-1:0] + partial[i][int_yw-1:0] + partial_sum[i-1][Y_WIDTH-1:(i*`DSP_A_MAXWIDTH)], partial_sum[i-1][(i*`DSP_A_MAXWIDTH)-1:0] }; @@ -119,15 +121,15 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-(n-1)*`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), - .Y_WIDTH(A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH), + .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH)), ) mul_slice_last ( .A(A[A_WIDTH-1:(n-1)*`DSP_A_MAXWIDTH]), .B(B), - .Y(partial[n-1][A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH-1:0]) + .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH)-1:0]) ); //assign Y = (partial[n-1] << (n-1)*`DSP_A_MAXWIDTH) + partial_sum[n-2]; assign Y = { - partial[n-1][A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH:0] + partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH):0] + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_A_MAXWIDTH)], partial_sum[n-2][((n-1)*`DSP_A_MAXWIDTH)-1:0] }; @@ -137,19 +139,21 @@ module \$__mul_gen (A, B, Y); localparam n = n_floored + (n_floored*`DSP_B_MAXWIDTH < B_WIDTH ? 1 : 0); wire [A_WIDTH+`DSP_B_MAXWIDTH-1:0] partial [n-1:1]; wire [Y_WIDTH-1:0] partial_sum [n-2:0]; + localparam int_yw = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH); \$__mul_gen #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH), - .Y_WIDTH(A_WIDTH+`DSP_B_MAXWIDTH) + .Y_WIDTH(int_yw) ) mul_first ( .A(A), .B(B[`DSP_B_MAXWIDTH-1:0]), - .Y(partial_sum[0][A_WIDTH+`DSP_B_MAXWIDTH-1:0]) + .Y(partial_sum[0][int_yw-1:0]) ); - assign partial_sum[0][Y_WIDTH-1:A_WIDTH+`DSP_B_MAXWIDTH]=0; + if (Y_WIDTH > int_yw) + assign partial_sum[0][Y_WIDTH-1:A_WIDTH+`DSP_B_MAXWIDTH]=0; for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( @@ -157,11 +161,11 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH), - .Y_WIDTH(A_WIDTH+`DSP_B_MAXWIDTH) + .Y_WIDTH(int_yw) ) mul ( .A(A), .B(B[(i+1)*`DSP_B_MAXWIDTH-1:i*`DSP_B_MAXWIDTH]), - .Y(partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:0]) + .Y(partial[i][int_yw-1:0]) ); //assign partial_sum[i] = (partial[i] << i*`DSP_B_MAXWIDTH) + partial_sum[i-1]; // was: @@ -170,7 +174,7 @@ module \$__mul_gen (A, B, Y); // partial[i][`DSP_B_MAXWIDTH-1:0] + partial_sum[i-1][A_WIDTH+(i*`DSP_B_MAXWIDTH)-1:A_WIDTH+((i-1)*`DSP_B_MAXWIDTH)], // partial_sum[i-1][A_WIDTH+((i-1)*`DSP_B_MAXWIDTH):0] assign partial_sum[i] = { - partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:0] + partial[i][int_yw-1:0] + partial_sum[i-1][Y_WIDTH-1:(i*`DSP_B_MAXWIDTH)], partial_sum[i-1][(i*`DSP_B_MAXWIDTH)-1:0] }; @@ -181,11 +185,11 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-(n-1)*`DSP_B_MAXWIDTH), - .Y_WIDTH(A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH) + .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH)) ) mul_last ( .A(A), .B(B[B_WIDTH-1:(n-1)*`DSP_B_MAXWIDTH]), - .Y(partial[n-1][A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH-1:0]) + .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH)-1:0]) ); // AMD: this came comment out -- looks closer to right answer //assign Y = (partial[n-1] << (n-1)*`DSP_B_MAXWIDTH) + partial_sum[n-2]; @@ -195,7 +199,7 @@ module \$__mul_gen (A, B, Y); // partial[n-1][`DSP_B_MAXWIDTH-1:0] + partial_sum[n-2][A_WIDTH+((n-1)*`DSP_B_MAXWIDTH)-1:A_WIDTH+((n-2)*`DSP_B_MAXWIDTH)], // partial_sum[n-2][A_WIDTH+((n-2)*`DSP_B_MAXWIDTH):0] assign Y = { - partial[n-1][A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH-1:0] + partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH)-1:0] + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_B_MAXWIDTH)], partial_sum[n-2][((n-1)*`DSP_B_MAXWIDTH)-1:0] }; From 95c8d27b0bfdea330a62a18825dea3691b4affe2 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 16 Jul 2019 16:46:41 +0100 Subject: [PATCH 016/356] xilinx: Treat DSP48E1 as 24x17 unsigned for now (actual behaviour is 25x18 signed) Signed-off-by: David Shah --- techlibs/xilinx/cells_map.v | 6 +++--- techlibs/xilinx/synth_xilinx.cc | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 6ebca0d54..8302e0b3a 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -366,7 +366,7 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); endmodule `endif -module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] OUT); +module \$__MUL25X18 (input [23:0] A, input [16:0] B, output [40:0] OUT); wire [47:0] P_48; DSP48E1 #( // Disable all registers @@ -388,8 +388,8 @@ module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] OUT); .PREG(0) ) _TECHMAP_REPLACE_ ( //Data path - .A({5'b0, A}), - .B(B), + .A({6'b0, A}), + .B({1'b0, B}), .C(48'b0), .D(24'b0), .P(P_48), diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 01e75b50e..5bfbd1583 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -284,8 +284,12 @@ struct SynthXilinxPass : public ScriptPass run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); + // The actual behaviour of the Xilinx DSP is a signed 25x18 multiply + // Due to current limitations of mul2dsp, we are actually mapping as a 24x17 + // unsigned multiply with MSBs set to 1'b0 + if (!nodsp || help_mode) - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_NAME=$__MUL25X18"); + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=24 -D DSP_B_MAXWIDTH=17 -D DSP_NAME=$__MUL25X18"); run("alumacc"); run("share"); From d38df68d26f1644539e5116e6b6c360e1c389cc9 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 16 Jul 2019 17:53:08 +0100 Subject: [PATCH 017/356] xilinx: Add correct signed behaviour to DSP48E1 model Signed-off-by: David Shah --- techlibs/xilinx/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 99120452c..ea5a3b788 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -506,6 +506,6 @@ module DSP48E1 ( if (PCIN != 48'b0) $fatal(1, "Unsupported PCIN value"); if (CARRYIN != 1'b0) $fatal(1, "Unsupported CARRYIN value"); `endif - P[42:0] <= A[24:0] * B; + P[42:0] <= $signed(A[24:0]) * $signed(B); end endmodule From 5d1ce043812b9b86ee3c3588c430ea1cd57fee1e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Jul 2019 14:05:50 -0700 Subject: [PATCH 018/356] Add support for {A,B,P}REG in DSP48E1 --- techlibs/xilinx/cells_sim.v | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 99120452c..5410983ae 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -466,11 +466,11 @@ module DSP48E1 ( if (ACASCREG != 0) $fatal(1, "Unsupported ACASCREG value"); if (ADREG != 0) $fatal(1, "Unsupported ADREG value"); if (ALUMODEREG != 0) $fatal(1, "Unsupported ALUMODEREG value"); - if (AREG != 0) $fatal(1, "Unsupported AREG value"); + if (AREG == 2) $fatal(1, "Unsupported AREG value"); if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value"); if (A_INPUT != "DIRECT") $fatal(1, "Unsupported A_INPUT value"); if (BCASCREG != 0) $fatal(1, "Unsupported BCASCREG value"); - if (BREG != 0) $fatal(1, "Unsupported BREG value"); + if (BREG == 2) $fatal(1, "Unsupported BREG value"); if (B_INPUT != "DIRECT") $fatal(1, "Unsupported B_INPUT value"); if (CARRYINREG != 0) $fatal(1, "Unsupported CARRYINREG value"); if (CARRYINSELREG != 0) $fatal(1, "Unsupported CARRYINSELREG value"); @@ -479,7 +479,7 @@ module DSP48E1 ( if (INMODEREG != 0) $fatal(1, "Unsupported INMODEREG value"); if (MREG != 0) $fatal(1, "Unsupported MREG value"); if (OPMODEREG != 0) $fatal(1, "Unsupported OPMODEREG value"); - if (PREG != 0) $fatal(1, "Unsupported PREG value"); + //if (PREG != 0) $fatal(1, "Unsupported PREG value"); if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value"); if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value"); if (USE_DPORT != "FALSE") $fatal(1, "Unsupported USE_DPORT value"); @@ -494,8 +494,18 @@ module DSP48E1 ( `endif end + reg [29:0] Ar; + reg [17:0] Br; + reg [47:0] Pr; + generate + if (AREG == 1) begin always @(posedge CLK) if (CEA2) Ar <= A; end + else always @* Ar <= A; + if (BREG == 1) begin always @(posedge CLK) if (CEB2) Br <= B; end + else always @* Br <= B; + endgenerate + always @* begin - P <= {48{1'bx}}; + Pr <= {48{1'bx}}; `ifdef __ICARUS__ if (INMODE != 4'b0000) $fatal(1, "Unsupported INMODE value"); if (ALUMODE != 4'b0000) $fatal(1, "Unsupported ALUMODE value"); @@ -506,6 +516,12 @@ module DSP48E1 ( if (PCIN != 48'b0) $fatal(1, "Unsupported PCIN value"); if (CARRYIN != 1'b0) $fatal(1, "Unsupported CARRYIN value"); `endif - P[42:0] <= A[24:0] * B; + Pr[42:0] <= Ar[24:0] * Br; end + + generate + if (PREG == 1) begin always @(posedge CLK) if (CEP) P <= Pr; end + else always @* P <= Pr; + endgenerate + endmodule From d086dfb5b0d4f1f8e60a9e32d874a1f94cf73c66 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Jul 2019 14:06:07 -0700 Subject: [PATCH 019/356] SigSpec::extract to allow negative length --- kernel/rtlil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index ebb6f5bf6..6f5082138 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3353,7 +3353,7 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const { unpack(); cover("kernel.rtlil.sigspec.extract_pos"); - return std::vector(bits_.begin() + offset, bits_.begin() + offset + length); + return std::vector(bits_.begin() + offset, length >= 0 ? bits_.begin() + offset + length : bits_.end() + length + 1); } void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal) From 9616dbd125171905bccf55fa7fd564e4ae2ca5ab Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Jul 2019 14:06:32 -0700 Subject: [PATCH 020/356] Add support {A,B,P}REG packing --- passes/pmgen/xilinx_dsp.cc | 68 ++++++++++++++++++------------ passes/pmgen/xilinx_dsp.pmg | 83 +++++++++++++++++++++++-------------- 2 files changed, 95 insertions(+), 56 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index b98703de3..a09f96a7f 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -25,46 +25,60 @@ PRIVATE_NAMESPACE_BEGIN #include "passes/pmgen/xilinx_dsp_pm.h" -void create_xilinx_dsp(xilinx_dsp_pm &pm) +void pack_xilinx_dsp(xilinx_dsp_pm &pm) { auto &st = pm.st_xilinx_dsp; -#if 0 +#if 1 log("\n"); log("ffA: %s\n", log_id(st.ffA, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); - log("mul: %s\n", log_id(st.mul, "--")); - log("ffY: %s\n", log_id(st.ffY, "--")); + log("dsp: %s\n", log_id(st.dsp, "--")); + log("ffP: %s\n", log_id(st.ffP, "--")); + log("muxP: %s\n", log_id(st.muxP, "--")); + log("P_WIDTH: %d\n", st.P_WIDTH); #endif - log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.mul)); + log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.dsp)); - Cell *cell = st.mul; + Cell *cell = st.dsp; log_assert(cell); - // Input Interface - - cell->setPort("\\A", st.sigA); - cell->setPort("\\B", st.sigB); - - cell->setParam("\\AREG", st.ffA ? State::S1 : State::S0); - cell->setParam("\\BREG", st.ffB ? State::S1 : State::S0); - if (st.clock != SigBit()) { cell->setPort("\\CLK", st.clock); if (st.ffA) { + SigSpec D = st.ffA->getPort("\\D"); + cell->setPort("\\A", D.extend_u0(30)); cell->setParam("\\AREG", State::S1); - cell->setPort("\\CEA2", State::S1); + if (st.ffA->type == "$dff") + cell->setPort("\\CEA2", State::S1); + else if (st.ffA->type == "$dffe") + cell->setPort("\\CEA2", st.ffA->getPort("\\EN")); + else log_abort(); } if (st.ffB) { + SigSpec D = st.ffB->getPort("\\D"); + cell->setPort("\\B", D.extend_u0(18)); cell->setParam("\\BREG", State::S1); - cell->setPort("\\CEA2", State::S1); + if (st.ffB->type == "$dff") + cell->setPort("\\CEB2", State::S1); + else if (st.ffB->type == "$dffe") + cell->setPort("\\CEB2", st.ffB->getPort("\\EN")); + else log_abort(); } - if (st.ffY) { - cell->setPort("\\PREG", State::S1); - cell->setPort("\\CEP", State::S1); + if (st.ffP) { + SigSpec P = cell->getPort("\\P"); + SigSpec Q = st.ffP->getPort("\\Q"); + Q.append(P.extract(GetSize(Q), -1)); + cell->setPort("\\P", Q); + cell->setParam("\\PREG", State::S1); + if (st.ffP->type == "$dff") + cell->setPort("\\CEP", State::S1); + else if (st.ffP->type == "$dffe") + cell->setPort("\\CEP", st.ffP->getPort("\\EN")); + else log_abort(); } log(" clock: %s (%s)", log_signal(st.clock), "posedge"); @@ -75,15 +89,17 @@ void create_xilinx_dsp(xilinx_dsp_pm &pm) if (st.ffB) log(" ffB:%s", log_id(st.ffB)); - if (st.ffY) - log(" ffY:%s", log_id(st.ffY)); + if (st.ffP) + log(" ffY:%s", log_id(st.ffP)); log("\n"); } - // Output Interface - - pm.autoremove(st.ffY); + pm.autoremove(st.ffA); + pm.autoremove(st.ffB); + pm.autoremove(st.ffP); + pm.autoremove(st.muxP); + pm.blacklist(cell); } struct Ice40DspPass : public Pass { @@ -99,7 +115,7 @@ struct Ice40DspPass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - log_header(design, "Executing ICE40_DSP pass (map multipliers).\n"); + log_header(design, "Executing XILINX_DSP pass (pack DSPs).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -113,7 +129,7 @@ struct Ice40DspPass : public Pass { extra_args(args, argidx, design); for (auto module : design->selected_modules()) - xilinx_dsp_pm(module, module->selected_cells()).run_xilinx_dsp(create_xilinx_dsp); + xilinx_dsp_pm(module, module->selected_cells()).run_xilinx_dsp(pack_xilinx_dsp); } } Ice40DspPass; diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 6bb4e7bd8..ceed64b30 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,44 +1,36 @@ pattern xilinx_dsp state clock -state sigA sigB sigY sigS -state addAB muxAB +state P_WIDTH -match mul - select mul->type.in($__MUL25X18) +match dsp + select dsp->type.in(\DSP48E1) endmatch match ffA - select ffA->type.in($dff) /* TODO: $dffe */ + select ffA->type.in($dff, $dffe) // select nusers(port(ffA, \Q)) == 2 - index port(ffA, \Q) === port(mul, \A) + index port(ffA, \Q).extend_u0(30) === port(dsp, \A) // DSP48E1 does not support clock inversion - index port(ffA, \CLK_POLARITY) === State::S1 + index param(ffA, \CLK_POLARITY).as_bool() === true optional endmatch -code sigA clock - sigA = port(mul, \A); - - if (ffA) { - sigA = port(ffA, \D); +code clock + if (ffA) clock = port(ffA, \CLK).as_bit(); - } endcode match ffB - select ffB->type.in($dff) + select ffB->type.in($dff, $dffe) // select nusers(port(ffB, \Q)) == 2 - index port(ffB, \Q) === port(mul, \B) - index port(ffB, \CLK_POLARITY) === State::S1 + index port(ffB, \Q).extend_u0(18) === port(dsp, \B) + index param(ffB, \CLK_POLARITY).as_bool() === true optional endmatch -code sigB clock - sigB = port(mul, \B); - +code clock if (ffB) { - sigB = port(ffB, \D); SigBit c = port(ffB, \CLK).as_bit(); if (clock != SigBit() && c != clock) @@ -48,20 +40,51 @@ code sigB clock } endcode -match ffY - select ffY->type.in($dff) - select nusers(port(ffY, \D)) == 2 - index port(ffY, \D) === port(mul, \Y) - index port(ffY, \CLK_POLARITY) === State::S1 +code P_WIDTH + SigSpec P = port(dsp, \P); + int i; + for (i = GetSize(P); i > 0; i--) + if (nusers(P[i-1]) > 1) + break; + P_WIDTH = i; +endcode + +match ffP + select ffP->type.in($dff, $dffe) + select nusers(port(ffP, \D)) == 2 + filter param(ffP, \WIDTH).as_int() == P_WIDTH + filter port(ffP, \D) == port(dsp, \P).extract(0, P_WIDTH) + index param(ffP, \CLK_POLARITY) === State::S1 optional endmatch -code sigY clock - sigY = port(mul, \Y); +// $mux cell left behind by dff2dffe +// would prefer not to run 'opt_expr -mux_undef' +// since that would lose information helpful for +// efficient wide-mux inference +match muxP + if !ffP + select muxP->type.in($mux) + select port(muxP, \A).is_fully_undef() + filter param(muxP, \WIDTH).as_int() == P_WIDTH + filter port(muxP, \B) == port(dsp, \P).extract(0, P_WIDTH) + select nusers(port(muxP, \B)) == 2 + optional +endmatch - if (ffY) { - sigY = port(ffY, \Q); - SigBit c = port(ffY, \CLK).as_bit(); +match ffY + if muxP + select ffY->type.in($dff, $dffe) + select nusers(port(ffY, \D)) == 2 + index port(ffY, \D) === port(muxP, \Y) +endmatch + +code ffP clock + if (ffY) + ffP = ffY; + + if (ffP) { + SigBit c = port(ffP, \CLK).as_bit(); if (clock != SigBit() && c != clock) reject; From 6390c535ba70c0a4fe0cb08156fefa80fb621e47 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Jul 2019 14:30:25 -0700 Subject: [PATCH 021/356] Revert drop down to 24x16 multipliers for all --- techlibs/xilinx/dsp_map.v | 6 +++--- techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v index 2063c45e2..da1d6f3a9 100644 --- a/techlibs/xilinx/dsp_map.v +++ b/techlibs/xilinx/dsp_map.v @@ -1,4 +1,4 @@ -module \$__MUL25X18 (input [23:0] A, input [16:0] B, output [40:0] Y); +module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); wire [47:0] P_48; DSP48E1 #( // Disable all registers @@ -20,8 +20,8 @@ module \$__MUL25X18 (input [23:0] A, input [16:0] B, output [40:0] Y); .PREG(0) ) _TECHMAP_REPLACE_ ( //Data path - .A({6'b0, A}), - .B({1'b0, B}), + .A({5'b0, A}), + .B(B), .C(48'b0), .D(24'b0), .P(P_48), diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 815bf0848..bfce922db 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -289,7 +289,7 @@ struct SynthXilinxPass : public ScriptPass // unsigned multiply with MSBs set to 1'b0 if (!nodsp || help_mode) - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=24 -D DSP_B_MAXWIDTH=17 -D DSP_NAME=$__MUL25X18"); + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_A_SIGNEDONLY=1 -D DSP_B_MAXWIDTH=18 -D DSP_B_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); run("alumacc"); run("share"); From 3f677fb0db15f75d9655fe653f991c94e78a4a1f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Jul 2019 15:54:07 -0700 Subject: [PATCH 022/356] Signed extension --- passes/pmgen/xilinx_dsp.cc | 4 ++-- passes/pmgen/xilinx_dsp.pmg | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index a09f96a7f..a4602dd63 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -50,7 +50,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) if (st.ffA) { SigSpec D = st.ffA->getPort("\\D"); - cell->setPort("\\A", D.extend_u0(30)); + cell->setPort("\\A", D.extend_u0(30, true)); cell->setParam("\\AREG", State::S1); if (st.ffA->type == "$dff") cell->setPort("\\CEA2", State::S1); @@ -60,7 +60,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) } if (st.ffB) { SigSpec D = st.ffB->getPort("\\D"); - cell->setPort("\\B", D.extend_u0(18)); + cell->setPort("\\B", D.extend_u0(18, true)); cell->setParam("\\BREG", State::S1); if (st.ffB->type == "$dff") cell->setPort("\\CEB2", State::S1); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index ceed64b30..4b7bea308 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -9,10 +9,10 @@ endmatch match ffA select ffA->type.in($dff, $dffe) + select param(ffA, \CLK_POLARITY).as_bool() // select nusers(port(ffA, \Q)) == 2 - index port(ffA, \Q).extend_u0(30) === port(dsp, \A) + index port(ffA, \Q).extend_u0(25, true) === port(dsp, \A).extract(0, 25) // DSP48E1 does not support clock inversion - index param(ffA, \CLK_POLARITY).as_bool() === true optional endmatch @@ -23,9 +23,9 @@ endcode match ffB select ffB->type.in($dff, $dffe) + select param(ffB, \CLK_POLARITY).as_bool() // select nusers(port(ffB, \Q)) == 2 - index port(ffB, \Q).extend_u0(18) === port(dsp, \B) - index param(ffB, \CLK_POLARITY).as_bool() === true + index port(ffB, \Q).extend_u0(18, true) === port(dsp, \B) optional endmatch From c501aa5ee84c14f5b6aebe3052dabb1c314eb9e0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Jul 2019 15:54:27 -0700 Subject: [PATCH 023/356] Signedness --- techlibs/xilinx/cells_sim.v | 14 +++++++------- techlibs/xilinx/dsp_map.v | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 1262fc8c1..33b2a8f62 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -386,15 +386,15 @@ module DSP48E1 ( output [3:0] CARRYOUT, output MULTSIGNOUT, output OVERFLOW, - output reg [47:0] P, + output reg signed [47:0] P, output PATTERNBDETECT, output PATTERNDETECT, output [47:0] PCOUT, output UNDERFLOW, - input [29:0] A, + input signed [29:0] A, input [29:0] ACIN, input [3:0] ALUMODE, - input [17:0] B, + input signed [17:0] B, input [17:0] BCIN, input [47:0] C, input CARRYCASCIN, @@ -494,9 +494,9 @@ module DSP48E1 ( `endif end - reg [29:0] Ar; - reg [17:0] Br; - reg [47:0] Pr; + reg signed [29:0] Ar; + reg signed [17:0] Br; + reg signed [47:0] Pr; generate if (AREG == 1) begin always @(posedge CLK) if (CEA2) Ar <= A; end else always @* Ar <= A; @@ -516,7 +516,7 @@ module DSP48E1 ( if (PCIN != 48'b0) $fatal(1, "Unsupported PCIN value"); if (CARRYIN != 1'b0) $fatal(1, "Unsupported CARRYIN value"); `endif - Pr[42:0] <= $signed(Ar[24:0]) * $signed(Br); + Pr[42:0] <= $signed(Ar[24:0]) * Br; end generate diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v index da1d6f3a9..28e456898 100644 --- a/techlibs/xilinx/dsp_map.v +++ b/techlibs/xilinx/dsp_map.v @@ -20,7 +20,7 @@ module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); .PREG(0) ) _TECHMAP_REPLACE_ ( //Data path - .A({5'b0, A}), + .A({{5{A[24]}}, A}), .B(B), .C(48'b0), .D(24'b0), From 0b6d47f8bfe3117817398a7a84a2d93dd339335b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Jul 2019 15:55:13 -0700 Subject: [PATCH 024/356] Add DSP_{A,B}_SIGNEDONLY macro --- techlibs/common/mul2dsp.v | 51 ++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 6f2281c0a..258ddf021 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -3,24 +3,25 @@ // revised by Andre DeHon // further revised by David Shah `ifndef DSP_A_MAXWIDTH -`define DSP_A_MAXWIDTH 18 +$error("Macro DSP_A_MAXWIDTH must be defined"); `endif -`ifndef DSP_A_MAXWIDTH -`define DSP_B_MAXWIDTH 25 +`ifndef DSP_A_SIGNEDONLY +`define DSP_A_SIGNEDONLY 0 `endif - -`ifndef ADDER_MINWIDTH -`define ADDER_MINWIDTH AAA +`ifndef DSP_B_MAXWIDTH +$error("Macro DSP_B_MAXWIDTH must be defined"); +`endif +`ifndef DSP_B_SIGNEDONLY +`define DSP_B_SIGNEDONLY 0 `endif `ifndef DSP_NAME -`define DSP_NAME M18x25 +$error("Macro DSP_NAME must be defined"); `endif `define MAX(a,b) (a > b ? a : b) `define MIN(a,b) (a < b ? a : b) -(* techmap_celltype = "$mul" *) module \$mul (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -33,14 +34,42 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - if (A_WIDTH >= B_WIDTH) + if (`DSP_A_SIGNEDONLY && !A_SIGNED) begin + wire dummy; + \$mul #( + .A_SIGNED(1), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH+1), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH+1) + ) _TECHMAP_REPLACE_ ( + .A({1'b0, A}), + .B(B), + .Y({dummy, Y}) + ); + end + else if (`DSP_B_SIGNEDONLY && !B_SIGNED) begin + wire dummy; + \$mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(1), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH+1), + .Y_WIDTH(Y_WIDTH+1) + ) _TECHMAP_REPLACE_ ( + .A(A), + .B({1'b0, B}), + .Y({dummy, Y}) + ); + end + else if (A_WIDTH >= B_WIDTH) \$__mul_gen #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH) - ) mul_slice ( + ) _TECHMAP_REPLACE_ ( .A(A), .B(B), .Y(Y) @@ -52,7 +81,7 @@ module \$mul (A, B, Y); .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH) - ) mul_slice ( + ) _TECHMAP_REPLACE_ ( .A(B), .B(A), .Y(Y) From d63f1057083d625d4317da2b6934d0531129d961 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Jul 2019 10:44:11 -0700 Subject: [PATCH 025/356] SigSpec::remove_const() to return SigSpec& --- kernel/rtlil.cc | 3 ++- kernel/rtlil.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 6f5082138..5d992ef2d 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3297,7 +3297,7 @@ void RTLIL::SigSpec::replace(int offset, const RTLIL::SigSpec &with) check(); } -void RTLIL::SigSpec::remove_const() +RTLIL::SigSpec& RTLIL::SigSpec::remove_const() { if (packed()) { @@ -3331,6 +3331,7 @@ void RTLIL::SigSpec::remove_const() } check(); + return *this; } void RTLIL::SigSpec::remove(int offset, int length) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 8d88cc97c..b484f5306 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -767,7 +767,7 @@ public: void remove2(const std::set &pattern, RTLIL::SigSpec *other); void remove(int offset, int length = 1); - void remove_const(); + RTLIL::SigSpec& remove_const(); RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; RTLIL::SigSpec extract(const pool &pattern, const RTLIL::SigSpec *other = NULL) const; From 1b62b82e05ef5405d8ddff211f623d90d848a9ca Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Jul 2019 11:34:18 -0700 Subject: [PATCH 026/356] A_SIGNED == B_SIGNED so flip both --- techlibs/common/mul2dsp.v | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 258ddf021..d19599620 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -34,31 +34,22 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - if (`DSP_A_SIGNEDONLY && !A_SIGNED) begin - wire dummy; + localparam add_sign_A = `DSP_A_SIGNEDONLY && !A_SIGNED; + localparam add_sign_B = `DSP_B_SIGNEDONLY && !B_SIGNED; + if (add_sign_A || add_sign_B) begin + if (add_sign_A && add_sign_B) + wire [1:0] dummy; + else + wire dummy; \$mul #( .A_SIGNED(1), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH+1), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH+1) - ) _TECHMAP_REPLACE_ ( - .A({1'b0, A}), - .B(B), - .Y({dummy, Y}) - ); - end - else if (`DSP_B_SIGNEDONLY && !B_SIGNED) begin - wire dummy; - \$mul #( - .A_SIGNED(A_SIGNED), .B_SIGNED(1), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH+1), - .Y_WIDTH(Y_WIDTH+1) + .A_WIDTH(A_WIDTH + (add_sign_A ? 1 : 0)), + .B_WIDTH(B_WIDTH + (add_sign_B ? 1 : 0)), + .Y_WIDTH(Y_WIDTH + (add_sign_A ? 1 : 0) + (add_sign_B ? 1 : 0)) ) _TECHMAP_REPLACE_ ( - .A(A), - .B({1'b0, B}), + .A(add_sign_A ? {1'b0, A} : A), + .B(add_sign_B ? {1'b0, B} : B), .Y({dummy, Y}) ); end From 8dca8d486e945eb5883e6757f711011ed23aa5ba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Jul 2019 12:44:52 -0700 Subject: [PATCH 027/356] Fix mul2dsp signedness --- techlibs/common/mul2dsp.v | 80 +++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index d19599620..7344bc5fe 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -34,49 +34,45 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - localparam add_sign_A = `DSP_A_SIGNEDONLY && !A_SIGNED; - localparam add_sign_B = `DSP_B_SIGNEDONLY && !B_SIGNED; - if (add_sign_A || add_sign_B) begin - if (add_sign_A && add_sign_B) - wire [1:0] dummy; - else - wire dummy; - \$mul #( - .A_SIGNED(1), - .B_SIGNED(1), - .A_WIDTH(A_WIDTH + (add_sign_A ? 1 : 0)), - .B_WIDTH(B_WIDTH + (add_sign_B ? 1 : 0)), - .Y_WIDTH(Y_WIDTH + (add_sign_A ? 1 : 0) + (add_sign_B ? 1 : 0)) - ) _TECHMAP_REPLACE_ ( - .A(add_sign_A ? {1'b0, A} : A), - .B(add_sign_B ? {1'b0, B} : B), - .Y({dummy, Y}) - ); + if (`DSP_A_SIGNEDONLY && `DSP_B_SIGNEDONLY && !A_SIGNED) begin + wire [1:0] dummy; + \$mul #( + .A_SIGNED(1), + .B_SIGNED(1), + .A_WIDTH(A_WIDTH + 1), + .B_WIDTH(B_WIDTH + 1), + .Y_WIDTH(Y_WIDTH + 2) + ) _TECHMAP_REPLACE_ ( + .A({1'b0, A}), + .B({1'b0, B}), + .Y({dummy, Y}) + ); end - else if (A_WIDTH >= B_WIDTH) - \$__mul_gen #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(A), - .B(B), - .Y(Y) - ); - else - \$__mul_gen #( - .A_SIGNED(B_SIGNED), - .B_SIGNED(A_SIGNED), - .A_WIDTH(B_WIDTH), - .B_WIDTH(A_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(B), - .B(A), - .Y(Y) - ); + // NB: A_SIGNED == B_SIGNED == 0 from here + else if (A_WIDTH >= B_WIDTH) + \$__mul_gen #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A), + .B(B), + .Y(Y) + ); + else + \$__mul_gen #( + .A_SIGNED(B_SIGNED), + .B_SIGNED(A_SIGNED), + .A_WIDTH(B_WIDTH), + .B_WIDTH(A_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(B), + .B(A), + .Y(Y) + ); endgenerate endmodule From 91629ee4b3aae3aa8243a659ffe1716ad5c432a2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Jul 2019 12:45:25 -0700 Subject: [PATCH 028/356] Pattern matcher to check pool of bits, not exactly --- passes/pmgen/xilinx_dsp.cc | 12 +++++++++--- passes/pmgen/xilinx_dsp.pmg | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index a4602dd63..bd04cc40b 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -49,8 +49,11 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) cell->setPort("\\CLK", st.clock); if (st.ffA) { + SigSpec A = cell->getPort("\\A"); SigSpec D = st.ffA->getPort("\\D"); - cell->setPort("\\A", D.extend_u0(30, true)); + SigSpec Q = st.ffA->getPort("\\Q"); + A.replace(Q, D); + cell->setPort("\\A", A); cell->setParam("\\AREG", State::S1); if (st.ffA->type == "$dff") cell->setPort("\\CEA2", State::S1); @@ -59,8 +62,11 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) else log_abort(); } if (st.ffB) { + SigSpec B = cell->getPort("\\B"); SigSpec D = st.ffB->getPort("\\D"); - cell->setPort("\\B", D.extend_u0(18, true)); + SigSpec Q = st.ffB->getPort("\\Q"); + B.replace(Q, D); + cell->setPort("\\B", B); cell->setParam("\\BREG", State::S1); if (st.ffB->type == "$dff") cell->setPort("\\CEB2", State::S1); @@ -71,7 +77,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) if (st.ffP) { SigSpec P = cell->getPort("\\P"); SigSpec Q = st.ffP->getPort("\\Q"); - Q.append(P.extract(GetSize(Q), -1)); + P.replace(Q, P.extract(0, GetSize(Q))); cell->setPort("\\P", Q); cell->setParam("\\PREG", State::S1); if (st.ffP->type == "$dff") diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 4b7bea308..60e972615 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -11,7 +11,7 @@ match ffA select ffA->type.in($dff, $dffe) select param(ffA, \CLK_POLARITY).as_bool() // select nusers(port(ffA, \Q)) == 2 - index port(ffA, \Q).extend_u0(25, true) === port(dsp, \A).extract(0, 25) + index port(ffA, \Q).to_sigbit_pool() === port(dsp, \A).remove_const().to_sigbit_pool() // DSP48E1 does not support clock inversion optional endmatch @@ -25,7 +25,7 @@ match ffB select ffB->type.in($dff, $dffe) select param(ffB, \CLK_POLARITY).as_bool() // select nusers(port(ffB, \Q)) == 2 - index port(ffB, \Q).extend_u0(18, true) === port(dsp, \B) + index port(ffB, \Q).to_sigbit_pool() === port(dsp, \B).remove_const().to_sigbit_pool() optional endmatch From 58e63feae1e950fff839c4261a787d5daf07612e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Jul 2019 13:26:17 -0700 Subject: [PATCH 029/356] Update comment --- techlibs/xilinx/synth_xilinx.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index bfce922db..2e2fbbd9d 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -284,12 +284,10 @@ struct SynthXilinxPass : public ScriptPass run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); - // The actual behaviour of the Xilinx DSP is a signed 25x18 multiply - // Due to current limitations of mul2dsp, we are actually mapping as a 24x17 - // unsigned multiply with MSBs set to 1'b0 - - if (!nodsp || help_mode) + if (!nodsp || help_mode) { + // NB: Xilinx multipliers are signed only run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_A_SIGNEDONLY=1 -D DSP_B_MAXWIDTH=18 -D DSP_B_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); + } run("alumacc"); run("share"); From e3f8e59f182129aa2ff9ba7a1ed7fbbaab657ce5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Jul 2019 14:25:40 -0700 Subject: [PATCH 030/356] Make all operands signed --- techlibs/xilinx/dsp_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v index 28e456898..32f570935 100644 --- a/techlibs/xilinx/dsp_map.v +++ b/techlibs/xilinx/dsp_map.v @@ -1,4 +1,4 @@ -module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); +module \$__MUL25X18 (input signed [24:0] A, input signed [17:0] B, output signed [42:0] Y); wire [47:0] P_48; DSP48E1 #( // Disable all registers From 16b0ccf04ca83d76f9bd182e125dd75fa838753a Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 18 Jul 2019 11:33:37 +0100 Subject: [PATCH 031/356] mul2dsp: Lower partial products always have unsigned inputs Signed-off-by: David Shah --- techlibs/common/mul2dsp.v | 72 ++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 7344bc5fe..31469ddeb 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -92,20 +92,25 @@ module \$__mul_gen (A, B, Y); genvar i; generate if (A_WIDTH > `DSP_A_MAXWIDTH) begin - localparam n_floored = A_WIDTH/`DSP_A_MAXWIDTH; - localparam n = n_floored + (n_floored*`DSP_A_MAXWIDTH < A_WIDTH ? 1 : 0); +`ifdef DSP_A_SIGNEDONLY + localparam sign_headroom = 1; +`else + localparam sign_headroom = 0; +`endif + localparam n_floored = A_WIDTH/(`DSP_A_MAXWIDTH - sign_headroom); + localparam n = n_floored + (n_floored*(`DSP_A_MAXWIDTH - sign_headroom) < A_WIDTH ? 1 : 0); wire [`DSP_A_MAXWIDTH+B_WIDTH-1:0] partial [n-1:1]; wire [Y_WIDTH-1:0] partial_sum [n-2:0]; localparam int_yw = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH); \$__mul_gen #( - .A_SIGNED(A_SIGNED), + .A_SIGNED(0), .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(int_yw) ) mul_slice_first ( - .A(A[`DSP_A_MAXWIDTH-1:0]), + .A({{sign_headroom{1'b0}}, A[`DSP_A_MAXWIDTH-sign_headroom-1:0]}), .B(B), .Y(partial_sum[0][int_yw-1:0]) ); @@ -114,73 +119,78 @@ module \$__mul_gen (A, B, Y); for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( - .A_SIGNED(A_SIGNED), + .A_SIGNED(0), .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(int_yw) ) mul_slice ( - .A(A[(i+1)*`DSP_A_MAXWIDTH-1:i*`DSP_A_MAXWIDTH]), + .A({{sign_headroom{1'b0}}, A[(i+1)*(`DSP_A_MAXWIDTH-sign_headroom)-1:i*(`DSP_A_MAXWIDTH-sign_headroom)]}), .B(B), .Y(partial[i][int_yw-1:0]) ); //assign partial_sum[i] = (partial[i] << i*`DSP_A_MAXWIDTH) + partial_sum[i-1]; assign partial_sum[i] = { partial[i][int_yw-1:0] - + partial_sum[i-1][Y_WIDTH-1:(i*`DSP_A_MAXWIDTH)], - partial_sum[i-1][(i*`DSP_A_MAXWIDTH)-1:0] + + partial_sum[i-1][Y_WIDTH-1:(i*(`DSP_A_MAXWIDTH-sign_headroom))], + partial_sum[i-1][(i*(`DSP_A_MAXWIDTH-sign_headroom))-1:0] }; end \$__mul_gen #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH-(n-1)*`DSP_A_MAXWIDTH), + .A_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)), .B_WIDTH(B_WIDTH), - .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH)), + .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH)), ) mul_slice_last ( - .A(A[A_WIDTH-1:(n-1)*`DSP_A_MAXWIDTH]), + .A(A[A_WIDTH-1:(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)]), .B(B), - .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH)-1:0]) + .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH)-1:0]) ); //assign Y = (partial[n-1] << (n-1)*`DSP_A_MAXWIDTH) + partial_sum[n-2]; assign Y = { - partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH):0] - + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_A_MAXWIDTH)], - partial_sum[n-2][((n-1)*`DSP_A_MAXWIDTH)-1:0] + partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH):0] + + partial_sum[n-2][Y_WIDTH-1:((n-1)*(`DSP_A_MAXWIDTH-sign_headroom))], + partial_sum[n-2][((n-1)*(`DSP_A_MAXWIDTH-sign_headroom))-1:0] }; end else if (B_WIDTH > `DSP_B_MAXWIDTH) begin - localparam n_floored = B_WIDTH/`DSP_B_MAXWIDTH; - localparam n = n_floored + (n_floored*`DSP_B_MAXWIDTH < B_WIDTH ? 1 : 0); +`ifdef DSP_B_SIGNEDONLY + localparam sign_headroom = 1; +`else + localparam sign_headroom = 0; +`endif + localparam n_floored = B_WIDTH/(`DSP_B_MAXWIDTH - sign_headroom); + localparam n = n_floored + (n_floored*(`DSP_B_MAXWIDTH - sign_headroom) < B_WIDTH ? 1 : 0); wire [A_WIDTH+`DSP_B_MAXWIDTH-1:0] partial [n-1:1]; wire [Y_WIDTH-1:0] partial_sum [n-2:0]; localparam int_yw = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH); \$__mul_gen #( .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), + .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH), .Y_WIDTH(int_yw) ) mul_first ( .A(A), - .B(B[`DSP_B_MAXWIDTH-1:0]), + .B({{sign_headroom{1'b0}}, B[(`DSP_B_MAXWIDTH - sign_headroom)-1:0]}), .Y(partial_sum[0][int_yw-1:0]) ); if (Y_WIDTH > int_yw) - assign partial_sum[0][Y_WIDTH-1:A_WIDTH+`DSP_B_MAXWIDTH]=0; + assign partial_sum[0][Y_WIDTH-1:int_yw]=0; for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), + .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH), .Y_WIDTH(int_yw) ) mul ( .A(A), - .B(B[(i+1)*`DSP_B_MAXWIDTH-1:i*`DSP_B_MAXWIDTH]), + .B({{sign_headroom{1'b0}}, B[(i+1)*(`DSP_B_MAXWIDTH - sign_headroom)-1:i*(`DSP_B_MAXWIDTH - sign_headroom)]}), .Y(partial[i][int_yw-1:0]) ); //assign partial_sum[i] = (partial[i] << i*`DSP_B_MAXWIDTH) + partial_sum[i-1]; @@ -191,8 +201,8 @@ module \$__mul_gen (A, B, Y); // partial_sum[i-1][A_WIDTH+((i-1)*`DSP_B_MAXWIDTH):0] assign partial_sum[i] = { partial[i][int_yw-1:0] - + partial_sum[i-1][Y_WIDTH-1:(i*`DSP_B_MAXWIDTH)], - partial_sum[i-1][(i*`DSP_B_MAXWIDTH)-1:0] + + partial_sum[i-1][Y_WIDTH-1:(i*(`DSP_B_MAXWIDTH - sign_headroom))], + partial_sum[i-1][(i*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] }; end @@ -200,12 +210,12 @@ module \$__mul_gen (A, B, Y); .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH-(n-1)*`DSP_B_MAXWIDTH), - .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH)) + .B_WIDTH(B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)), + .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))) ) mul_last ( .A(A), - .B(B[B_WIDTH-1:(n-1)*`DSP_B_MAXWIDTH]), - .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH)-1:0]) + .B(B[B_WIDTH-1:(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)]), + .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0]) ); // AMD: this came comment out -- looks closer to right answer //assign Y = (partial[n-1] << (n-1)*`DSP_B_MAXWIDTH) + partial_sum[n-2]; @@ -215,9 +225,9 @@ module \$__mul_gen (A, B, Y); // partial[n-1][`DSP_B_MAXWIDTH-1:0] + partial_sum[n-2][A_WIDTH+((n-1)*`DSP_B_MAXWIDTH)-1:A_WIDTH+((n-2)*`DSP_B_MAXWIDTH)], // partial_sum[n-2][A_WIDTH+((n-2)*`DSP_B_MAXWIDTH):0] assign Y = { - partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH)-1:0] - + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_B_MAXWIDTH)], - partial_sum[n-2][((n-1)*`DSP_B_MAXWIDTH)-1:0] + partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] + + partial_sum[n-2][Y_WIDTH-1:((n-1)*(`DSP_B_MAXWIDTH - sign_headroom))], + partial_sum[n-2][((n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] }; end else begin From c76607b9bcb2d90fce81ff71e37cc05d21facde4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 08:14:58 -0700 Subject: [PATCH 032/356] Wrong wildcard symbol --- passes/pmgen/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/.gitignore b/passes/pmgen/.gitignore index 10e245e00..e52f3282f 100644 --- a/passes/pmgen/.gitignore +++ b/passes/pmgen/.gitignore @@ -1 +1 @@ -/%_pm.h +/*_pm.h From d5cd2c80be95857cfd30d50081d6c87415e9169a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 09:20:48 -0700 Subject: [PATCH 033/356] Cleanup --- techlibs/common/mul2dsp.v | 128 +++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 70 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 31469ddeb..9da778ace 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -97,25 +97,23 @@ module \$__mul_gen (A, B, Y); `else localparam sign_headroom = 0; `endif - localparam n_floored = A_WIDTH/(`DSP_A_MAXWIDTH - sign_headroom); - localparam n = n_floored + (n_floored*(`DSP_A_MAXWIDTH - sign_headroom) < A_WIDTH ? 1 : 0); - wire [`DSP_A_MAXWIDTH+B_WIDTH-1:0] partial [n-1:1]; + localparam n = (A_WIDTH + `DSP_A_MAXWIDTH - sign_headroom - 1)/(`DSP_A_MAXWIDTH - sign_headroom); + localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH); + wire [partial_Y_WIDTH-1:0] partial [n-1:1]; wire [Y_WIDTH-1:0] partial_sum [n-2:0]; - localparam int_yw = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH); \$__mul_gen #( .A_SIGNED(0), .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), - .Y_WIDTH(int_yw) + .Y_WIDTH(partial_Y_WIDTH) ) mul_slice_first ( .A({{sign_headroom{1'b0}}, A[`DSP_A_MAXWIDTH-sign_headroom-1:0]}), .B(B), - .Y(partial_sum[0][int_yw-1:0]) + .Y(partial[0]) ); - if (Y_WIDTH > int_yw) - assign partial_sum[0][Y_WIDTH-1:int_yw]=0; + assign partial_sum[0] = partial[0]; for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( @@ -123,18 +121,18 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), - .Y_WIDTH(int_yw) + .Y_WIDTH(partial_Y_WIDTH) ) mul_slice ( - .A({{sign_headroom{1'b0}}, A[(i+1)*(`DSP_A_MAXWIDTH-sign_headroom)-1:i*(`DSP_A_MAXWIDTH-sign_headroom)]}), + .A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH-sign_headroom) +: `DSP_A_MAXWIDTH-sign_headroom]}), .B(B), - .Y(partial[i][int_yw-1:0]) + .Y(partial[i]) ); - //assign partial_sum[i] = (partial[i] << i*`DSP_A_MAXWIDTH) + partial_sum[i-1]; - assign partial_sum[i] = { - partial[i][int_yw-1:0] - + partial_sum[i-1][Y_WIDTH-1:(i*(`DSP_A_MAXWIDTH-sign_headroom))], - partial_sum[i-1][(i*(`DSP_A_MAXWIDTH-sign_headroom))-1:0] - }; + assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; + //assign partial_sum[i] = { + // partial[i][partial_Y_WIDTH-1:0] + // + partial_sum[i-1][Y_WIDTH-1:(i*(`DSP_A_MAXWIDTH-sign_headroom))], + // partial_sum[i-1][(i*(`DSP_A_MAXWIDTH-sign_headroom))-1:0] + //}; end \$__mul_gen #( @@ -148,12 +146,12 @@ module \$__mul_gen (A, B, Y); .B(B), .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH)-1:0]) ); - //assign Y = (partial[n-1] << (n-1)*`DSP_A_MAXWIDTH) + partial_sum[n-2]; - assign Y = { - partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH):0] - + partial_sum[n-2][Y_WIDTH-1:((n-1)*(`DSP_A_MAXWIDTH-sign_headroom))], - partial_sum[n-2][((n-1)*(`DSP_A_MAXWIDTH-sign_headroom))-1:0] - }; + assign Y = (partial[n-1] << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; + //assign Y = { + // partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH):0] + // + partial_sum[n-2][Y_WIDTH-1:((n-1)*(`DSP_A_MAXWIDTH-sign_headroom))], + // partial_sum[n-2][((n-1)*(`DSP_A_MAXWIDTH-sign_headroom))-1:0] + //}; end else if (B_WIDTH > `DSP_B_MAXWIDTH) begin `ifdef DSP_B_SIGNEDONLY @@ -161,25 +159,23 @@ module \$__mul_gen (A, B, Y); `else localparam sign_headroom = 0; `endif - localparam n_floored = B_WIDTH/(`DSP_B_MAXWIDTH - sign_headroom); - localparam n = n_floored + (n_floored*(`DSP_B_MAXWIDTH - sign_headroom) < B_WIDTH ? 1 : 0); - wire [A_WIDTH+`DSP_B_MAXWIDTH-1:0] partial [n-1:1]; + localparam n = (B_WIDTH + `DSP_B_MAXWIDTH - sign_headroom - 1)/(`DSP_B_MAXWIDTH - sign_headroom); + localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH); + wire [partial_Y_WIDTH-1:0] partial [n-1:1]; wire [Y_WIDTH-1:0] partial_sum [n-2:0]; - localparam int_yw = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH); \$__mul_gen #( .A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH), - .Y_WIDTH(int_yw) + .Y_WIDTH(partial_Y_WIDTH) ) mul_first ( .A(A), - .B({{sign_headroom{1'b0}}, B[(`DSP_B_MAXWIDTH - sign_headroom)-1:0]}), - .Y(partial_sum[0][int_yw-1:0]) + .B({{sign_headroom{1'b0}}, B[`DSP_B_MAXWIDTH-sign_headroom-1:0]}), + .Y(partial[0]) ); - if (Y_WIDTH > int_yw) - assign partial_sum[0][Y_WIDTH-1:int_yw]=0; + assign partial_sum[0] = partial[0]; for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( @@ -187,23 +183,23 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH), - .Y_WIDTH(int_yw) + .Y_WIDTH(partial_Y_WIDTH) ) mul ( .A(A), - .B({{sign_headroom{1'b0}}, B[(i+1)*(`DSP_B_MAXWIDTH - sign_headroom)-1:i*(`DSP_B_MAXWIDTH - sign_headroom)]}), - .Y(partial[i][int_yw-1:0]) + .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH-sign_headroom) +: `DSP_B_MAXWIDTH-sign_headroom]}), + .Y(partial[i]) ); - //assign partial_sum[i] = (partial[i] << i*`DSP_B_MAXWIDTH) + partial_sum[i-1]; - // was: + assign partial_sum[i] = (partial[i] <<< i*(`DSP_B_MAXWIDTH - sign_headroom)) + partial_sum[i-1]; + //// was: + ////assign partial_sum[i] = { + //// partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH], + //// partial[i][`DSP_B_MAXWIDTH-1:0] + partial_sum[i-1][A_WIDTH+(i*`DSP_B_MAXWIDTH)-1:A_WIDTH+((i-1)*`DSP_B_MAXWIDTH)], + //// partial_sum[i-1][A_WIDTH+((i-1)*`DSP_B_MAXWIDTH):0] //assign partial_sum[i] = { - // partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH], - // partial[i][`DSP_B_MAXWIDTH-1:0] + partial_sum[i-1][A_WIDTH+(i*`DSP_B_MAXWIDTH)-1:A_WIDTH+((i-1)*`DSP_B_MAXWIDTH)], - // partial_sum[i-1][A_WIDTH+((i-1)*`DSP_B_MAXWIDTH):0] - assign partial_sum[i] = { - partial[i][int_yw-1:0] - + partial_sum[i-1][Y_WIDTH-1:(i*(`DSP_B_MAXWIDTH - sign_headroom))], - partial_sum[i-1][(i*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] - }; + // partial[i][partial_Y_WIDTH-1:0] + // + partial_sum[i-1][Y_WIDTH-1:(i*(`DSP_B_MAXWIDTH - sign_headroom))], + // partial_sum[i-1][(i*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] + //}; end \$__mul_gen #( @@ -217,36 +213,28 @@ module \$__mul_gen (A, B, Y); .B(B[B_WIDTH-1:(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)]), .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0]) ); - // AMD: this came comment out -- looks closer to right answer - //assign Y = (partial[n-1] << (n-1)*`DSP_B_MAXWIDTH) + partial_sum[n-2]; - // was (looks broken) + assign Y = (partial[n-1] << (n-1)*(`DSP_B_MAXWIDTH - sign_headroom)) + partial_sum[n-2]; + //// was (looks broken) + ////assign Y = { + //// partial[n-1][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH], + //// partial[n-1][`DSP_B_MAXWIDTH-1:0] + partial_sum[n-2][A_WIDTH+((n-1)*`DSP_B_MAXWIDTH)-1:A_WIDTH+((n-2)*`DSP_B_MAXWIDTH)], + //// partial_sum[n-2][A_WIDTH+((n-2)*`DSP_B_MAXWIDTH):0] //assign Y = { - // partial[n-1][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH], - // partial[n-1][`DSP_B_MAXWIDTH-1:0] + partial_sum[n-2][A_WIDTH+((n-1)*`DSP_B_MAXWIDTH)-1:A_WIDTH+((n-2)*`DSP_B_MAXWIDTH)], - // partial_sum[n-2][A_WIDTH+((n-2)*`DSP_B_MAXWIDTH):0] - assign Y = { - partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] - + partial_sum[n-2][Y_WIDTH-1:((n-1)*(`DSP_B_MAXWIDTH - sign_headroom))], - partial_sum[n-2][((n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] - }; + // partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] + // + partial_sum[n-2][Y_WIDTH-1:((n-1)*(`DSP_B_MAXWIDTH - sign_headroom))], + // partial_sum[n-2][((n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] + //}; end else begin - wire [A_WIDTH+B_WIDTH-1:0] out; - wire [(`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH)-(A_WIDTH+B_WIDTH)-1:0] dummy; - wire Asign, Bsign; - assign Asign = (A_SIGNED ? A[A_WIDTH-1] : 1'b0); - assign Bsign = (B_SIGNED ? B[B_WIDTH-1] : 1'b0); + (* keep *) wire [Y_WIDTH-1:0] Yunsigned; + wire signed [`DSP_A_MAXWIDTH-1:0] Asigned = $signed(A); + wire signed [`DSP_A_MAXWIDTH-1:0] Bsigned = $signed(B); `DSP_NAME _TECHMAP_REPLACE_ ( - .A({ {{`DSP_A_MAXWIDTH-A_WIDTH}{Asign}}, A }), - .B({ {{`DSP_B_MAXWIDTH-B_WIDTH}{Bsign}}, B }), - .Y({dummy, out}) + .A(Asigned), + .B(Bsigned), + .Y(Yunsigned) ); - if (Y_WIDTH < A_WIDTH+B_WIDTH) - assign Y = out[Y_WIDTH-1:0]; - else begin - wire Ysign = (A_SIGNED || B_SIGNED ? out[A_WIDTH+B_WIDTH-1] : 1'b0); - assign Y = { {{Y_WIDTH-(A_WIDTH+B_WIDTH)}{Ysign}}, out[A_WIDTH+B_WIDTH-1:0] }; - end + assign Y = $signed(Yunsigned[A_WIDTH+B_WIDTH-1:0]); end endgenerate endmodule From 2024357f32b3a5ee562501f66b16c30d9554aa4b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 10:53:18 -0700 Subject: [PATCH 034/356] Working for unsigned --- techlibs/common/mul2dsp.v | 80 ++++++++++++++------------------------- 1 file changed, 28 insertions(+), 52 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 9da778ace..4af3b871b 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -34,7 +34,7 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - if (`DSP_A_SIGNEDONLY && `DSP_B_SIGNEDONLY && !A_SIGNED) begin + if (`DSP_SIGNEDONLY && !A_SIGNED) begin wire [1:0] dummy; \$mul #( .A_SIGNED(1), @@ -89,22 +89,23 @@ module \$__mul_gen (A, B, Y); wire [1023:0] _TECHMAP_DO_ = "proc; clean"; +`ifdef DSP_SIGNEDONLY + localparam sign_headroom = 1; +`else + localparam sign_headroom = 0; +`endif + genvar i; generate if (A_WIDTH > `DSP_A_MAXWIDTH) begin -`ifdef DSP_A_SIGNEDONLY - localparam sign_headroom = 1; -`else - localparam sign_headroom = 0; -`endif localparam n = (A_WIDTH + `DSP_A_MAXWIDTH - sign_headroom - 1)/(`DSP_A_MAXWIDTH - sign_headroom); localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH); wire [partial_Y_WIDTH-1:0] partial [n-1:1]; - wire [Y_WIDTH-1:0] partial_sum [n-2:0]; + wire [Y_WIDTH-1:0] partial_sum [n-1:0]; \$__mul_gen #( .A_SIGNED(0), - .B_SIGNED(B_SIGNED), + .B_SIGNED(0), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(partial_Y_WIDTH) @@ -118,7 +119,7 @@ module \$__mul_gen (A, B, Y); for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( .A_SIGNED(0), - .B_SIGNED(B_SIGNED), + .B_SIGNED(0), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(partial_Y_WIDTH) @@ -128,11 +129,6 @@ module \$__mul_gen (A, B, Y); .Y(partial[i]) ); assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; - //assign partial_sum[i] = { - // partial[i][partial_Y_WIDTH-1:0] - // + partial_sum[i-1][Y_WIDTH-1:(i*(`DSP_A_MAXWIDTH-sign_headroom))], - // partial_sum[i-1][(i*(`DSP_A_MAXWIDTH-sign_headroom))-1:0] - //}; end \$__mul_gen #( @@ -140,18 +136,13 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)), .B_WIDTH(B_WIDTH), - .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH)), + .Y_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom) + B_WIDTH), ) mul_slice_last ( .A(A[A_WIDTH-1:(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)]), .B(B), - .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH)-1:0]) + .Y(partial[n-1]) ); assign Y = (partial[n-1] << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; - //assign Y = { - // partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH):0] - // + partial_sum[n-2][Y_WIDTH-1:((n-1)*(`DSP_A_MAXWIDTH-sign_headroom))], - // partial_sum[n-2][((n-1)*(`DSP_A_MAXWIDTH-sign_headroom))-1:0] - //}; end else if (B_WIDTH > `DSP_B_MAXWIDTH) begin `ifdef DSP_B_SIGNEDONLY @@ -162,7 +153,7 @@ module \$__mul_gen (A, B, Y); localparam n = (B_WIDTH + `DSP_B_MAXWIDTH - sign_headroom - 1)/(`DSP_B_MAXWIDTH - sign_headroom); localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH); wire [partial_Y_WIDTH-1:0] partial [n-1:1]; - wire [Y_WIDTH-1:0] partial_sum [n-2:0]; + wire [Y_WIDTH-1:0] partial_sum [n-1:0]; \$__mul_gen #( .A_SIGNED(A_SIGNED), @@ -189,17 +180,7 @@ module \$__mul_gen (A, B, Y); .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH-sign_headroom) +: `DSP_B_MAXWIDTH-sign_headroom]}), .Y(partial[i]) ); - assign partial_sum[i] = (partial[i] <<< i*(`DSP_B_MAXWIDTH - sign_headroom)) + partial_sum[i-1]; - //// was: - ////assign partial_sum[i] = { - //// partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH], - //// partial[i][`DSP_B_MAXWIDTH-1:0] + partial_sum[i-1][A_WIDTH+(i*`DSP_B_MAXWIDTH)-1:A_WIDTH+((i-1)*`DSP_B_MAXWIDTH)], - //// partial_sum[i-1][A_WIDTH+((i-1)*`DSP_B_MAXWIDTH):0] - //assign partial_sum[i] = { - // partial[i][partial_Y_WIDTH-1:0] - // + partial_sum[i-1][Y_WIDTH-1:(i*(`DSP_B_MAXWIDTH - sign_headroom))], - // partial_sum[i-1][(i*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] - //}; + assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH - sign_headroom)) + partial_sum[i-1]; end \$__mul_gen #( @@ -207,34 +188,29 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)), - .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))) + .Y_WIDTH(A_WIDTH + B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)) ) mul_last ( .A(A), .B(B[B_WIDTH-1:(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)]), - .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0]) + .Y(partial[n-1]) ); assign Y = (partial[n-1] << (n-1)*(`DSP_B_MAXWIDTH - sign_headroom)) + partial_sum[n-2]; - //// was (looks broken) - ////assign Y = { - //// partial[n-1][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH], - //// partial[n-1][`DSP_B_MAXWIDTH-1:0] + partial_sum[n-2][A_WIDTH+((n-1)*`DSP_B_MAXWIDTH)-1:A_WIDTH+((n-2)*`DSP_B_MAXWIDTH)], - //// partial_sum[n-2][A_WIDTH+((n-2)*`DSP_B_MAXWIDTH):0] - //assign Y = { - // partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] - // + partial_sum[n-2][Y_WIDTH-1:((n-1)*(`DSP_B_MAXWIDTH - sign_headroom))], - // partial_sum[n-2][((n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] - //}; end else begin - (* keep *) wire [Y_WIDTH-1:0] Yunsigned; - wire signed [`DSP_A_MAXWIDTH-1:0] Asigned = $signed(A); - wire signed [`DSP_A_MAXWIDTH-1:0] Bsigned = $signed(B); + if (A_SIGNED) + wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A); + else + wire [`DSP_A_MAXWIDTH-1:0] Aext = A; + if (B_SIGNED) + wire signed [`DSP_B_MAXWIDTH-1:0] Bext = $signed(B); + else + wire [`DSP_B_MAXWIDTH-1:0] Bext = B; + `DSP_NAME _TECHMAP_REPLACE_ ( - .A(Asigned), - .B(Bsigned), - .Y(Yunsigned) + .A(Aext), + .B(Bext), + .Y(Y) ); - assign Y = $signed(Yunsigned[A_WIDTH+B_WIDTH-1:0]); end endgenerate endmodule From 5562cb08a47881bee30bf79f8ca720b997166b2f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 13:09:55 -0700 Subject: [PATCH 035/356] Use single DSP_SIGNEDONLY macro --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 2e2fbbd9d..e5a27015a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -286,7 +286,7 @@ struct SynthXilinxPass : public ScriptPass if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_A_SIGNEDONLY=1 -D DSP_B_MAXWIDTH=18 -D DSP_B_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); } run("alumacc"); From 8326af5418205e51452e0cced8d2253afe730e76 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 13:11:26 -0700 Subject: [PATCH 036/356] Fix signed multiplier decomposition --- techlibs/common/mul2dsp.v | 65 ++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 4af3b871b..2819c939e 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -5,14 +5,11 @@ `ifndef DSP_A_MAXWIDTH $error("Macro DSP_A_MAXWIDTH must be defined"); `endif -`ifndef DSP_A_SIGNEDONLY -`define DSP_A_SIGNEDONLY 0 -`endif `ifndef DSP_B_MAXWIDTH $error("Macro DSP_B_MAXWIDTH must be defined"); `endif -`ifndef DSP_B_SIGNEDONLY -`define DSP_B_SIGNEDONLY 0 +`ifndef DSP_SIGNEDONLY +`define DSP_SIGNEDONLY 0 `endif `ifndef DSP_NAME @@ -34,7 +31,9 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - if (`DSP_SIGNEDONLY && !A_SIGNED) begin + if (A_SIGNED != B_SIGNED) + wire _TECHMAP_FAIL_ = 1; + else if (`DSP_SIGNEDONLY && !A_SIGNED) begin wire [1:0] dummy; \$mul #( .A_SIGNED(1), @@ -98,19 +97,25 @@ module \$__mul_gen (A, B, Y); genvar i; generate if (A_WIDTH > `DSP_A_MAXWIDTH) begin - localparam n = (A_WIDTH + `DSP_A_MAXWIDTH - sign_headroom - 1)/(`DSP_A_MAXWIDTH - sign_headroom); + localparam n = (A_WIDTH+`DSP_A_MAXWIDTH-sign_headroom-1) / (`DSP_A_MAXWIDTH-sign_headroom); localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH); - wire [partial_Y_WIDTH-1:0] partial [n-1:1]; - wire [Y_WIDTH-1:0] partial_sum [n-1:0]; + if (A_SIGNED && B_SIGNED) begin + wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; + wire signed [Y_WIDTH-1:0] partial_sum [n-1:0]; + end + else begin + wire [partial_Y_WIDTH-1:0] partial [n-1:0]; + wire [Y_WIDTH-1:0] partial_sum [n-1:0]; + end \$__mul_gen #( .A_SIGNED(0), - .B_SIGNED(0), + .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(partial_Y_WIDTH) ) mul_slice_first ( - .A({{sign_headroom{1'b0}}, A[`DSP_A_MAXWIDTH-sign_headroom-1:0]}), + .A({{sign_headroom{1'b0}}, A[`DSP_A_MAXWIDTH-sign_headroom-1 : 0]}), .B(B), .Y(partial[0]) ); @@ -119,7 +124,7 @@ module \$__mul_gen (A, B, Y); for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( .A_SIGNED(0), - .B_SIGNED(0), + .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(partial_Y_WIDTH) @@ -136,24 +141,26 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)), .B_WIDTH(B_WIDTH), - .Y_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom) + B_WIDTH), + .Y_WIDTH(partial_Y_WIDTH) ) mul_slice_last ( - .A(A[A_WIDTH-1:(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)]), + .A(A[A_WIDTH-1 : (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)]), .B(B), .Y(partial[n-1]) ); - assign Y = (partial[n-1] << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; + assign partial_sum[n-1] = (partial[n-1] << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; + assign Y = partial_sum[n-1]; end else if (B_WIDTH > `DSP_B_MAXWIDTH) begin -`ifdef DSP_B_SIGNEDONLY - localparam sign_headroom = 1; -`else - localparam sign_headroom = 0; -`endif - localparam n = (B_WIDTH + `DSP_B_MAXWIDTH - sign_headroom - 1)/(`DSP_B_MAXWIDTH - sign_headroom); + localparam n = (B_WIDTH+`DSP_B_MAXWIDTH-sign_headroom-1) / (`DSP_B_MAXWIDTH-sign_headroom); localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH); - wire [partial_Y_WIDTH-1:0] partial [n-1:1]; - wire [Y_WIDTH-1:0] partial_sum [n-1:0]; + if (A_SIGNED && B_SIGNED) begin + wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; + wire signed [Y_WIDTH-1:0] partial_sum [n-1:0]; + end + else begin + wire [partial_Y_WIDTH-1:0] partial [n-1:0]; + wire [Y_WIDTH-1:0] partial_sum [n-1:0]; + end \$__mul_gen #( .A_SIGNED(A_SIGNED), @@ -163,7 +170,7 @@ module \$__mul_gen (A, B, Y); .Y_WIDTH(partial_Y_WIDTH) ) mul_first ( .A(A), - .B({{sign_headroom{1'b0}}, B[`DSP_B_MAXWIDTH-sign_headroom-1:0]}), + .B({{sign_headroom{1'b0}}, B[`DSP_B_MAXWIDTH-sign_headroom-1 : 0]}), .Y(partial[0]) ); assign partial_sum[0] = partial[0]; @@ -180,21 +187,21 @@ module \$__mul_gen (A, B, Y); .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH-sign_headroom) +: `DSP_B_MAXWIDTH-sign_headroom]}), .Y(partial[i]) ); - assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH - sign_headroom)) + partial_sum[i-1]; + assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; end \$__mul_gen #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)), - .Y_WIDTH(A_WIDTH + B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)) + .B_WIDTH(B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom)), + .Y_WIDTH(partial_Y_WIDTH) ) mul_last ( .A(A), - .B(B[B_WIDTH-1:(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)]), + .B(B[B_WIDTH-1 : (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)]), .Y(partial[n-1]) ); - assign Y = (partial[n-1] << (n-1)*(`DSP_B_MAXWIDTH - sign_headroom)) + partial_sum[n-2]; + assign Y = (partial[n-1] << (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; end else begin if (A_SIGNED) From 0727b2c902df37fbbf2fe9acc31d96ce84fa88a7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 13:18:04 -0700 Subject: [PATCH 037/356] Fix xilinx_dsp index cast --- passes/pmgen/xilinx_dsp.pmg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 60e972615..51fd733d4 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -11,7 +11,7 @@ match ffA select ffA->type.in($dff, $dffe) select param(ffA, \CLK_POLARITY).as_bool() // select nusers(port(ffA, \Q)) == 2 - index port(ffA, \Q).to_sigbit_pool() === port(dsp, \A).remove_const().to_sigbit_pool() + index > port(ffA, \Q).to_sigbit_pool() === port(dsp, \A).remove_const().to_sigbit_pool() // DSP48E1 does not support clock inversion optional endmatch @@ -25,7 +25,7 @@ match ffB select ffB->type.in($dff, $dffe) select param(ffB, \CLK_POLARITY).as_bool() // select nusers(port(ffB, \Q)) == 2 - index port(ffB, \Q).to_sigbit_pool() === port(dsp, \B).remove_const().to_sigbit_pool() + index > port(ffB, \Q).to_sigbit_pool() === port(dsp, \B).remove_const().to_sigbit_pool() optional endmatch From e075f0dda0999374346ddfc09f83d323f426ddde Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 13:22:22 -0700 Subject: [PATCH 038/356] Do not autoremove A/B registers since they might have other consumers --- passes/pmgen/xilinx_dsp.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index bd04cc40b..0010edf55 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -101,8 +101,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("\n"); } - pm.autoremove(st.ffA); - pm.autoremove(st.ffB); pm.autoremove(st.ffP); pm.autoremove(st.muxP); pm.blacklist(cell); From 79d63479eab35cf9bbb94b44a42c61e056cd9bcd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 13:30:35 -0700 Subject: [PATCH 039/356] Improve A/B reg packing --- passes/pmgen/xilinx_dsp.cc | 3 +++ passes/pmgen/xilinx_dsp.pmg | 14 ++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 0010edf55..b583988c4 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -23,6 +23,9 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +template bool includes(const T &lhs, const T &rhs) { + return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} #include "passes/pmgen/xilinx_dsp_pm.h" void pack_xilinx_dsp(xilinx_dsp_pm &pm) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 51fd733d4..fe907b298 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -9,10 +9,9 @@ endmatch match ffA select ffA->type.in($dff, $dffe) - select param(ffA, \CLK_POLARITY).as_bool() - // select nusers(port(ffA, \Q)) == 2 - index > port(ffA, \Q).to_sigbit_pool() === port(dsp, \A).remove_const().to_sigbit_pool() // DSP48E1 does not support clock inversion + select param(ffA, \CLK_POLARITY).as_bool() + filter includes(port(ffA, \Q).to_sigbit_set(), port(dsp, \A).remove_const().to_sigbit_set()) optional endmatch @@ -23,9 +22,9 @@ endcode match ffB select ffB->type.in($dff, $dffe) + // DSP48E1 does not support clock inversion select param(ffB, \CLK_POLARITY).as_bool() - // select nusers(port(ffB, \Q)) == 2 - index > port(ffB, \Q).to_sigbit_pool() === port(dsp, \B).remove_const().to_sigbit_pool() + filter includes(port(ffB, \Q).to_sigbit_set(), port(dsp, \B).remove_const().to_sigbit_set()) optional endmatch @@ -52,9 +51,10 @@ endcode match ffP select ffP->type.in($dff, $dffe) select nusers(port(ffP, \D)) == 2 + // DSP48E1 does not support clock inversion + select param(ffP, \CLK_POLARITY).as_bool() filter param(ffP, \WIDTH).as_int() == P_WIDTH filter port(ffP, \D) == port(dsp, \P).extract(0, P_WIDTH) - index param(ffP, \CLK_POLARITY) === State::S1 optional endmatch @@ -76,6 +76,8 @@ match ffY if muxP select ffY->type.in($dff, $dffe) select nusers(port(ffY, \D)) == 2 + // DSP48E1 does not support clock inversion + select param(ffY, \CLK_POLARITY).as_bool() index port(ffY, \D) === port(muxP, \Y) endmatch From 08fe63c61e652e51d16bd0259ccff3e482f1aa14 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 14:08:18 -0700 Subject: [PATCH 040/356] Improve pattern matcher to match subsets of $dffe? cells --- passes/pmgen/xilinx_dsp.cc | 10 ++++++++-- passes/pmgen/xilinx_dsp.pmg | 24 ++++++++++++++---------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index b583988c4..897bc1aaa 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -39,7 +39,8 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("dsp: %s\n", log_id(st.dsp, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); log("muxP: %s\n", log_id(st.muxP, "--")); - log("P_WIDTH: %d\n", st.P_WIDTH); + log("P_used: %s\n", log_signal(st.P_used)); + log_module(pm.module); #endif log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.dsp)); @@ -79,8 +80,13 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) } if (st.ffP) { SigSpec P = cell->getPort("\\P"); + SigSpec D; + if (st.muxP) + D = st.muxP->getPort("\\B"); + else + D = st.ffP->getPort("\\D"); SigSpec Q = st.ffP->getPort("\\Q"); - P.replace(Q, P.extract(0, GetSize(Q))); + P.replace(D, Q); cell->setPort("\\P", Q); cell->setParam("\\PREG", State::S1); if (st.ffP->type == "$dff") diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index fe907b298..c2bec4c54 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,7 +1,7 @@ pattern xilinx_dsp state clock -state P_WIDTH +state P_used match dsp select dsp->type.in(\DSP48E1) @@ -39,22 +39,25 @@ code clock } endcode -code P_WIDTH +// Extract the bits of P that actually have a consumer +// (as opposed to being a sign extension) +code P_used SigSpec P = port(dsp, \P); int i; for (i = GetSize(P); i > 0; i--) if (nusers(P[i-1]) > 1) break; - P_WIDTH = i; + P_used = P.extract(0, i).remove_const(); endcode match ffP + if !P_used.empty() select ffP->type.in($dff, $dffe) select nusers(port(ffP, \D)) == 2 // DSP48E1 does not support clock inversion select param(ffP, \CLK_POLARITY).as_bool() - filter param(ffP, \WIDTH).as_int() == P_WIDTH - filter port(ffP, \D) == port(dsp, \P).extract(0, P_WIDTH) + filter param(ffP, \WIDTH).as_int() >= GetSize(P_used) + filter includes(port(ffP, \D).to_sigbit_set(), P_used.to_sigbit_set()) optional endmatch @@ -63,12 +66,12 @@ endmatch // since that would lose information helpful for // efficient wide-mux inference match muxP - if !ffP + if !P_used.empty() && !ffP select muxP->type.in($mux) - select port(muxP, \A).is_fully_undef() - filter param(muxP, \WIDTH).as_int() == P_WIDTH - filter port(muxP, \B) == port(dsp, \P).extract(0, P_WIDTH) select nusers(port(muxP, \B)) == 2 + select port(muxP, \A).is_fully_undef() + filter param(muxP, \WIDTH).as_int() >= GetSize(P_used) + filter includes(port(muxP, \B).to_sigbit_set(), P_used.to_sigbit_set()) optional endmatch @@ -78,7 +81,8 @@ match ffY select nusers(port(ffY, \D)) == 2 // DSP48E1 does not support clock inversion select param(ffY, \CLK_POLARITY).as_bool() - index port(ffY, \D) === port(muxP, \Y) + filter param(ffY, \WIDTH).as_int() >= GetSize(P_used) + filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set()) endmatch code ffP clock From 90ac147eb2139dacc18f80515984ef83d7acb6a1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 15:02:41 -0700 Subject: [PATCH 041/356] Do not autoremove ffP aor muxP --- passes/pmgen/xilinx_dsp.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 897bc1aaa..c71ac5ef8 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -110,8 +110,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("\n"); } - pm.autoremove(st.ffP); - pm.autoremove(st.muxP); pm.blacklist(cell); } From e22a7522422ec5f2f6db52d4e9c98d09868ea3e3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 15:21:23 -0700 Subject: [PATCH 042/356] Make consistent --- techlibs/common/mul2dsp.v | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 2819c939e..ee53701ee 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -201,7 +201,8 @@ module \$__mul_gen (A, B, Y); .B(B[B_WIDTH-1 : (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)]), .Y(partial[n-1]) ); - assign Y = (partial[n-1] << (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; + assign partial_sum[n-1] = (partial[n-1] << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; + assign Y = partial_sum[n-1]; end else begin if (A_SIGNED) From 802470746c320676d61431d420e33d34c239da84 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 15:22:00 -0700 Subject: [PATCH 043/356] Check if RHS is empty first --- passes/pmgen/xilinx_dsp.pmg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index c2bec4c54..7a175123e 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -11,6 +11,7 @@ match ffA select ffA->type.in($dff, $dffe) // DSP48E1 does not support clock inversion select param(ffA, \CLK_POLARITY).as_bool() + filter !port(dsp, \A).remove_const().empty() filter includes(port(ffA, \Q).to_sigbit_set(), port(dsp, \A).remove_const().to_sigbit_set()) optional endmatch @@ -24,6 +25,7 @@ match ffB select ffB->type.in($dff, $dffe) // DSP48E1 does not support clock inversion select param(ffB, \CLK_POLARITY).as_bool() + filter !port(dsp, \B).remove_const().empty() filter includes(port(ffB, \Q).to_sigbit_set(), port(dsp, \B).remove_const().to_sigbit_set()) optional endmatch From 2339b7fc3732996a217f635d95f1f7400cf43d48 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 15:37:35 -0700 Subject: [PATCH 044/356] mul2dsp to create cells that can be interchanged with $mul --- techlibs/common/mul2dsp.v | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index ee53701ee..391b395ff 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -214,7 +214,13 @@ module \$__mul_gen (A, B, Y); else wire [`DSP_B_MAXWIDTH-1:0] Bext = B; - `DSP_NAME _TECHMAP_REPLACE_ ( + `DSP_NAME #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(`DSP_A_MAXWIDTH), + .B_WIDTH(`DSP_B_MAXWIDTH), + .Y_WIDTH(`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH), + ) _TECHMAP_REPLACE_ ( .A(Aext), .B(Bext), .Y(Y) From 266c1ae1226656d90ee6416c214ef64fe8b5906f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 15:38:09 -0700 Subject: [PATCH 045/356] synth_ice40 to decompose into 16x16 --- techlibs/ice40/synth_ice40.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 0474e76e9..66446deb7 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -265,8 +265,10 @@ struct SynthIce40Pass : public ScriptPass run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4"); run("opt_expr"); run("opt_clean"); - if (help_mode || dsp) + if (help_mode || dsp) { + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_NAME=$__MUL16X16"); run("ice40_dsp", "(if -dsp)"); + } run("alumacc"); run("opt"); run("fsm"); From 09411dd996f75dbce22a6f6979b7d61b0dae24f7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 15:38:28 -0700 Subject: [PATCH 046/356] ice40_dsp to accept $__MUL16X16 too --- passes/pmgen/ice40_dsp.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 1f3590d4e..f2b7f2169 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -6,7 +6,7 @@ state sigA sigB sigY sigS state addAB muxAB match mul - select mul->type.in($mul) + select mul->type.in($mul, $__MUL16X16) select GetSize(mul->getPort(\A)) + GetSize(mul->getPort(\B)) > 10 select GetSize(mul->getPort(\Y)) > 10 endmatch From 15c2a79ab96e280ecd6311cb0b726b348a2b1eb5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 16:04:58 -0700 Subject: [PATCH 047/356] Do not define `DSP_SIGNEDONLY macro if no exists --- techlibs/common/mul2dsp.v | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 391b395ff..1f4759929 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -8,9 +8,6 @@ $error("Macro DSP_A_MAXWIDTH must be defined"); `ifndef DSP_B_MAXWIDTH $error("Macro DSP_B_MAXWIDTH must be defined"); `endif -`ifndef DSP_SIGNEDONLY -`define DSP_SIGNEDONLY 0 -`endif `ifndef DSP_NAME $error("Macro DSP_NAME must be defined"); @@ -33,7 +30,8 @@ module \$mul (A, B, Y); generate if (A_SIGNED != B_SIGNED) wire _TECHMAP_FAIL_ = 1; - else if (`DSP_SIGNEDONLY && !A_SIGNED) begin +`ifdef DSP_SIGNEDONLY + else if (!A_SIGNED) begin wire [1:0] dummy; \$mul #( .A_SIGNED(1), @@ -47,6 +45,7 @@ module \$mul (A, B, Y); .Y({dummy, Y}) ); end +`endif // NB: A_SIGNED == B_SIGNED == 0 from here else if (A_WIDTH >= B_WIDTH) \$__mul_gen #( From 601fac97e4c48d524d5c7f9b4688b536c2e1c891 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 21:02:49 -0700 Subject: [PATCH 048/356] Add params --- techlibs/xilinx/dsp_map.v | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v index 32f570935..3d7b09d69 100644 --- a/techlibs/xilinx/dsp_map.v +++ b/techlibs/xilinx/dsp_map.v @@ -1,4 +1,10 @@ module \$__MUL25X18 (input signed [24:0] A, input signed [17:0] B, output signed [42:0] Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 0; + parameter B_WIDTH = 0; + parameter Y_WIDTH = 0; + wire [47:0] P_48; DSP48E1 #( // Disable all registers From bddd641290d3c01d86144362cd0e16c82e0bcfd8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Jul 2019 21:03:54 -0700 Subject: [PATCH 049/356] Fix SB_MAC sim model -- do not sign extend internal products? --- techlibs/ice40/cells_sim.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 609facc93..4402f8d36 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -1363,9 +1363,9 @@ module SB_MAC16 ( wire [15:0] p_Ah_Bh, p_Al_Bh, p_Ah_Bl, p_Al_Bl; wire [15:0] Ah, Al, Bh, Bl; assign Ah = {A_SIGNED ? {8{iA[15]}} : 8'b0, iA[15: 8]}; - assign Al = {A_SIGNED ? {8{iA[ 7]}} : 8'b0, iA[ 7: 0]}; + assign Al = {A_SIGNED && MODE_8x8 ? {8{iA[ 7]}} : 8'b0, iA[ 7: 0]}; assign Bh = {B_SIGNED ? {8{iB[15]}} : 8'b0, iB[15: 8]}; - assign Bl = {B_SIGNED ? {8{iB[ 7]}} : 8'b0, iB[ 7: 0]}; + assign Bl = {B_SIGNED && MODE_8x8 ? {8{iB[ 7]}} : 8'b0, iB[ 7: 0]}; assign p_Ah_Bh = Ah * Bh; assign p_Al_Bh = Al * Bh; assign p_Ah_Bl = Ah * Bl; From 2168568f43984af2d194c0eab74ad73443f7e84c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 09:16:13 -0700 Subject: [PATCH 050/356] Use sign_headroom instead --- techlibs/common/mul2dsp.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 1f4759929..da887d426 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -108,7 +108,7 @@ module \$__mul_gen (A, B, Y); end \$__mul_gen #( - .A_SIGNED(0), + .A_SIGNED(sign_headroom), .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), @@ -122,7 +122,7 @@ module \$__mul_gen (A, B, Y); for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( - .A_SIGNED(0), + .A_SIGNED(sign_headroom), .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(B_WIDTH), @@ -163,7 +163,7 @@ module \$__mul_gen (A, B, Y); \$__mul_gen #( .A_SIGNED(A_SIGNED), - .B_SIGNED(0), + .B_SIGNED(sign_headroom), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH), .Y_WIDTH(partial_Y_WIDTH) @@ -177,7 +177,7 @@ module \$__mul_gen (A, B, Y); for (i = 1; i < n-1; i=i+1) begin:slice \$__mul_gen #( .A_SIGNED(A_SIGNED), - .B_SIGNED(0), + .B_SIGNED(sign_headroom), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH), .Y_WIDTH(partial_Y_WIDTH) From ca94c2d3c4785c45a2fefdb659e9ff94f2f8c7b3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 10:27:44 -0700 Subject: [PATCH 051/356] Fix typo in B --- techlibs/common/mul2dsp.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index ee53701ee..da1c7c0c7 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -201,7 +201,7 @@ module \$__mul_gen (A, B, Y); .B(B[B_WIDTH-1 : (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)]), .Y(partial[n-1]) ); - assign partial_sum[n-1] = (partial[n-1] << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; + assign partial_sum[n-1] = (partial[n-1] << (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; assign Y = partial_sum[n-1]; end else begin From 8f0e796be131c2a47694e786ff901cc9970917c6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 10:38:13 -0700 Subject: [PATCH 052/356] Add support for ice40 signed multipliers --- passes/pmgen/ice40_dsp.cc | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 39d033a04..963a7d7a1 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -62,32 +62,27 @@ void create_ice40_dsp(ice40_dsp_pm &pm) return; } - bool mul_signed = st.mul->getParam("\\A_SIGNED").as_bool(); - - if (mul_signed) { - log(" inference of signed iCE40 DSP arithmetic is currently not supported.\n"); - return; - } - - log(" replacing $mul with SB_MAC16 cell.\n"); + log(" replacing %s with SB_MAC16 cell.\n", log_id(st.mul->type)); Cell *cell = pm.module->addCell(NEW_ID, "\\SB_MAC16"); pm.module->swap_names(cell, st.mul); // SB_MAC16 Input Interface + bool a_signed = st.mul->getParam("\\A_SIGNED").as_bool(); + bool b_signed = st.mul->getParam("\\B_SIGNED").as_bool(); SigSpec A = st.sigA; - A.extend_u0(16, mul_signed); + A.extend_u0(16, a_signed); SigSpec B = st.sigB; - B.extend_u0(16, mul_signed); + B.extend_u0(16, b_signed); SigSpec CD; if (st.muxA) CD = st.muxA->getPort("\\B"); if (st.muxB) CD = st.muxB->getPort("\\A"); - CD.extend_u0(32, mul_signed); + CD.extend_u0(32, a_signed && b_signed); cell->setPort("\\A", A); cell->setPort("\\B", B); @@ -198,8 +193,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2)); cell->setParam("\\MODE_8x8", State::S0); - cell->setParam("\\A_SIGNED", mul_signed ? State::S1 : State::S0); - cell->setParam("\\B_SIGNED", mul_signed ? State::S1 : State::S0); + cell->setParam("\\A_SIGNED", a_signed); + cell->setParam("\\B_SIGNED", b_signed); pm.autoremove(st.mul); pm.autoremove(st.ffY); From 9ad11ea2cc25f764bcd4e27dfc12c0f8041cb48a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 10:57:32 -0700 Subject: [PATCH 053/356] Fine tune ice40_dsp.pmg, add support for packing subsets of registers --- passes/pmgen/ice40_dsp.cc | 7 +++-- passes/pmgen/ice40_dsp.pmg | 53 ++++++++++++++++++++++--------------- passes/pmgen/xilinx_dsp.cc | 2 +- passes/pmgen/xilinx_dsp.pmg | 20 +++++++------- 4 files changed, 47 insertions(+), 35 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 963a7d7a1..f6a701540 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -23,13 +23,16 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +template bool includes(const T &lhs, const T &rhs) { + return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} #include "passes/pmgen/ice40_dsp_pm.h" void create_ice40_dsp(ice40_dsp_pm &pm) { auto &st = pm.st_ice40_dsp; -#if 0 +#if 1 log("\n"); log("ffA: %s\n", log_id(st.ffA, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); @@ -100,7 +103,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\IRSTTOP", State::S0); cell->setPort("\\IRSTBOT", State::S0); - if (st.clock_vld) + if (st.clock != SigBit()) { cell->setPort("\\CLK", st.clock); cell->setPort("\\CE", State::S1); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index f2b7f2169..471b8b519 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,8 +1,9 @@ pattern ice40_dsp state clock -state clock_pol clock_vld +state clock_pol state sigA sigB sigY sigS +state sigYused state addAB muxAB match mul @@ -13,68 +14,77 @@ endmatch match ffA select ffA->type.in($dff) - // select nusers(port(ffA, \Q)) == 2 - index port(ffA, \Q) === port(mul, \A) + filter !port(mul, \A).remove_const().empty() + filter includes(port(ffA, \Q).to_sigbit_set(), port(mul, \A).remove_const().to_sigbit_set()) optional endmatch -code sigA clock clock_pol clock_vld +code sigA clock clock_pol sigA = port(mul, \A); if (ffA) { - sigA = port(ffA, \D); + sigA.replace(port(ffA, \Q), port(ffA, \D)); clock = port(ffA, \CLK).as_bit(); clock_pol = param(ffA, \CLK_POLARITY).as_bool(); - clock_vld = true; } endcode match ffB select ffB->type.in($dff) - // select nusers(port(ffB, \Q)) == 2 - index port(ffB, \Q) === port(mul, \B) + filter !port(mul, \B).remove_const().empty() + filter includes(port(ffB, \Q).to_sigbit_set(), port(mul, \B).remove_const().to_sigbit_set()) optional endmatch -code sigB clock clock_pol clock_vld +code sigB clock clock_pol sigB = port(mul, \B); if (ffB) { - sigB = port(ffB, \D); + sigB.replace(port(ffB, \Q), port(ffB, \D)); + SigBit c = port(ffB, \CLK).as_bit(); bool cp = param(ffB, \CLK_POLARITY).as_bool(); - if (clock_vld && (c != clock || cp != clock_pol)) + if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; clock = c; clock_pol = cp; - clock_vld = true; } endcode +// Extract the bits of Y that actually have a consumer +// (as opposed to being a sign extension) +code sigY sigYused + sigY = port(mul, \Y); + int i; + for (i = GetSize(sigY); i > 0; i--) + if (nusers(sigY[i-1]) > 1) + break; + sigYused = sigY.extract(0, i).remove_const(); +endcode + match ffY select ffY->type.in($dff) select nusers(port(ffY, \D)) == 2 - index port(ffY, \D) === port(mul, \Y) + filter param(ffY, \WIDTH).as_int() >= GetSize(sigYused) + filter includes(port(ffY, \D).to_sigbit_set(), sigYused.to_sigbit_set()) optional endmatch -code sigY clock clock_pol clock_vld - sigY = port(mul, \Y); - +code clock clock_pol sigY if (ffY) { - sigY = port(ffY, \Q); + sigY.replace(port(ffY, \D), port(ffY, \Q)); + SigBit c = port(ffY, \CLK).as_bit(); bool cp = param(ffY, \CLK_POLARITY).as_bool(); - if (clock_vld && (c != clock || cp != clock_pol)) + if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; clock = c; clock_pol = cp; - clock_vld = true; } endcode @@ -147,16 +157,15 @@ match ffS index port(ffS, \Q) === sigS endmatch -code clock clock_pol clock_vld +code clock clock_pol if (ffS) { SigBit c = port(ffS, \CLK).as_bit(); bool cp = param(ffS, \CLK_POLARITY).as_bool(); - if (clock_vld && (c != clock || cp != clock_pol)) + if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; clock = c; clock_pol = cp; - clock_vld = true; } endcode diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index c71ac5ef8..d87d63670 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -39,7 +39,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("dsp: %s\n", log_id(st.dsp, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); log("muxP: %s\n", log_id(st.muxP, "--")); - log("P_used: %s\n", log_signal(st.P_used)); + log("sigPused: %s\n", log_signal(st.sigPused)); log_module(pm.module); #endif diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 7a175123e..a97ab4dd5 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,7 +1,7 @@ pattern xilinx_dsp state clock -state P_used +state sigPused match dsp select dsp->type.in(\DSP48E1) @@ -43,23 +43,23 @@ endcode // Extract the bits of P that actually have a consumer // (as opposed to being a sign extension) -code P_used +code sigPused SigSpec P = port(dsp, \P); int i; for (i = GetSize(P); i > 0; i--) if (nusers(P[i-1]) > 1) break; - P_used = P.extract(0, i).remove_const(); + sigPused = P.extract(0, i).remove_const(); endcode match ffP - if !P_used.empty() + if !sigPused.empty() select ffP->type.in($dff, $dffe) select nusers(port(ffP, \D)) == 2 // DSP48E1 does not support clock inversion select param(ffP, \CLK_POLARITY).as_bool() - filter param(ffP, \WIDTH).as_int() >= GetSize(P_used) - filter includes(port(ffP, \D).to_sigbit_set(), P_used.to_sigbit_set()) + filter param(ffP, \WIDTH).as_int() >= GetSize(sigPused) + filter includes(port(ffP, \D).to_sigbit_set(), sigPused.to_sigbit_set()) optional endmatch @@ -68,12 +68,12 @@ endmatch // since that would lose information helpful for // efficient wide-mux inference match muxP - if !P_used.empty() && !ffP + if !sigPused.empty() && !ffP select muxP->type.in($mux) select nusers(port(muxP, \B)) == 2 select port(muxP, \A).is_fully_undef() - filter param(muxP, \WIDTH).as_int() >= GetSize(P_used) - filter includes(port(muxP, \B).to_sigbit_set(), P_used.to_sigbit_set()) + filter param(muxP, \WIDTH).as_int() >= GetSize(sigPused) + filter includes(port(muxP, \B).to_sigbit_set(), sigPused.to_sigbit_set()) optional endmatch @@ -83,7 +83,7 @@ match ffY select nusers(port(ffY, \D)) == 2 // DSP48E1 does not support clock inversion select param(ffY, \CLK_POLARITY).as_bool() - filter param(ffY, \WIDTH).as_int() >= GetSize(P_used) + filter param(ffY, \WIDTH).as_int() >= GetSize(sigPused) filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set()) endmatch From 1d14cec7fd41710aba0bb910a82fa5ca81c4adb0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 11:39:24 -0700 Subject: [PATCH 054/356] Add a DSP_MINWIDTH macro, and soft-logic for {A_WIDTH,B_WIDTH} <= 1 too --- techlibs/common/mul2dsp.v | 96 +++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 28 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index b6aa02834..aab568c9f 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -28,27 +28,11 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - if (A_SIGNED != B_SIGNED) + if (A_SIGNED != B_SIGNED || A_WIDTH <= 1 || B_WIDTH <= 1) wire _TECHMAP_FAIL_ = 1; -`ifdef DSP_SIGNEDONLY - else if (!A_SIGNED) begin - wire [1:0] dummy; - \$mul #( - .A_SIGNED(1), - .B_SIGNED(1), - .A_WIDTH(A_WIDTH + 1), - .B_WIDTH(B_WIDTH + 1), - .Y_WIDTH(Y_WIDTH + 2) - ) _TECHMAP_REPLACE_ ( - .A({1'b0, A}), - .B({1'b0, B}), - .Y({dummy, Y}) - ); - end -`endif // NB: A_SIGNED == B_SIGNED == 0 from here else if (A_WIDTH >= B_WIDTH) - \$__mul_gen #( + \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), @@ -60,7 +44,7 @@ module \$mul (A, B, Y); .Y(Y) ); else - \$__mul_gen #( + \$__mul #( .A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), @@ -74,7 +58,7 @@ module \$mul (A, B, Y); endgenerate endmodule -module \$__mul_gen (A, B, Y); +module \$__mul (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -95,7 +79,13 @@ module \$__mul_gen (A, B, Y); genvar i; generate - if (A_WIDTH > `DSP_A_MAXWIDTH) begin + if (A_WIDTH <= 1 || B_WIDTH <= 1) + wire _TECHMAP_FAIL_ = 1; +`ifdef DSP_MINWIDTH + else if (A_WIDTH+B_WIDTH < `DSP_MINWIDTH || Y_WIDTH < `DSP_MINWIDTH) + wire _TECHMAP_FAIL_ = 1; +`endif + else if (A_WIDTH > `DSP_A_MAXWIDTH) begin localparam n = (A_WIDTH+`DSP_A_MAXWIDTH-sign_headroom-1) / (`DSP_A_MAXWIDTH-sign_headroom); localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH); if (A_SIGNED && B_SIGNED) begin @@ -107,7 +97,7 @@ module \$__mul_gen (A, B, Y); wire [Y_WIDTH-1:0] partial_sum [n-1:0]; end - \$__mul_gen #( + \$__mul #( .A_SIGNED(sign_headroom), .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), @@ -121,7 +111,7 @@ module \$__mul_gen (A, B, Y); assign partial_sum[0] = partial[0]; for (i = 1; i < n-1; i=i+1) begin:slice - \$__mul_gen #( + \$__mul #( .A_SIGNED(sign_headroom), .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), @@ -135,7 +125,7 @@ module \$__mul_gen (A, B, Y); assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; end - \$__mul_gen #( + \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)), @@ -161,7 +151,7 @@ module \$__mul_gen (A, B, Y); wire [Y_WIDTH-1:0] partial_sum [n-1:0]; end - \$__mul_gen #( + \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(sign_headroom), .A_WIDTH(A_WIDTH), @@ -175,7 +165,7 @@ module \$__mul_gen (A, B, Y); assign partial_sum[0] = partial[0]; for (i = 1; i < n-1; i=i+1) begin:slice - \$__mul_gen #( + \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(sign_headroom), .A_WIDTH(A_WIDTH), @@ -189,7 +179,7 @@ module \$__mul_gen (A, B, Y); assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; end - \$__mul_gen #( + \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), @@ -218,7 +208,7 @@ module \$__mul_gen (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH), .B_WIDTH(`DSP_B_MAXWIDTH), - .Y_WIDTH(`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH), + .Y_WIDTH(`MIN(Y_WIDTH,`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH)), ) _TECHMAP_REPLACE_ ( .A(Aext), .B(Bext), @@ -228,4 +218,54 @@ module \$__mul_gen (A, B, Y); endgenerate endmodule +(* techmap_celltype = "$__mul" *) +module _90_internal_mul_to_external (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + generate + if (A_SIGNED && !B_SIGNED) + \$mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(1), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH+1), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A), + .B({1'b0, B}), + .Y(Y) + ); + else if (!A_SIGNED && B_SIGNED) + \$mul #( + .A_SIGNED(1), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH+1), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A({1'b0, A}), + .B(B), + .Y(Y) + ); + else + \$mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A), + .B(B), + .Y(Y) + ); + endgenerate +endmodule From 3dc3c749d5c7c10e1aa504f48794ef0a87513a82 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 11:41:00 -0700 Subject: [PATCH 055/356] Add DSP_MINWIDTH=11 for ice40 since ice40_dsp uses this threshold --- techlibs/ice40/synth_ice40.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 5053e445d..77bd0ac81 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -266,7 +266,7 @@ struct SynthIce40Pass : public ScriptPass run("opt_expr"); run("opt_clean"); if (help_mode || dsp) { - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_NAME=$__MUL16X16"); + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_MINWIDTH=11 -D DSP_NAME=$__MUL16X16", "(if -dsp)"); run("ice40_dsp", "(if -dsp)"); } run("alumacc"); From bba72f03ddd6db370e8fd5afbf14f4f89d0c7e3e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 11:54:26 -0700 Subject: [PATCH 056/356] Do not $mul -> $__mul if A and B are less than maxwidth --- techlibs/common/mul2dsp.v | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index aab568c9f..5444d842a 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -28,7 +28,9 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - if (A_SIGNED != B_SIGNED || A_WIDTH <= 1 || B_WIDTH <= 1) + if (A_SIGNED != B_SIGNED) + wire _TECHMAP_FAIL_ = 1; + else if (A_WIDTH <= `DSP_A_MAXWIDTH && B_WIDTH <= `DSP_B_MAXWIDTH) wire _TECHMAP_FAIL_ = 1; // NB: A_SIGNED == B_SIGNED == 0 from here else if (A_WIDTH >= B_WIDTH) From 595a8f032f1e9db385959f92a4a414a40de291fd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 15:50:13 -0700 Subject: [PATCH 057/356] Do not do sign extension in techmap; let packer do it --- techlibs/common/mul2dsp.v | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 5444d842a..70c2c42c6 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -196,24 +196,15 @@ module \$__mul (A, B, Y); assign Y = partial_sum[n-1]; end else begin - if (A_SIGNED) - wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A); - else - wire [`DSP_A_MAXWIDTH-1:0] Aext = A; - if (B_SIGNED) - wire signed [`DSP_B_MAXWIDTH-1:0] Bext = $signed(B); - else - wire [`DSP_B_MAXWIDTH-1:0] Bext = B; - `DSP_NAME #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), - .A_WIDTH(`DSP_A_MAXWIDTH), - .B_WIDTH(`DSP_B_MAXWIDTH), - .Y_WIDTH(`MIN(Y_WIDTH,`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH)), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(`MIN(Y_WIDTH,A_WIDTH+B_WIDTH)), ) _TECHMAP_REPLACE_ ( - .A(Aext), - .B(Bext), + .A(A), + .B(B), .Y(Y) ); end From 47fd042b9f8a92df1e1d59042068e7846c4ce808 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 20:20:33 -0700 Subject: [PATCH 058/356] Indirection via $__soft_mul --- techlibs/common/mul2dsp.v | 18 +++++++++--------- techlibs/ice40/synth_ice40.cc | 1 + 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 70c2c42c6..8b1ddefbf 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -28,9 +28,7 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - if (A_SIGNED != B_SIGNED) - wire _TECHMAP_FAIL_ = 1; - else if (A_WIDTH <= `DSP_A_MAXWIDTH && B_WIDTH <= `DSP_B_MAXWIDTH) + if (A_SIGNED != B_SIGNED || A_WIDTH <= 1 || B_WIDTH <= 1) wire _TECHMAP_FAIL_ = 1; // NB: A_SIGNED == B_SIGNED == 0 from here else if (A_WIDTH >= B_WIDTH) @@ -212,7 +210,7 @@ module \$__mul (A, B, Y); endmodule (* techmap_celltype = "$__mul" *) -module _90_internal_mul_to_external (A, B, Y); +module $__soft_mul (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -223,9 +221,11 @@ module _90_internal_mul_to_external (A, B, Y); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; + // Indirection necessary since mapping + // back to $mul will cause recursion generate if (A_SIGNED && !B_SIGNED) - \$mul #( + \$__soft__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(1), .A_WIDTH(A_WIDTH), @@ -233,23 +233,23 @@ module _90_internal_mul_to_external (A, B, Y); .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( .A(A), - .B({1'b0, B}), + .B({1'b0,B}), .Y(Y) ); else if (!A_SIGNED && B_SIGNED) - \$mul #( + \$__soft_mul #( .A_SIGNED(1), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( - .A({1'b0, A}), + .A({1'b0,A}), .B(B), .Y(Y) ); else - \$mul #( + \$__soft_mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 77bd0ac81..fcb177491 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -268,6 +268,7 @@ struct SynthIce40Pass : public ScriptPass if (help_mode || dsp) { run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_MINWIDTH=11 -D DSP_NAME=$__MUL16X16", "(if -dsp)"); run("ice40_dsp", "(if -dsp)"); + run("chtype -set $mul t:$__soft_mul"); } run("alumacc"); run("opt"); From f9d08a5e5e0ce637b510f6c19a4cd72edf17b3f7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 20:25:28 -0700 Subject: [PATCH 059/356] Cleanup --- passes/pmgen/ice40_dsp.pmg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 471b8b519..fb5fe0951 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -23,10 +23,10 @@ code sigA clock clock_pol sigA = port(mul, \A); if (ffA) { - sigA.replace(port(ffA, \Q), port(ffA, \D)); - clock = port(ffA, \CLK).as_bit(); clock_pol = param(ffA, \CLK_POLARITY).as_bool(); + + sigA.replace(port(ffA, \Q), port(ffA, \D)); } endcode @@ -41,8 +41,6 @@ code sigB clock clock_pol sigB = port(mul, \B); if (ffB) { - sigB.replace(port(ffB, \Q), port(ffB, \D)); - SigBit c = port(ffB, \CLK).as_bit(); bool cp = param(ffB, \CLK_POLARITY).as_bool(); @@ -51,6 +49,8 @@ code sigB clock clock_pol clock = c; clock_pol = cp; + + sigB.replace(port(ffB, \Q), port(ffB, \D)); } endcode @@ -62,7 +62,7 @@ code sigY sigYused for (i = GetSize(sigY); i > 0; i--) if (nusers(sigY[i-1]) > 1) break; - sigYused = sigY.extract(0, i).remove_const(); + sigYused = sigY.extract(0, i); endcode match ffY From e0720a8018702a2b4de108363a51c8bffc287b55 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 22:47:08 -0700 Subject: [PATCH 060/356] Restore old ffY behaviour --- passes/pmgen/ice40_dsp.pmg | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index fb5fe0951..e4c6238c5 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -3,7 +3,6 @@ pattern ice40_dsp state clock state clock_pol state sigA sigB sigY sigS -state sigYused state addAB muxAB match mul @@ -54,28 +53,18 @@ code sigB clock clock_pol } endcode -// Extract the bits of Y that actually have a consumer -// (as opposed to being a sign extension) -code sigY sigYused - sigY = port(mul, \Y); - int i; - for (i = GetSize(sigY); i > 0; i--) - if (nusers(sigY[i-1]) > 1) - break; - sigYused = sigY.extract(0, i); -endcode - match ffY select ffY->type.in($dff) select nusers(port(ffY, \D)) == 2 - filter param(ffY, \WIDTH).as_int() >= GetSize(sigYused) - filter includes(port(ffY, \D).to_sigbit_set(), sigYused.to_sigbit_set()) + index port(ffY, \D) === port(mul, \Y) optional endmatch -code clock clock_pol sigY +code sigY clock clock_pol + sigY = port(mul, \Y); + if (ffY) { - sigY.replace(port(ffY, \D), port(ffY, \Q)); + sigY = port(ffY, \Q); SigBit c = port(ffY, \CLK).as_bit(); bool cp = param(ffY, \CLK_POLARITY).as_bool(); From 3a7aeb028d7680a73c18ec700939cca76aab0433 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Jul 2019 13:01:26 -0700 Subject: [PATCH 061/356] Use minimum sized width wires --- techlibs/common/mul2dsp.v | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 8b1ddefbf..cf9eeff6f 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -88,12 +88,15 @@ module \$__mul (A, B, Y); else if (A_WIDTH > `DSP_A_MAXWIDTH) begin localparam n = (A_WIDTH+`DSP_A_MAXWIDTH-sign_headroom-1) / (`DSP_A_MAXWIDTH-sign_headroom); localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH); + localparam last_Y_WIDTH = `MIN(partial_Y_WIDTH, B_WIDTH+A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)); if (A_SIGNED && B_SIGNED) begin - wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; + wire signed [partial_Y_WIDTH-1:0] partial [n-2:0]; + wire signed [last_Y_WIDTH-1:0] last_partial; wire signed [Y_WIDTH-1:0] partial_sum [n-1:0]; end else begin wire [partial_Y_WIDTH-1:0] partial [n-1:0]; + wire [last_Y_WIDTH-1:0] last_partial; wire [Y_WIDTH-1:0] partial_sum [n-1:0]; end @@ -130,24 +133,27 @@ module \$__mul (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)), .B_WIDTH(B_WIDTH), - .Y_WIDTH(partial_Y_WIDTH) + .Y_WIDTH(last_Y_WIDTH) ) mul_slice_last ( .A(A[A_WIDTH-1 : (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)]), .B(B), - .Y(partial[n-1]) + .Y(last_partial) ); - assign partial_sum[n-1] = (partial[n-1] << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; + assign partial_sum[n-1] = (last_partial << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; assign Y = partial_sum[n-1]; end else if (B_WIDTH > `DSP_B_MAXWIDTH) begin localparam n = (B_WIDTH+`DSP_B_MAXWIDTH-sign_headroom-1) / (`DSP_B_MAXWIDTH-sign_headroom); localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH); + localparam last_Y_WIDTH = `MIN(partial_Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom)); if (A_SIGNED && B_SIGNED) begin - wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; + wire signed [partial_Y_WIDTH-1:0] partial [n-2:0]; + wire signed [last_Y_WIDTH-1:0] last_partial; wire signed [Y_WIDTH-1:0] partial_sum [n-1:0]; end else begin wire [partial_Y_WIDTH-1:0] partial [n-1:0]; + wire [last_Y_WIDTH-1:0] last_partial; wire [Y_WIDTH-1:0] partial_sum [n-1:0]; end @@ -188,9 +194,9 @@ module \$__mul (A, B, Y); ) mul_last ( .A(A), .B(B[B_WIDTH-1 : (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)]), - .Y(partial[n-1]) + .Y(last_partial) ); - assign partial_sum[n-1] = (partial[n-1] << (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; + assign partial_sum[n-1] = (last_partial << (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; assign Y = partial_sum[n-1]; end else begin From 5a14b6e1f6331d7587d566173e0d82e0c6c77f4c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Jul 2019 13:01:49 -0700 Subject: [PATCH 062/356] Pack adders not just accumulators --- passes/pmgen/ice40_dsp.cc | 38 ++++++++++++++++++++++++++------------ passes/pmgen/ice40_dsp.pmg | 11 +++++++---- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index f6a701540..7215ed473 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -80,17 +80,25 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec B = st.sigB; B.extend_u0(16, b_signed); + // MAC only if ffS exists and adder's other input (sigS) + // is output of ffS + bool accum = (st.ffS && st.sigS == st.ffS->getPort("\\Q")); + SigSpec CD; - if (st.muxA) - CD = st.muxA->getPort("\\B"); - if (st.muxB) - CD = st.muxB->getPort("\\A"); + if (st.ffS) { + if (st.muxA) + CD = st.muxA->getPort("\\B"); + else if (st.muxB) + CD = st.muxB->getPort("\\A"); + } + else if (!accum) + CD = st.sigS.extend_u0(32, st.sigS_signed); CD.extend_u0(32, a_signed && b_signed); cell->setPort("\\A", A); cell->setPort("\\B", B); - cell->setPort("\\C", CD.extract(0, 16)); - cell->setPort("\\D", CD.extract(16, 16)); + cell->setPort("\\C", CD.extract(16, 16)); + cell->setPort("\\D", CD.extract(0, 16)); cell->setParam("\\A_REG", st.ffA ? State::S1 : State::S0); cell->setParam("\\B_REG", st.ffB ? State::S1 : State::S0); @@ -145,14 +153,19 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Output Interface - SigSpec O = st.ffS ? st.sigS : st.sigY; + if (st.addAB) log_cell(st.addAB); + SigSpec O = st.ffS ? st.sigS : (st.addAB ? st.addAB->getPort("\\Y") : st.sigY); if (GetSize(O) < 32) O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); cell->setPort("\\O", O); if (st.addAB) { - log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + log_warning("sigS = %s\n", log_signal(st.sigS)); + if (accum) + log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + else + log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); cell->setPort("\\ADDSUBTOP", st.addAB->type == "$add" ? State::S0 : State::S1); cell->setPort("\\ADDSUBBOT", st.addAB->type == "$add" ? State::S0 : State::S1); } else { @@ -185,14 +198,14 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffY ? State::S1 : State::S0); cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0); - cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2)); + cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffS ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2)); - cell->setParam("\\TOPADDSUB_UPPERINPUT", State::S0); + cell->setParam("\\TOPADDSUB_UPPERINPUT", st.ffS ? State::S0 : State::S1); cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2)); - cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2)); + cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffS ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2)); - cell->setParam("\\BOTADDSUB_UPPERINPUT", State::S0); + cell->setParam("\\BOTADDSUB_UPPERINPUT", st.ffS ? State::S0 : State::S1); cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2)); cell->setParam("\\MODE_8x8", State::S0); @@ -201,6 +214,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) pm.autoremove(st.mul); pm.autoremove(st.ffY); + pm.autoremove(st.addAB); pm.autoremove(st.ffS); } diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index e4c6238c5..a92cf8dd4 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,7 +1,7 @@ pattern ice40_dsp state clock -state clock_pol +state clock_pol sigS_signed state sigA sigB sigY sigS state addAB muxAB @@ -92,14 +92,16 @@ match addB optional endmatch -code addAB sigS +code addAB sigS sigS_signed if (addA) { addAB = addA; - sigS = port(addA, \B); + sigS = port(addAB, \B); + sigS_signed = param(addAB, \B_SIGNED).as_bool(); } if (addB) { addAB = addB; - sigS = port(addB, \A); + sigS = port(addAB, \A); + sigS_signed = param(addAB, \A_SIGNED).as_bool(); } if (addAB) { int natural_mul_width = GetSize(sigA) + GetSize(sigB); @@ -144,6 +146,7 @@ match ffS select nusers(port(ffS, \D)) == 2 index port(ffS, \D) === port(muxAB, \Y) index port(ffS, \Q) === sigS + optional endmatch code clock clock_pol From 5e70b8a22bf38e622943b0546255befd539fa884 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Jul 2019 13:48:33 -0700 Subject: [PATCH 063/356] opt and wreduce necessary for -dsp --- techlibs/ice40/synth_ice40.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index fcb177491..ce88a0542 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -267,8 +267,10 @@ struct SynthIce40Pass : public ScriptPass run("opt_clean"); if (help_mode || dsp) { run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_MINWIDTH=11 -D DSP_NAME=$__MUL16X16", "(if -dsp)"); - run("ice40_dsp", "(if -dsp)"); - run("chtype -set $mul t:$__soft_mul"); + run("opt_expr", " (if -dsp)"); + run("wreduce", " (if -dsp)"); + run("ice40_dsp", " (if -dsp)"); + run("chtype -set $mul t:$__soft_mul","(if -dsp)"); } run("alumacc"); run("opt"); From 304cefbbe2b0c000c30e8d73d1761488be65ccf0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Jul 2019 15:05:16 -0700 Subject: [PATCH 064/356] Pack Y register --- passes/pmgen/ice40_dsp.cc | 48 ++++++++++++++++++++++++-------------- passes/pmgen/ice40_dsp.pmg | 12 ++++++---- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 7215ed473..5f6a20dfc 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -80,20 +80,25 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec B = st.sigB; B.extend_u0(16, b_signed); - // MAC only if ffS exists and adder's other input (sigS) - // is output of ffS - bool accum = (st.ffS && st.sigS == st.ffS->getPort("\\Q")); - SigSpec CD; - if (st.ffS) { - if (st.muxA) - CD = st.muxA->getPort("\\B"); - else if (st.muxB) - CD = st.muxB->getPort("\\A"); - } - else if (!accum) - CD = st.sigS.extend_u0(32, st.sigS_signed); - CD.extend_u0(32, a_signed && b_signed); + bool CD_signed = false; + if (st.muxAB != st.addAB) { + if (st.muxA) + CD = st.muxA->getPort("\\B"); + else if (st.muxB) + CD = st.muxB->getPort("\\A"); + else log_abort(); + CD_signed = a_signed && b_signed; // TODO: Do muxes have [AB]_SIGNED? + } + else if (st.addAB) { + if (st.addA) + CD = st.addAB->getPort("\\B"); + else if (st.addB) + CD = st.addAB->getPort("\\A"); + else log_abort(); + CD_signed = st.sigS_signed; + } + CD.extend_u0(32, CD_signed); cell->setPort("\\A", A); cell->setPort("\\B", B); @@ -153,15 +158,21 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Output Interface - if (st.addAB) log_cell(st.addAB); SigSpec O = st.ffS ? st.sigS : (st.addAB ? st.addAB->getPort("\\Y") : st.sigY); if (GetSize(O) < 32) O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); cell->setPort("\\O", O); + // MAC only if ffS exists and adder's other input (sigS) + // is output of ffS + bool accum = false; if (st.addAB) { - log_warning("sigS = %s\n", log_signal(st.sigS)); + if (st.addA) + accum = (st.ffS && st.addAB->getPort("\\B") == st.ffS->getPort("\\Q")); + else if (st.addB) + accum = (st.ffS && st.addAB->getPort("\\A") == st.ffS->getPort("\\Q")); + else log_abort(); if (accum) log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); else @@ -200,12 +211,12 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffS ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2)); - cell->setParam("\\TOPADDSUB_UPPERINPUT", st.ffS ? State::S0 : State::S1); + cell->setParam("\\TOPADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2)); cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffS ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2)); - cell->setParam("\\BOTADDSUB_UPPERINPUT", st.ffS ? State::S0 : State::S1); + cell->setParam("\\BOTADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2)); cell->setParam("\\MODE_8x8", State::S0); @@ -215,7 +226,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) pm.autoremove(st.mul); pm.autoremove(st.ffY); pm.autoremove(st.addAB); - pm.autoremove(st.ffS); + if (st.ffS) + st.ffS->connections_.at("\\Q").replace(st.sigS, pm.module->addWire(NEW_ID, GetSize(st.sigS))); } struct Ice40DspPass : public Pass { diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index a92cf8dd4..223f9b2e4 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -143,17 +143,21 @@ endcode match ffS if muxAB select ffS->type.in($dff) - select nusers(port(ffS, \D)) == 2 - index port(ffS, \D) === port(muxAB, \Y) - index port(ffS, \Q) === sigS + filter nusers(port(muxAB, \Y)) == 2 + filter includes(port(ffS, \D).to_sigbit_set(), port(muxAB, \Y).to_sigbit_set()) optional endmatch -code clock clock_pol +code clock clock_pol sigS if (ffS) { SigBit c = port(ffS, \CLK).as_bit(); bool cp = param(ffS, \CLK_POLARITY).as_bool(); + if (port(ffS, \Q) != sigS) { + sigS = port(muxAB, \Y); + sigS.replace(port(ffS, \D), port(ffS, \Q)); + } + if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; From 4d71ab384d640f53435d2e4773b2277f385cda27 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Jul 2019 15:08:26 -0700 Subject: [PATCH 065/356] Rename according to vendor doc TN1295 --- passes/pmgen/ice40_dsp.cc | 48 +++++++++++++-------------- passes/pmgen/ice40_dsp.pmg | 62 +++++++++++++++++------------------ techlibs/ice40/synth_ice40.cc | 1 + 3 files changed, 56 insertions(+), 55 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 5f6a20dfc..d4e2914d9 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -37,10 +37,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log("ffA: %s\n", log_id(st.ffA, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); log("mul: %s\n", log_id(st.mul, "--")); - log("ffY: %s\n", log_id(st.ffY, "--")); + log("ffH: %s\n", log_id(st.ffH, "--")); log("addAB: %s\n", log_id(st.addAB, "--")); log("muxAB: %s\n", log_id(st.muxAB, "--")); - log("ffS: %s\n", log_id(st.ffS, "--")); + log("ffO: %s\n", log_id(st.ffO, "--")); #endif log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); @@ -55,13 +55,13 @@ void create_ice40_dsp(ice40_dsp_pm &pm) return; } - if (GetSize(st.sigS) > 32) { - log(" accumulator (%s) is too large (%d > 32).\n", log_signal(st.sigS), GetSize(st.sigS)); + if (GetSize(st.sigO) > 32) { + log(" accumulator (%s) is too large (%d > 32).\n", log_signal(st.sigO), GetSize(st.sigO)); return; } - if (GetSize(st.sigY) > 32) { - log(" output (%s) is too large (%d > 32).\n", log_signal(st.sigY), GetSize(st.sigY)); + if (GetSize(st.sigH) > 32) { + log(" output (%s) is too large (%d > 32).\n", log_signal(st.sigH), GetSize(st.sigH)); return; } @@ -96,7 +96,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) else if (st.addB) CD = st.addAB->getPort("\\A"); else log_abort(); - CD_signed = st.sigS_signed; + CD_signed = st.sigO_signed; } CD.extend_u0(32, CD_signed); @@ -130,11 +130,11 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (st.ffB) log(" ffB:%s", log_id(st.ffB)); - if (st.ffY) - log(" ffY:%s", log_id(st.ffY)); + if (st.ffH) + log(" ffH:%s", log_id(st.ffH)); - if (st.ffS) - log(" ffS:%s", log_id(st.ffS)); + if (st.ffO) + log(" ffO:%s", log_id(st.ffO)); log("\n"); } @@ -158,20 +158,20 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Output Interface - SigSpec O = st.ffS ? st.sigS : (st.addAB ? st.addAB->getPort("\\Y") : st.sigY); + SigSpec O = st.ffO ? st.sigO : (st.addAB ? st.addAB->getPort("\\Y") : st.sigH); if (GetSize(O) < 32) O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); cell->setPort("\\O", O); - // MAC only if ffS exists and adder's other input (sigS) - // is output of ffS + // MAC only if ffO exists and adder's other input (sigO) + // is output of ffO bool accum = false; if (st.addAB) { if (st.addA) - accum = (st.ffS && st.addAB->getPort("\\B") == st.ffS->getPort("\\Q")); + accum = (st.ffO && st.addAB->getPort("\\B") == st.ffO->getPort("\\Q")); else if (st.addB) - accum = (st.ffS && st.addAB->getPort("\\A") == st.ffS->getPort("\\Q")); + accum = (st.ffO && st.addAB->getPort("\\A") == st.ffO->getPort("\\Q")); else log_abort(); if (accum) log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); @@ -204,17 +204,17 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\C_REG", State::S0); cell->setParam("\\D_REG", State::S0); - cell->setParam("\\TOP_8x8_MULT_REG", st.ffY ? State::S1 : State::S0); - cell->setParam("\\BOT_8x8_MULT_REG", st.ffY ? State::S1 : State::S0); - cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffY ? State::S1 : State::S0); + cell->setParam("\\TOP_8x8_MULT_REG", st.ffH ? State::S1 : State::S0); + cell->setParam("\\BOT_8x8_MULT_REG", st.ffH ? State::S1 : State::S0); + cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffH ? State::S1 : State::S0); cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0); - cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffS ? 1 : (st.addAB ? 0 : 3), 2)); + cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffO ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2)); cell->setParam("\\TOPADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2)); - cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffS ? 1 : (st.addAB ? 0 : 3), 2)); + cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffO ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2)); cell->setParam("\\BOTADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2)); @@ -224,10 +224,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\B_SIGNED", b_signed); pm.autoremove(st.mul); - pm.autoremove(st.ffY); + pm.autoremove(st.ffH); pm.autoremove(st.addAB); - if (st.ffS) - st.ffS->connections_.at("\\Q").replace(st.sigS, pm.module->addWire(NEW_ID, GetSize(st.sigS))); + if (st.ffO) + st.ffO->connections_.at("\\Q").replace(st.sigO, pm.module->addWire(NEW_ID, GetSize(st.sigO))); } struct Ice40DspPass : public Pass { diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 223f9b2e4..a74bd7902 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,8 +1,8 @@ pattern ice40_dsp state clock -state clock_pol sigS_signed -state sigA sigB sigY sigS +state clock_pol sigO_signed +state sigA sigB sigH sigO state addAB muxAB match mul @@ -53,21 +53,21 @@ code sigB clock clock_pol } endcode -match ffY - select ffY->type.in($dff) - select nusers(port(ffY, \D)) == 2 - index port(ffY, \D) === port(mul, \Y) +match ffH + select ffH->type.in($dff) + select nusers(port(ffH, \D)) == 2 + index port(ffH, \D) === port(mul, \Y) optional endmatch -code sigY clock clock_pol - sigY = port(mul, \Y); +code sigH clock clock_pol + sigH = port(mul, \Y); - if (ffY) { - sigY = port(ffY, \Q); + if (ffH) { + sigH = port(ffH, \Q); - SigBit c = port(ffY, \CLK).as_bit(); - bool cp = param(ffY, \CLK_POLARITY).as_bool(); + SigBit c = port(ffH, \CLK).as_bit(); + bool cp = param(ffH, \CLK_POLARITY).as_bool(); if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; @@ -80,7 +80,7 @@ endcode match addA select addA->type.in($add) select nusers(port(addA, \A)) == 2 - index port(addA, \A) === sigY + index port(addA, \A) === sigH optional endmatch @@ -88,25 +88,25 @@ match addB if !addA select addB->type.in($add, $sub) select nusers(port(addB, \B)) == 2 - index port(addB, \B) === sigY + index port(addB, \B) === sigH optional endmatch -code addAB sigS sigS_signed +code addAB sigO sigO_signed if (addA) { addAB = addA; - sigS = port(addAB, \B); - sigS_signed = param(addAB, \B_SIGNED).as_bool(); + sigO = port(addAB, \B); + sigO_signed = param(addAB, \B_SIGNED).as_bool(); } if (addB) { addAB = addB; - sigS = port(addAB, \A); - sigS_signed = param(addAB, \A_SIGNED).as_bool(); + sigO = port(addAB, \A); + sigO_signed = param(addAB, \A_SIGNED).as_bool(); } if (addAB) { int natural_mul_width = GetSize(sigA) + GetSize(sigB); - int actual_mul_width = GetSize(sigY); - int actual_acc_width = GetSize(sigS); + int actual_mul_width = GetSize(sigH); + int actual_acc_width = GetSize(sigO); if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) reject; @@ -140,22 +140,22 @@ code muxAB muxAB = muxB; endcode -match ffS +match ffO if muxAB - select ffS->type.in($dff) + select ffO->type.in($dff) filter nusers(port(muxAB, \Y)) == 2 - filter includes(port(ffS, \D).to_sigbit_set(), port(muxAB, \Y).to_sigbit_set()) + filter includes(port(ffO, \D).to_sigbit_set(), port(muxAB, \Y).to_sigbit_set()) optional endmatch -code clock clock_pol sigS - if (ffS) { - SigBit c = port(ffS, \CLK).as_bit(); - bool cp = param(ffS, \CLK_POLARITY).as_bool(); +code clock clock_pol sigO + if (ffO) { + SigBit c = port(ffO, \CLK).as_bit(); + bool cp = param(ffO, \CLK_POLARITY).as_bool(); - if (port(ffS, \Q) != sigS) { - sigS = port(muxAB, \Y); - sigS.replace(port(ffS, \D), port(ffS, \Q)); + if (port(ffO, \Q) != sigO) { + sigO = port(muxAB, \Y); + sigO.replace(port(ffO, \D), port(ffO, \Q)); } if (clock != SigBit() && (c != clock || cp != clock_pol)) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index ce88a0542..50e071a1a 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -271,6 +271,7 @@ struct SynthIce40Pass : public ScriptPass run("wreduce", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); run("chtype -set $mul t:$__soft_mul","(if -dsp)"); + run("dump A:top"); } run("alumacc"); run("opt"); From 8c31441ba066ea246ff1ef55c3dd6ceb4ee8d6e3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Jul 2019 16:10:21 -0700 Subject: [PATCH 066/356] SigSpec::extract() to return as many bits as poss if out of bounds --- kernel/rtlil.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 5d992ef2d..fd98ab4bd 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3354,7 +3354,13 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const { unpack(); cover("kernel.rtlil.sigspec.extract_pos"); - return std::vector(bits_.begin() + offset, length >= 0 ? bits_.begin() + offset + length : bits_.end() + length + 1); + auto it = bits_.begin() + std::min(offset, width_); + decltype(it) ie; + if (length >= 0) + ie = bits_.begin() + std::min(offset + length, width_); + else + ie = bits_.end() + std::max(length + 1, offset - width_); + return std::vector(it, ie); } void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal) From 068617f0948b411fcf9cdf047c6dfc600a0689bb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Jul 2019 16:12:57 -0700 Subject: [PATCH 067/356] Pack hi and lo registers separately --- passes/pmgen/ice40_dsp.cc | 47 +++++++++++++++++------------ passes/pmgen/ice40_dsp.pmg | 62 ++++++++++++++++++++++++++------------ 2 files changed, 70 insertions(+), 39 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index d4e2914d9..6b6fd5640 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -34,13 +34,14 @@ void create_ice40_dsp(ice40_dsp_pm &pm) #if 1 log("\n"); - log("ffA: %s\n", log_id(st.ffA, "--")); - log("ffB: %s\n", log_id(st.ffB, "--")); - log("mul: %s\n", log_id(st.mul, "--")); - log("ffH: %s\n", log_id(st.ffH, "--")); - log("addAB: %s\n", log_id(st.addAB, "--")); - log("muxAB: %s\n", log_id(st.muxAB, "--")); - log("ffO: %s\n", log_id(st.ffO, "--")); + log("ffA: %s\n", log_id(st.ffA, "--")); + log("ffB: %s\n", log_id(st.ffB, "--")); + log("mul: %s\n", log_id(st.mul, "--")); + log("ffH: %s\n", log_id(st.ffH, "--")); + log("addAB: %s\n", log_id(st.addAB, "--")); + log("muxAB: %s\n", log_id(st.muxAB, "--")); + log("ffO_lo: %s\n", log_id(st.ffO_lo, "--")); + log("ffO_hi: %s\n", log_id(st.ffO_hi, "--")); #endif log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); @@ -133,8 +134,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (st.ffH) log(" ffH:%s", log_id(st.ffH)); - if (st.ffO) - log(" ffO:%s", log_id(st.ffO)); + if (st.ffO_lo) + log(" ffO_lo:%s", log_id(st.ffO_lo)); + if (st.ffO_hi) + log(" ffO_hi:%s", log_id(st.ffO_hi)); log("\n"); } @@ -158,20 +161,22 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Output Interface - SigSpec O = st.ffO ? st.sigO : (st.addAB ? st.addAB->getPort("\\Y") : st.sigH); - if (GetSize(O) < 32) - O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); + SigSpec O_lo = (st.ffO_lo ? st.sigO : (st.addAB ? st.addAB->getPort("\\Y") : st.sigH)).extract(0,16); + if (GetSize(O_lo) < 16) + O_lo.append(pm.module->addWire(NEW_ID, 16-GetSize(O_lo))); + SigSpec O_hi = (st.ffO_hi ? st.sigO : (st.addAB ? st.addAB->getPort("\\Y") : st.sigH)).extract(16,16); + if (GetSize(O_hi) < 16) + O_hi.append(pm.module->addWire(NEW_ID, 16-GetSize(O_hi))); + SigSpec O{O_hi,O_lo}; cell->setPort("\\O", O); - // MAC only if ffO exists and adder's other input (sigO) - // is output of ffO bool accum = false; if (st.addAB) { if (st.addA) - accum = (st.ffO && st.addAB->getPort("\\B") == st.ffO->getPort("\\Q")); + accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\B") == O); else if (st.addB) - accum = (st.ffO && st.addAB->getPort("\\A") == st.ffO->getPort("\\Q")); + accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\A") == O); else log_abort(); if (accum) log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); @@ -209,12 +214,12 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffH ? State::S1 : State::S0); cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0); - cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffO ? 1 : (st.addAB ? 0 : 3), 2)); + cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffO_hi ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2)); cell->setParam("\\TOPADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2)); - cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffO ? 1 : (st.addAB ? 0 : 3), 2)); + cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffO_lo ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2)); cell->setParam("\\BOTADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2)); @@ -226,8 +231,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) pm.autoremove(st.mul); pm.autoremove(st.ffH); pm.autoremove(st.addAB); - if (st.ffO) - st.ffO->connections_.at("\\Q").replace(st.sigO, pm.module->addWire(NEW_ID, GetSize(st.sigO))); + if (st.ffO_lo) + st.ffO_lo->connections_.at("\\Q").replace(O.extract(0,16), pm.module->addWire(NEW_ID, 16)); + if (st.ffO_hi) + st.ffO_hi->connections_.at("\\Q").replace(O.extract(16,16), pm.module->addWire(NEW_ID, 16)); } struct Ice40DspPass : public Pass { diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index a74bd7902..0684edc1b 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -60,11 +60,13 @@ match ffH optional endmatch -code sigH clock clock_pol +code sigH sigO clock clock_pol sigH = port(mul, \Y); + sigO = sigH; if (ffH) { sigH = port(ffH, \Q); + sigO = sigH; SigBit c = port(ffH, \CLK).as_bit(); bool cp = param(ffH, \CLK_POLARITY).as_bool(); @@ -95,12 +97,10 @@ endmatch code addAB sigO sigO_signed if (addA) { addAB = addA; - sigO = port(addAB, \B); sigO_signed = param(addAB, \B_SIGNED).as_bool(); } if (addB) { addAB = addB; - sigO = port(addAB, \A); sigO_signed = param(addAB, \A_SIGNED).as_bool(); } if (addAB) { @@ -112,6 +112,8 @@ code addAB sigO sigO_signed reject; if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) reject; + + sigO = port(addAB, \Y); } endcode @@ -132,36 +134,58 @@ match muxB optional endmatch -code muxAB +code muxAB sigO muxAB = addAB; if (muxA) muxAB = muxA; if (muxB) muxAB = muxB; + if (muxA || muxB) + sigO = port(muxAB, \Y); endcode -match ffO - if muxAB - select ffO->type.in($dff) - filter nusers(port(muxAB, \Y)) == 2 - filter includes(port(ffO, \D).to_sigbit_set(), port(muxAB, \Y).to_sigbit_set()) +match ffO_lo + select ffO_lo->type.in($dff) + filter nusers(sigO.extract(0,16)) == 2 + filter includes(port(ffO_lo, \D).to_sigbit_set(), sigO.extract(0,16).to_sigbit_set()) + optional +endmatch + +match ffO_hi + select ffO_hi->type.in($dff) + filter nusers(sigO.extract(16,16)) == 2 + filter includes(port(ffO_hi, \D).to_sigbit_set(), sigO.extract(16,16).to_sigbit_set()) optional endmatch code clock clock_pol sigO - if (ffO) { - SigBit c = port(ffO, \CLK).as_bit(); - bool cp = param(ffO, \CLK_POLARITY).as_bool(); + if (ffO_lo || ffO_hi) { + if (ffO_lo) { + SigBit c = port(ffO_lo, \CLK).as_bit(); + bool cp = param(ffO_lo, \CLK_POLARITY).as_bool(); - if (port(ffO, \Q) != sigO) { - sigO = port(muxAB, \Y); - sigO.replace(port(ffO, \D), port(ffO, \Q)); + if (clock != SigBit() && (c != clock || cp != clock_pol)) + reject; + + clock = c; + clock_pol = cp; + + if (port(ffO_lo, \Q) != sigO.extract(0,16)) + sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q)); } - if (clock != SigBit() && (c != clock || cp != clock_pol)) - reject; + if (ffO_hi) { + SigBit c = port(ffO_hi, \CLK).as_bit(); + bool cp = param(ffO_hi, \CLK_POLARITY).as_bool(); - clock = c; - clock_pol = cp; + if (clock != SigBit() && (c != clock || cp != clock_pol)) + reject; + + clock = c; + clock_pol = cp; + + if (port(ffO_hi, \Q) != sigO.extract(16,16)) + sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q)); + } } endcode From cb505c50d3572a0622110b31b950b43cffc995db Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Jul 2019 16:14:15 -0700 Subject: [PATCH 068/356] Remove debug --- techlibs/ice40/synth_ice40.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 50e071a1a..ce88a0542 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -271,7 +271,6 @@ struct SynthIce40Pass : public ScriptPass run("wreduce", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); run("chtype -set $mul t:$__soft_mul","(if -dsp)"); - run("dump A:top"); } run("alumacc"); run("opt"); From 33c984a0445b2bb24081adf324b2254c454266d1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Jul 2019 16:37:13 -0700 Subject: [PATCH 069/356] Fix spacing --- passes/pmgen/ice40_dsp.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 6b6fd5640..f365ae8b6 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -174,9 +174,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm) bool accum = false; if (st.addAB) { if (st.addA) - accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\B") == O); + accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\B") == O); else if (st.addB) - accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\A") == O); + accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\A") == O); else log_abort(); if (accum) log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); From 4f11ff8ebd23d1f74aae6296ff0a4f792ac97749 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Jul 2019 13:58:56 -0700 Subject: [PATCH 070/356] Fix typo --- passes/pmgen/ice40_dsp.pmg | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 0684edc1b..73ece6962 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,8 +1,8 @@ pattern ice40_dsp state clock -state clock_pol sigO_signed -state sigA sigB sigH sigO +state clock_pol sigCD_signed +state sigA sigB sigCD sigH sigO state addAB muxAB match mul @@ -94,14 +94,16 @@ match addB optional endmatch -code addAB sigO sigO_signed +code addAB sigCD sigCD_signed sigO if (addA) { addAB = addA; - sigO_signed = param(addAB, \B_SIGNED).as_bool(); + sigCD = port(addAB, \B); + sigCD_signed = param(addAB, \B_SIGNED).as_bool(); } if (addB) { addAB = addB; - sigO_signed = param(addAB, \A_SIGNED).as_bool(); + sigCD = port(addAB, \A); + sigCD_signed = param(addAB, \A_SIGNED).as_bool(); } if (addAB) { int natural_mul_width = GetSize(sigA) + GetSize(sigB); @@ -118,30 +120,36 @@ code addAB sigO sigO_signed endcode match muxA - if addAB + if sigCD.empty() select muxA->type.in($mux) select nusers(port(muxA, \A)) == 2 - index port(muxA, \A) === port(addAB, \Y) + index port(muxA, \A) === sigO optional endmatch match muxB - if addAB + if sigCD.empty() if !muxA select muxB->type.in($mux) select nusers(port(muxB, \B)) == 2 - index port(muxB, \B) === port(addAB, \Y) + index port(muxB, \B) === sigO optional endmatch -code muxAB sigO +code muxAB sigCD sigCD_signed sigO muxAB = addAB; - if (muxA) + if (muxA) { muxAB = muxA; - if (muxB) + sigCD = port(muxAB, \B); + } + if (muxB) { muxAB = muxB; - if (muxA || muxB) + sigCD = port(muxAB, \A); + } + if (muxA || muxB) { sigO = port(muxAB, \Y); + sigCD_signed = addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool(); + } endcode match ffO_lo From dc0c853abeadd11e81da280c657fd1341405de3b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Jul 2019 14:20:34 -0700 Subject: [PATCH 071/356] Simplify and fix for MACs --- passes/pmgen/ice40_dsp.cc | 61 +++++++++++++------------------------- passes/pmgen/ice40_dsp.pmg | 33 +++++++++++---------- 2 files changed, 38 insertions(+), 56 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index f365ae8b6..f18fad060 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -81,25 +81,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec B = st.sigB; B.extend_u0(16, b_signed); - SigSpec CD; - bool CD_signed = false; - if (st.muxAB != st.addAB) { - if (st.muxA) - CD = st.muxA->getPort("\\B"); - else if (st.muxB) - CD = st.muxB->getPort("\\A"); - else log_abort(); - CD_signed = a_signed && b_signed; // TODO: Do muxes have [AB]_SIGNED? - } - else if (st.addAB) { - if (st.addA) - CD = st.addAB->getPort("\\B"); - else if (st.addB) - CD = st.addAB->getPort("\\A"); - else log_abort(); - CD_signed = st.sigO_signed; - } - CD.extend_u0(32, CD_signed); + SigSpec CD = st.sigCD; + CD.extend_u0(32, st.sigCD_signed); cell->setPort("\\A", A); cell->setPort("\\B", B); @@ -161,27 +144,19 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Output Interface - SigSpec O_lo = (st.ffO_lo ? st.sigO : (st.addAB ? st.addAB->getPort("\\Y") : st.sigH)).extract(0,16); - if (GetSize(O_lo) < 16) - O_lo.append(pm.module->addWire(NEW_ID, 16-GetSize(O_lo))); - SigSpec O_hi = (st.ffO_hi ? st.sigO : (st.addAB ? st.addAB->getPort("\\Y") : st.sigH)).extract(16,16); - if (GetSize(O_hi) < 16) - O_hi.append(pm.module->addWire(NEW_ID, 16-GetSize(O_hi))); - - SigSpec O{O_hi,O_lo}; - cell->setPort("\\O", O); + cell->setPort("\\O", st.sigO); bool accum = false; if (st.addAB) { - if (st.addA) - accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\B") == O); - else if (st.addB) - accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\A") == O); - else log_abort(); - if (accum) - log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); - else - log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + if (st.addA) + accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\B") == st.sigO); + else if (st.addB) + accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\A") == st.sigO); + else log_abort(); + if (accum) + log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + else + log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); cell->setPort("\\ADDSUBTOP", st.addAB->type == "$add" ? State::S0 : State::S1); cell->setPort("\\ADDSUBBOT", st.addAB->type == "$add" ? State::S0 : State::S1); } else { @@ -231,10 +206,14 @@ void create_ice40_dsp(ice40_dsp_pm &pm) pm.autoremove(st.mul); pm.autoremove(st.ffH); pm.autoremove(st.addAB); - if (st.ffO_lo) - st.ffO_lo->connections_.at("\\Q").replace(O.extract(0,16), pm.module->addWire(NEW_ID, 16)); - if (st.ffO_hi) - st.ffO_hi->connections_.at("\\Q").replace(O.extract(16,16), pm.module->addWire(NEW_ID, 16)); + if (st.ffO_lo) { + SigSpec O = st.sigO.extract(0,16); + st.ffO_lo->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); + } + if (st.ffO_hi) { + SigSpec O = st.sigO.extract(16,16); + st.ffO_hi->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); + } } struct Ice40DspPass : public Pass { diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 73ece6962..24247d3cf 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -120,7 +120,6 @@ code addAB sigCD sigCD_signed sigO endcode match muxA - if sigCD.empty() select muxA->type.in($mux) select nusers(port(muxA, \A)) == 2 index port(muxA, \A) === sigO @@ -128,7 +127,6 @@ match muxA endmatch match muxB - if sigCD.empty() if !muxA select muxB->type.in($mux) select nusers(port(muxB, \B)) == 2 @@ -136,20 +134,11 @@ match muxB optional endmatch -code muxAB sigCD sigCD_signed sigO - muxAB = addAB; - if (muxA) { +code muxAB + if (muxA) muxAB = muxA; - sigCD = port(muxAB, \B); - } - if (muxB) { + else if (muxB) muxAB = muxB; - sigCD = port(muxAB, \A); - } - if (muxA || muxB) { - sigO = port(muxAB, \Y); - sigCD_signed = addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool(); - } endcode match ffO_lo @@ -166,7 +155,7 @@ match ffO_hi optional endmatch -code clock clock_pol sigO +code clock clock_pol sigO sigCD sigCD_signed if (ffO_lo || ffO_hi) { if (ffO_lo) { SigBit c = port(ffO_lo, \CLK).as_bit(); @@ -195,5 +184,19 @@ code clock clock_pol sigO if (port(ffO_hi, \Q) != sigO.extract(16,16)) sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q)); } + + // Loading value into output register is not + // supported unless using accumulator + if (muxAB && sigCD != sigO) { + if (muxAB != addAB) + reject; + + if (muxA) + sigCD = port(muxAB, \B); + else if (muxB) + sigCD = port(muxAB, \A); + else log_abort(); + sigCD_signed = addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool(); + } } endcode From 0dd2a125f655c459b17b5c56c4d34a21d0833bc8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Jul 2019 14:21:45 -0700 Subject: [PATCH 072/356] Remove debug print --- passes/pmgen/ice40_dsp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index f18fad060..ee4e4f5e8 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -32,7 +32,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) { auto &st = pm.st_ice40_dsp; -#if 1 +#if 0 log("\n"); log("ffA: %s\n", log_id(st.ffA, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); From a37574ccbfe047c09a60bb6ee68b7b5e2ef61337 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Jul 2019 14:52:14 -0700 Subject: [PATCH 073/356] Fix muxAB logic --- passes/pmgen/ice40_dsp.pmg | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 24247d3cf..4b566f0a6 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -187,10 +187,9 @@ code clock clock_pol sigO sigCD sigCD_signed // Loading value into output register is not // supported unless using accumulator - if (muxAB && sigCD != sigO) { - if (muxAB != addAB) + if (muxAB) { + if (sigCD != sigO) reject; - if (muxA) sigCD = port(muxAB, \B); else if (muxB) From 151c5c96c0a85a1b69fc7824949ed89d70667059 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Jul 2019 15:05:20 -0700 Subject: [PATCH 074/356] Typo for Y_WIDTH --- techlibs/common/mul2dsp.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index cf9eeff6f..06ae3fc04 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -190,7 +190,7 @@ module \$__mul (A, B, Y); .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom)), - .Y_WIDTH(partial_Y_WIDTH) + .Y_WIDTH(last_Y_WIDTH) ) mul_last ( .A(A), .B(B[B_WIDTH-1 : (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)]), From 79fd6edc5a076d263a9d68f0e1a103a9d643a9df Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Jul 2019 15:13:30 -0700 Subject: [PATCH 075/356] Eliminate warnings by sizing O correctly --- passes/pmgen/ice40_dsp.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index ee4e4f5e8..3ceffdbf6 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -144,7 +144,11 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Output Interface - cell->setPort("\\O", st.sigO); + SigSpec O = st.sigO; + if (GetSize(O) < 32) + O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); + + cell->setPort("\\O", O); bool accum = false; if (st.addAB) { From c39ccc65e9ba79aafa6ebd5c3abe9faf7d465a8f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 24 Jul 2019 10:49:09 -0700 Subject: [PATCH 076/356] Add copyright header, comment on cascade --- techlibs/common/mul2dsp.v | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 06ae3fc04..a8c2dcccc 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -1,7 +1,31 @@ -// From Eddie Hung -// extracted from: https://github.com/eddiehung/vtr-with-yosys/blob/vtr7-with-yosys/vtr_flow/misc/yosys_models.v#L220 -// revised by Andre DeHon -// further revised by David Shah +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * 2019 David Shah + * + * 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. + * + * --- + * + * Tech-mapping rules for decomposing arbitrarily-sized $mul cells + * into an equivalent collection of smaller `DSP_NAME cells (with the + * same interface as $mul) no larger than `DSP_[AB]_MAXWIDTH, attached + * to $shl and $add cells. + * + */ + `ifndef DSP_A_MAXWIDTH $error("Macro DSP_A_MAXWIDTH must be defined"); `endif @@ -125,6 +149,9 @@ module \$__mul (A, B, Y); .B(B), .Y(partial[i]) ); + // TODO: Currently a 'cascade' approach to summing the partial + // products is taken here, but a more efficient 'binary + // reduction' approach also exists... assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; end @@ -182,6 +209,9 @@ module \$__mul (A, B, Y); .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH-sign_headroom) +: `DSP_B_MAXWIDTH-sign_headroom]}), .Y(partial[i]) ); + // TODO: Currently a 'cascade' approach to summing the partial + // products is taken here, but a more efficient 'binary + // reduction' approach also exists... assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; end From c1a05f45577223c0585e93d728c8e04169c4598d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Jul 2019 10:15:36 -0700 Subject: [PATCH 077/356] Allow adders/accumulators with 33 bits using CO output --- passes/pmgen/ice40_dsp.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 3ceffdbf6..c5655ad20 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -56,8 +56,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) return; } - if (GetSize(st.sigO) > 32) { - log(" accumulator (%s) is too large (%d > 32).\n", log_signal(st.sigO), GetSize(st.sigO)); + if (GetSize(st.sigO) > 33) { + log(" adder/accumulator (%s) is too large (%d > 33).\n", log_signal(st.sigO), GetSize(st.sigO)); return; } @@ -137,7 +137,6 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\SIGNEXTOUT", pm.module->addWire(NEW_ID)); cell->setPort("\\CI", State::Sx); - cell->setPort("\\CO", pm.module->addWire(NEW_ID)); cell->setPort("\\ACCUMCI", State::Sx); cell->setPort("\\ACCUMCO", pm.module->addWire(NEW_ID)); @@ -145,6 +144,12 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Output Interface SigSpec O = st.sigO; + if (GetSize(O) == 33) + cell->setPort("\\CO", st.sigO[32]); + else { + log_assert(GetSize(O) <= 32); + cell->setPort("\\CO", pm.module->addWire(NEW_ID)); + } if (GetSize(O) < 32) O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); From 4c25d1a76fc006cac0d9e2038617f41ca90685c1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Jul 2019 10:27:30 -0700 Subject: [PATCH 078/356] Pop the CO bit from O --- passes/pmgen/ice40_dsp.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index c5655ad20..369cb211e 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -144,8 +144,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Output Interface SigSpec O = st.sigO; - if (GetSize(O) == 33) + if (GetSize(O) == 33) { cell->setPort("\\CO", st.sigO[32]); + O.remove(32); + } else { log_assert(GetSize(O) <= 32); cell->setPort("\\CO", pm.module->addWire(NEW_ID)); From 8cecad5059b7ce6e1db1597020794c8e8aad3e49 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Jul 2019 12:26:54 -0700 Subject: [PATCH 079/356] Add doc for "test_autotb -seed" option --- passes/tests/test_autotb.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc index bfb1d6642..7eee6a568 100644 --- a/passes/tests/test_autotb.cc +++ b/passes/tests/test_autotb.cc @@ -348,6 +348,9 @@ struct TestAutotbBackend : public Backend { log(" -n \n"); log(" number of iterations the test bench should run (default = 1000)\n"); log("\n"); + log(" -seed \n"); + log(" seed used for pseudo-random number generation (default = time)\n"); + log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { From 07e38d8d5c9d270404f68072b905b1dd43ced24b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Jul 2019 12:37:30 -0700 Subject: [PATCH 080/356] Update test_autotb doc to reflect default value of zero --- passes/tests/test_autotb.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc index 7eee6a568..7f11e54f3 100644 --- a/passes/tests/test_autotb.cc +++ b/passes/tests/test_autotb.cc @@ -349,7 +349,9 @@ struct TestAutotbBackend : public Backend { log(" number of iterations the test bench should run (default = 1000)\n"); log("\n"); log(" -seed \n"); - log(" seed used for pseudo-random number generation (default = time)\n"); + log(" seed used for pseudo-random number generation (default = 0).\n"); + log(" a value of 0 will cause an arbitrary seed to be chosen, based on\n"); + log(" the current system time.\n"); log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE From 2f71c2c2198b05e216524feb94b66d14c9c433c0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Jul 2019 15:30:51 -0700 Subject: [PATCH 081/356] Fix spacing --- techlibs/common/mul2dsp.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index a8c2dcccc..678de3796 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -149,9 +149,9 @@ module \$__mul (A, B, Y); .B(B), .Y(partial[i]) ); - // TODO: Currently a 'cascade' approach to summing the partial - // products is taken here, but a more efficient 'binary - // reduction' approach also exists... + // TODO: Currently a 'cascade' approach to summing the partial + // products is taken here, but a more efficient 'binary + // reduction' approach also exists... assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; end From 84c7a562e597aaaacaab122a2ec7cbdf67ff6cfc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 31 Jul 2019 12:18:03 -0700 Subject: [PATCH 082/356] Helper: SigSpec::operator[] to accept negative indices --- kernel/rtlil.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 868aaaa14..1ed055715 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -734,8 +734,8 @@ public: inline int size() const { return width_; } inline bool empty() const { return width_ == 0; } - inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return bits_.at(index); } - inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return bits_.at(index); } + inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return index >= 0 ? bits_.at(index) : bits_.at(width_ + index); } + inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return index >= 0 ? bits_.at(index) : bits_.at(width_ + index); } inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; } inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = width_; return it; } From e4a638c29297e3e8b915cf84a2dddc339f511476 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 31 Jul 2019 15:45:15 -0700 Subject: [PATCH 083/356] Restore old CO behaviour --- passes/pmgen/ice40_dsp.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 369cb211e..00794ca0d 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -144,14 +144,15 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Output Interface SigSpec O = st.sigO; - if (GetSize(O) == 33) { - cell->setPort("\\CO", st.sigO[32]); - O.remove(32); + int O_width = GetSize(O); + if (O_width == 33) { + log_assert(st.addAB); + cell->setPort("\\CO", O[-1]); + O.remove(O_width-1); } - else { - log_assert(GetSize(O) <= 32); + else cell->setPort("\\CO", pm.module->addWire(NEW_ID)); - } + log_assert(GetSize(O) <= 32); if (GetSize(O) < 32) O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); From 60c4887d15f89499d351fe9bd9ed36a5a4c1fe37 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 31 Jul 2019 15:45:41 -0700 Subject: [PATCH 084/356] For signed multipliers, compute sign bit separately... --- techlibs/common/mul2dsp.v | 65 +++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 678de3796..b745547a8 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -54,8 +54,22 @@ module \$mul (A, B, Y); generate if (A_SIGNED != B_SIGNED || A_WIDTH <= 1 || B_WIDTH <= 1) wire _TECHMAP_FAIL_ = 1; - // NB: A_SIGNED == B_SIGNED == 0 from here - else if (A_WIDTH >= B_WIDTH) + // NB: A_SIGNED == B_SIGNED from here + else if (A_WIDTH < B_WIDTH) + \$mul #( + .A_SIGNED(B_SIGNED), + .B_SIGNED(A_SIGNED), + .A_WIDTH(B_WIDTH), + .B_WIDTH(A_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(B), + .B(A), + .Y(Y) + ); + else if (A_SIGNED && (A_WIDTH > `DSP_A_MAXWIDTH || B_WIDTH > `DSP_B_MAXWIDTH)) begin + wire _; + assign Y[Y_WIDTH-1] = A[A_WIDTH-1] ^ B[B_WIDTH-1]; \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), @@ -65,18 +79,19 @@ module \$mul (A, B, Y); ) _TECHMAP_REPLACE_ ( .A(A), .B(B), - .Y(Y) + .Y({_,Y[Y_WIDTH-2:0]}) ); + end else \$__mul #( - .A_SIGNED(B_SIGNED), - .B_SIGNED(A_SIGNED), - .A_WIDTH(B_WIDTH), - .B_WIDTH(A_WIDTH), + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( - .A(B), - .B(A), + .A(A), + .B(B), .Y(Y) ); endgenerate @@ -209,23 +224,27 @@ module \$__mul (A, B, Y); .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH-sign_headroom) +: `DSP_B_MAXWIDTH-sign_headroom]}), .Y(partial[i]) ); - // TODO: Currently a 'cascade' approach to summing the partial - // products is taken here, but a more efficient 'binary - // reduction' approach also exists... + // TODO: Currently a 'cascade' approach to summing the partial + // products is taken here, but a more efficient 'binary + // reduction' approach also exists... assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; end - \$__mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom)), - .Y_WIDTH(last_Y_WIDTH) - ) mul_last ( - .A(A), - .B(B[B_WIDTH-1 : (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)]), - .Y(last_partial) - ); + localparam last_B_WIDTH = B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom); + if (A_SIGNED && B_SIGNED && last_B_WIDTH == 1) + assign last_partial = 0; + else + \$__mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(last_B_WIDTH), + .Y_WIDTH(last_Y_WIDTH) + ) mul_last ( + .A(A), + .B(B[B_WIDTH-1 -: last_B_WIDTH]), + .Y(last_partial) + ); assign partial_sum[n-1] = (last_partial << (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; assign Y = partial_sum[n-1]; end From d2c33863d08bbc506888b723a304aa11f8650296 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 31 Jul 2019 16:04:19 -0700 Subject: [PATCH 085/356] Do not compute sign bit if result is zero --- techlibs/common/mul2dsp.v | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index b745547a8..bfd216fbf 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -69,7 +69,6 @@ module \$mul (A, B, Y); ); else if (A_SIGNED && (A_WIDTH > `DSP_A_MAXWIDTH || B_WIDTH > `DSP_B_MAXWIDTH)) begin wire _; - assign Y[Y_WIDTH-1] = A[A_WIDTH-1] ^ B[B_WIDTH-1]; \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), @@ -81,6 +80,8 @@ module \$mul (A, B, Y); .B(B), .Y({_,Y[Y_WIDTH-2:0]}) ); + // For non-zero results, recompute sign bit + assign Y[Y_WIDTH-1] = (|Y[Y_WIDTH-2:0]) & (A[A_WIDTH-1] ^ B[B_WIDTH-1]); end else \$__mul #( From e3c39cc450a0317ad7e8234bb866d55465548c9c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 10:00:01 -0700 Subject: [PATCH 086/356] Fix typo --- passes/pmgen/ice40_dsp.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 4b566f0a6..73439cfd9 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -112,7 +112,7 @@ code addAB sigCD sigCD_signed sigO if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) reject; - if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) + if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \B_SIGNED).as_bool())) reject; sigO = port(addAB, \Y); From c54a39069d1f536da7a830fa2fa504bc72c20c18 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 10:00:49 -0700 Subject: [PATCH 087/356] CO is sign extension only if signed multiplier --- passes/pmgen/ice40_dsp.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 00794ca0d..f88cd62dd 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -147,7 +147,12 @@ void create_ice40_dsp(ice40_dsp_pm &pm) int O_width = GetSize(O); if (O_width == 33) { log_assert(st.addAB); - cell->setPort("\\CO", O[-1]); + // If we have a signed multiply-add, then perform sign extension + // TODO: Need to check CD[31:16] is sign extension of CD[15:0]? + if (st.addAB->getParam("\\A_SIGNED").as_bool() && st.addAB->getParam("\\B_SIGNED").as_bool()) + pm.module->connect(O[-1], O[-2]); + else + cell->setPort("\\CO", O[-1]); O.remove(O_width-1); } else From 7e86c8bcfb10f6a819273ad8bd10fa461987f2f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 10:01:43 -0700 Subject: [PATCH 088/356] Fix B_WIDTH > DSP_B_MAXWIDTH case --- techlibs/common/mul2dsp.v | 46 ++++++++++++--------------------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index bfd216fbf..b28a4247e 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -67,22 +67,6 @@ module \$mul (A, B, Y); .B(A), .Y(Y) ); - else if (A_SIGNED && (A_WIDTH > `DSP_A_MAXWIDTH || B_WIDTH > `DSP_B_MAXWIDTH)) begin - wire _; - \$__mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(A), - .B(B), - .Y({_,Y[Y_WIDTH-2:0]}) - ); - // For non-zero results, recompute sign bit - assign Y[Y_WIDTH-1] = (|Y[Y_WIDTH-2:0]) & (A[A_WIDTH-1] ^ B[B_WIDTH-1]); - end else \$__mul #( .A_SIGNED(A_SIGNED), @@ -171,14 +155,15 @@ module \$__mul (A, B, Y); assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; end + localparam last_A_WIDTH = A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom); \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)), + .A_WIDTH(last_A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(last_Y_WIDTH) ) mul_slice_last ( - .A(A[A_WIDTH-1 : (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)]), + .A(A[A_WIDTH-1 -: last_A_WIDTH]), .B(B), .Y(last_partial) ); @@ -232,20 +217,17 @@ module \$__mul (A, B, Y); end localparam last_B_WIDTH = B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom); - if (A_SIGNED && B_SIGNED && last_B_WIDTH == 1) - assign last_partial = 0; - else - \$__mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(last_B_WIDTH), - .Y_WIDTH(last_Y_WIDTH) - ) mul_last ( - .A(A), - .B(B[B_WIDTH-1 -: last_B_WIDTH]), - .Y(last_partial) - ); + \$__mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(last_B_WIDTH), + .Y_WIDTH(last_Y_WIDTH) + ) mul_last ( + .A(A), + .B(B[B_WIDTH-1 -: last_B_WIDTH]), + .Y(last_partial) + ); assign partial_sum[n-1] = (last_partial << (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; assign Y = partial_sum[n-1]; end From 332b86491de4d033f2fe259ab7ad7d02761cc515 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 12:17:14 -0700 Subject: [PATCH 089/356] Revert "Do not do sign extension in techmap; let packer do it" This reverts commit 595a8f032f1e9db385959f92a4a414a40de291fd. --- techlibs/common/mul2dsp.v | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index b28a4247e..99afce18c 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -232,15 +232,24 @@ module \$__mul (A, B, Y); assign Y = partial_sum[n-1]; end else begin + if (A_SIGNED) + wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A); + else + wire [`DSP_A_MAXWIDTH-1:0] Aext = A; + if (B_SIGNED) + wire signed [`DSP_B_MAXWIDTH-1:0] Bext = $signed(B); + else + wire [`DSP_B_MAXWIDTH-1:0] Bext = B; + `DSP_NAME #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(`MIN(Y_WIDTH,A_WIDTH+B_WIDTH)), + .A_WIDTH(`DSP_A_MAXWIDTH), + .B_WIDTH(`DSP_B_MAXWIDTH), + .Y_WIDTH(`MIN(Y_WIDTH,`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH)), ) _TECHMAP_REPLACE_ ( - .A(A), - .B(B), + .A(Aext), + .B(Bext), .Y(Y) ); end From e19d33b003702a03b191fa2eda14d016a6bce0aa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 12:44:56 -0700 Subject: [PATCH 090/356] Cope with sign extension in mul2dsp --- passes/pmgen/ice40_dsp.cc | 16 ++++++++-------- passes/pmgen/ice40_dsp.pmg | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index f88cd62dd..f6ae3a13f 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -72,17 +72,17 @@ void create_ice40_dsp(ice40_dsp_pm &pm) pm.module->swap_names(cell, st.mul); // SB_MAC16 Input Interface - bool a_signed = st.mul->getParam("\\A_SIGNED").as_bool(); - bool b_signed = st.mul->getParam("\\B_SIGNED").as_bool(); - SigSpec A = st.sigA; - A.extend_u0(16, a_signed); + log_assert(GetSize(A) == 16); SigSpec B = st.sigB; - B.extend_u0(16, b_signed); + log_assert(GetSize(B) == 16); SigSpec CD = st.sigCD; - CD.extend_u0(32, st.sigCD_signed); + if (CD.empty()) + CD = RTLIL::Const(0, 32); + else + log_assert(GetSize(CD) == 32); cell->setPort("\\A", A); cell->setPort("\\B", B); @@ -217,8 +217,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2)); cell->setParam("\\MODE_8x8", State::S0); - cell->setParam("\\A_SIGNED", a_signed); - cell->setParam("\\B_SIGNED", b_signed); + cell->setParam("\\A_SIGNED", st.mul->getParam("\\A_SIGNED").as_bool()); + cell->setParam("\\B_SIGNED", st.mul->getParam("\\B_SIGNED").as_bool()); pm.autoremove(st.mul); pm.autoremove(st.ffH); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 73439cfd9..040332539 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,7 +1,7 @@ pattern ice40_dsp state clock -state clock_pol sigCD_signed +state clock_pol state sigA sigB sigCD sigH sigO state addAB muxAB @@ -94,16 +94,16 @@ match addB optional endmatch -code addAB sigCD sigCD_signed sigO +code addAB sigCD sigO if (addA) { addAB = addA; sigCD = port(addAB, \B); - sigCD_signed = param(addAB, \B_SIGNED).as_bool(); + sigCD.extend_u0(32, param(addAB, \B_SIGNED).as_bool()); } if (addB) { addAB = addB; sigCD = port(addAB, \A); - sigCD_signed = param(addAB, \A_SIGNED).as_bool(); + sigCD.extend_u0(32, param(addAB, \A_SIGNED).as_bool()); } if (addAB) { int natural_mul_width = GetSize(sigA) + GetSize(sigB); @@ -155,7 +155,7 @@ match ffO_hi optional endmatch -code clock clock_pol sigO sigCD sigCD_signed +code clock clock_pol sigO sigCD if (ffO_lo || ffO_hi) { if (ffO_lo) { SigBit c = port(ffO_lo, \CLK).as_bit(); @@ -195,7 +195,7 @@ code clock clock_pol sigO sigCD sigCD_signed else if (muxB) sigCD = port(muxAB, \A); else log_abort(); - sigCD_signed = addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool(); + sigCD.extend_u0(32, addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool()); } } endcode From fc0b5d5ab6bcbb6cc5fcacab479504c08ab80d23 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 12:45:14 -0700 Subject: [PATCH 091/356] Change $__softmul back to $mul --- techlibs/xilinx/synth_xilinx.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index e5a27015a..a787c7c4c 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -334,6 +334,7 @@ struct SynthXilinxPass : public ScriptPass if (help_mode || !nodsp) { run("techmap -map +/xilinx/dsp_map.v", "(skip if '-nodsp')"); run("xilinx_dsp", " (skip if '-nodsp')"); + run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); } if (help_mode) { run("simplemap t:$mux", " ('-widemux' only)"); From 915f4e34bfdf1fd2b9f97d1c15a55e2c4c49f428 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 13:20:34 -0700 Subject: [PATCH 092/356] DSP_MINWIDTH -> DSP_{A,B,Y}_MINWIDTH --- techlibs/common/mul2dsp.v | 15 +++++++++++---- techlibs/ice40/synth_ice40.cc | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 99afce18c..5ff0e03aa 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -52,7 +52,7 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y; generate - if (A_SIGNED != B_SIGNED || A_WIDTH <= 1 || B_WIDTH <= 1) + if (A_SIGNED != B_SIGNED) wire _TECHMAP_FAIL_ = 1; // NB: A_SIGNED == B_SIGNED from here else if (A_WIDTH < B_WIDTH) @@ -103,10 +103,17 @@ module \$__mul (A, B, Y); genvar i; generate - if (A_WIDTH <= 1 || B_WIDTH <= 1) + if (0) begin end +`ifdef DSP_A_MINWIDTH + else if (A_WIDTH < `DSP_A_MINWIDTH) wire _TECHMAP_FAIL_ = 1; -`ifdef DSP_MINWIDTH - else if (A_WIDTH+B_WIDTH < `DSP_MINWIDTH || Y_WIDTH < `DSP_MINWIDTH) +`endif +`ifdef DSP_B_MINWIDTH + else if (B_WIDTH < `DSP_B_MINWIDTH) + wire _TECHMAP_FAIL_ = 1; +`endif +`ifdef DSP_Y_MINWIDTH + else if (Y_WIDTH < `DSP_Y_MINWIDTH) wire _TECHMAP_FAIL_ = 1; `endif else if (A_WIDTH > `DSP_A_MAXWIDTH) begin diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index ce88a0542..2cc5fd5fd 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -266,7 +266,7 @@ struct SynthIce40Pass : public ScriptPass run("opt_expr"); run("opt_clean"); if (help_mode || dsp) { - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_MINWIDTH=11 -D DSP_NAME=$__MUL16X16", "(if -dsp)"); + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 -D DSP_NAME=$__MUL16X16", "(if -dsp)"); run("opt_expr", " (if -dsp)"); run("wreduce", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); From 65de9aaaa9d744686e235ff8701cd997cd2dc891 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 14:29:00 -0700 Subject: [PATCH 093/356] Add DSP_SIGNEDONLY back --- techlibs/common/mul2dsp.v | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 5ff0e03aa..6cd5128a6 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -55,6 +55,22 @@ module \$mul (A, B, Y); if (A_SIGNED != B_SIGNED) wire _TECHMAP_FAIL_ = 1; // NB: A_SIGNED == B_SIGNED from here +`ifdef DSP_SIGNEDONLY + else if (!A_SIGNED) begin + wire [1:0] _; + \$mul #( + .A_SIGNED(1), + .B_SIGNED(1), + .A_WIDTH(A_WIDTH + 1), + .B_WIDTH(B_WIDTH + 1), + .Y_WIDTH(Y_WIDTH + 2) + ) _TECHMAP_REPLACE_ ( + .A({1'b0, A}), + .B({1'b0, B}), + .Y({_, Y}) + ); + end +`endif else if (A_WIDTH < B_WIDTH) \$mul #( .A_SIGNED(B_SIGNED), From 105aaeaf598a04020fa5030c947f623f0daa38da Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 14:33:16 -0700 Subject: [PATCH 094/356] Trim Y_WIDTH --- techlibs/common/mul2dsp.v | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 6cd5128a6..8e37201e2 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -56,20 +56,18 @@ module \$mul (A, B, Y); wire _TECHMAP_FAIL_ = 1; // NB: A_SIGNED == B_SIGNED from here `ifdef DSP_SIGNEDONLY - else if (!A_SIGNED) begin - wire [1:0] _; + else if (!A_SIGNED) \$mul #( .A_SIGNED(1), .B_SIGNED(1), .A_WIDTH(A_WIDTH + 1), .B_WIDTH(B_WIDTH + 1), - .Y_WIDTH(Y_WIDTH + 2) + .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( .A({1'b0, A}), .B({1'b0, B}), - .Y({_, Y}) + .Y(Y) ); - end `endif else if (A_WIDTH < B_WIDTH) \$mul #( From ed7540a46f22151d6c87205df92bc52f5e875130 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 15:10:43 -0700 Subject: [PATCH 095/356] Pack P register properly --- passes/pmgen/xilinx_dsp.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index d87d63670..be510b4cb 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -86,14 +86,16 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) else D = st.ffP->getPort("\\D"); SigSpec Q = st.ffP->getPort("\\Q"); - P.replace(D, Q); - cell->setPort("\\P", Q); + P.replace(pm.sigmap(D), Q); + cell->setPort("\\P", P); cell->setParam("\\PREG", State::S1); if (st.ffP->type == "$dff") cell->setPort("\\CEP", State::S1); else if (st.ffP->type == "$dffe") cell->setPort("\\CEP", st.ffP->getPort("\\EN")); else log_abort(); + + st.ffP->connections_.at("\\Q").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); } log(" clock: %s (%s)", log_signal(st.clock), "posedge"); From c39b1a6fcf648203df10d640c72e073f455ddc32 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 1 Aug 2019 15:13:18 -0700 Subject: [PATCH 096/356] Add comment about supporting $dffe in ice40_dsp --- passes/pmgen/ice40_dsp.pmg | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 040332539..b6da1d2f6 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -12,6 +12,7 @@ match mul endmatch match ffA + // TODO: Support $dffe too by checking if all enable signals are identical select ffA->type.in($dff) filter !port(mul, \A).remove_const().empty() filter includes(port(ffA, \Q).to_sigbit_set(), port(mul, \A).remove_const().to_sigbit_set()) From 7a563d0b92b3b5c837fca9647a43a01e258072a5 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 6 Aug 2019 13:23:42 +0100 Subject: [PATCH 097/356] [wip] DSP48E1 sim model improvements Signed-off-by: David Shah --- techlibs/xilinx/cells_sim.v | 83 +++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 33b2a8f62..9437a057b 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -494,14 +494,81 @@ module DSP48E1 ( `endif end - reg signed [29:0] Ar; - reg signed [17:0] Br; + reg signed [29:0] Ar1, Ar2; + reg signed [24:0] Dr; + reg signed [17:0] Br1, Br2; reg signed [47:0] Pr; + reg [4:0] INMODEr; generate - if (AREG == 1) begin always @(posedge CLK) if (CEA2) Ar <= A; end - else always @* Ar <= A; - if (BREG == 1) begin always @(posedge CLK) if (CEB2) Br <= B; end - else always @* Br <= B; + if (AREG == 2) begin + always @(posedge CLK) + if (RSTA) begin + Ar1 <= 30'b0; + Ar2 <= 30'b0; + end else begin + if (CEA1) Ar1 <= A; + if (CEA2) Ar2 <= Ar1; + end + end else if (AREG == 1) begin + always @(posedge CLK) + if (RSTA) begin + Ar1 <= 30'b0; + Ar2 <= 30'b0; + end else begin + if (CEA1) Ar1 <= A; + if (CEA2) Ar2 <= A; + end + end else begin + always @* Ar1 <= A; + always @* Ar2 <= A; + end + + if (BREG == 2) begin + always @(posedge CLK) + if (RSTB) begin + Br1 <= 18'b0; + Br2 <= 18'b0; + end else begin + if (CEB1) Br1 <= B; + if (CEB2) Br2 <= Br1; + end + end else if (AREG == 1) begin + always @(posedge CLK) + if (RSTB) begin + Br1 <= 18'b0; + Br2 <= 18'b0; + end else begin + if (CEB1) Br1 <= B; + if (CEB2) Br2 <= B; + end + end else begin + always @* Br1 <= B; + always @* Br2 <= B; + end + + if (DREG == 1) begin always @(posedge CLK) if (RSTD) Dr <= 25'b0; else if (CED) Dr <= D; end + else always @* Dr <= D; + + if (INMODEREG == 1) begin always @(posedge CLK) if (RSTINMODE) INMODEr <= 5'b0; else if (CEINMODE) INMODEr <= INMODE; end + else always @* INMODEr <= INMODE; + endgenerate + + wire signed [29:0] Ar12_muxed = INMODEr[0] ? Ar1 : Ar2; + wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed; + wire signed [24:0] Dr_gated = INMODEr[2] ? Dr : 25'b0; + wire signed [24:0] AD_result = INMODEr[3] ? (Dr_gated - Ar12_gated) : (Dr_gated + Ar12_gated); + reg signed [24:0] ADr; + + generate + if (ADREG == 1) begin always @(posedge CLK) if (RSTD) ADr <= 25'b0; else if (CEAD) ADr <= AD_result; end + else always @* ADr <= AD_result; + endgenerate + + wire signed [24:0] A_MULT; + wire signed [24:0] B_MULT = INMODEr[4] ? Br1 : Br2; + generate + if (USE_DPORT == "TRUE") assign A_MULT = ADr; + else assign A_MULT = Ar12_gated; endgenerate always @* begin @@ -516,11 +583,11 @@ module DSP48E1 ( if (PCIN != 48'b0) $fatal(1, "Unsupported PCIN value"); if (CARRYIN != 1'b0) $fatal(1, "Unsupported CARRYIN value"); `endif - Pr[42:0] <= $signed(Ar[24:0]) * Br; + Pr[42:0] <= A_MULT * B_MULT; end generate - if (PREG == 1) begin always @(posedge CLK) if (CEP) P <= Pr; end + if (PREG == 1) begin always @(posedge CLK) if (RSTP) P <= 48'b0; else if (CEP) P <= Pr; end else always @* P <= Pr; endgenerate From c43b0c4b49235da5aee658413a2a6f880aff09b0 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 6 Aug 2019 18:47:18 +0100 Subject: [PATCH 098/356] [wip] DSP48E1 sim model improvements Signed-off-by: David Shah --- techlibs/xilinx/cells_sim.v | 145 ++++++++++++++++++++++++++++++------ 1 file changed, 121 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 9437a057b..bc8a2d8f0 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -494,19 +494,35 @@ module DSP48E1 ( `endif end + wire signed [29:0] A_muxed; + wire signed [17:0] B_muxed; + + generate + if (A_INPUT == "CASCADE") assign A_muxed = ACIN; + else assign A_muxed = A; + + if (B_INPUT == "CASCADE") assign B_muxed = BCIN; + else assign B_muxed = B; + endgenerate + reg signed [29:0] Ar1, Ar2; reg signed [24:0] Dr; reg signed [17:0] Br1, Br2; - reg signed [47:0] Pr; + reg signed [47:0] Cr; reg [4:0] INMODEr; + reg [6:0] OPMODEr; + reg [3:0] ALUMODEr; + reg [2:0] CARRYINSELr; + generate + // Configurable A register if (AREG == 2) begin always @(posedge CLK) if (RSTA) begin Ar1 <= 30'b0; Ar2 <= 30'b0; end else begin - if (CEA1) Ar1 <= A; + if (CEA1) Ar1 <= A_muxed; if (CEA2) Ar2 <= Ar1; end end else if (AREG == 1) begin @@ -515,21 +531,22 @@ module DSP48E1 ( Ar1 <= 30'b0; Ar2 <= 30'b0; end else begin - if (CEA1) Ar1 <= A; - if (CEA2) Ar2 <= A; + if (CEA1) Ar1 <= A_muxed; + if (CEA2) Ar2 <= A_muxed; end end else begin - always @* Ar1 <= A; - always @* Ar2 <= A; + always @* Ar1 <= A_muxed; + always @* Ar2 <= A_muxed; end + // Configurable A register if (BREG == 2) begin always @(posedge CLK) if (RSTB) begin Br1 <= 18'b0; Br2 <= 18'b0; end else begin - if (CEB1) Br1 <= B; + if (CEB1) Br1 <= B_muxed; if (CEB2) Br2 <= Br1; end end else if (AREG == 1) begin @@ -538,21 +555,41 @@ module DSP48E1 ( Br1 <= 18'b0; Br2 <= 18'b0; end else begin - if (CEB1) Br1 <= B; - if (CEB2) Br2 <= B; + if (CEB1) Br1 <= B_muxed; + if (CEB2) Br2 <= B_muxed; end end else begin - always @* Br1 <= B; - always @* Br2 <= B; + always @* Br1 <= B_muxed; + always @* Br2 <= B_muxed; end + // C and D registers + if (CREG == 1) begin always @(posedge CLK) if (RSTC) Cr <= 48'b0; else if (CEC) Cr <= D; end + else always @* Cr <= C; + if (DREG == 1) begin always @(posedge CLK) if (RSTD) Dr <= 25'b0; else if (CED) Dr <= D; end else always @* Dr <= D; + // Control registers if (INMODEREG == 1) begin always @(posedge CLK) if (RSTINMODE) INMODEr <= 5'b0; else if (CEINMODE) INMODEr <= INMODE; end else always @* INMODEr <= INMODE; + if (OPMODEREG == 1) begin always @(posedge CLK) if (RSTCTRL) OPMODEr <= 7'b0; else if (CECTRL) OPMODEr <= OPMODE; end + else always @* OPMODEr <= OPMODE; + if (ALUMODEREG == 1) begin always @(posedge CLK) if (RSTALUMODE) ALUMODEr <= 4'b0; else if (CEALUMODE) ALUMODEr <= ALUMODE; end + else always @* ALUMODEr <= ALUMODE; + if (CARRYINSELREG == 1) begin always @(posedge CLK) if (RSTCTRL) CARRYINSELr <= 3'b0; else if (CECTRL) CARRYINSELr <= CARRYINSEL; end + else always @* CARRYINSELr <= CARRYINSEL; endgenerate + // A and B cascsde + generate + if (ACASCREG == 1 && AREG == 2) assign ACOUT = Ar1; + else assign ACOUT = Ar2; + if (BCASCREG == 1 && BREG == 2) assign BCOUT = Br1; + else assign BCOUT = Br2; + endgenerate + + // A/D input selection and pre-adder wire signed [29:0] Ar12_muxed = INMODEr[0] ? Ar1 : Ar2; wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed; wire signed [24:0] Dr_gated = INMODEr[2] ? Dr : 25'b0; @@ -564,31 +601,91 @@ module DSP48E1 ( else always @* ADr <= AD_result; endgenerate + // 25x18 multiplier wire signed [24:0] A_MULT; - wire signed [24:0] B_MULT = INMODEr[4] ? Br1 : Br2; + wire signed [17:0] B_MULT = INMODEr[4] ? Br1 : Br2; generate if (USE_DPORT == "TRUE") assign A_MULT = ADr; else assign A_MULT = Ar12_gated; endgenerate + wire signed [42:0] M = A_MULT * B_MULT; + reg signed [42:0] Mr; + + // Multiplier result register + generate + if (MREG == 1) begin always @(posedge CLK) if (RSTM) Mr <= 43'b0; else if (CEM) Mr <= M; end + else always @* Mr <= M; + endgenerate + + // X, Y and Z ALU inputs + reg signed [47:0] X, Y, Z; + always @* begin - Pr <= {48{1'bx}}; + // X multiplexer + case (OPMODEr[1:0]) + 2'b00: X = 48'b0; + 2'b01: X = $signed(M); `ifdef __ICARUS__ - if (INMODE != 4'b0000) $fatal(1, "Unsupported INMODE value"); - if (ALUMODE != 4'b0000) $fatal(1, "Unsupported ALUMODE value"); - if (OPMODE != 7'b000101) $fatal(1, "Unsupported OPMODE value"); - if (CARRYINSEL != 3'b000) $fatal(1, "Unsupported CARRYINSEL value"); - if (ACIN != 30'b0) $fatal(1, "Unsupported ACIN value"); - if (BCIN != 18'b0) $fatal(1, "Unsupported BCIN value"); - if (PCIN != 48'b0) $fatal(1, "Unsupported PCIN value"); - if (CARRYIN != 1'b0) $fatal(1, "Unsupported CARRYIN value"); + if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01"); +`endif + 2'b10: X = P; +`ifdef __ICARUS__ + if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10"); +`endif + 2'b11: X = $signed({Ar2, Br2}); + default: X = 48'bx; + endcase + + // Y multiplexer + case (OPMODEr[3:2]) + 2'b00: Y = 48'b0; + 2'b01: Y = 48'b0; // FIXME: more accurate partial product modelling? +`ifdef __ICARUS__ + if (OPMODEr[1:0] != 2'b01) $fatal(1, "OPMODEr[1:0] must be 2'b01 when OPMODEr[3:2] is 2'b01"); +`endif + 2'b10: Y = {48{1'b1}}; + 2'b11: Y = C; + default: Y = 48'bx; + endcase + + // Z multiplexer + case (OPMODEr[6:4]) + 3'b000: Z = 48'b0; + 3'b001: Z = PCIN; + 3'b010: Z = P; +`ifdef __ICARUS__ + if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010"); +`endif + 3'b011: Z = C; + 3'b100: Z = P; +`ifdef __ICARUS__ + if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100"); + if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100"); +`endif + 3'b101: Z = $signed(PCIN[47:17]); + 3'b110: Z = $signed(P[47:17]); + default: Z = 48'bx; + endcase + end + + wire alu_cin = 1'b0; // FIXME* + + wire [47:0] Z_muxinv = ALUMODEr[0] ? ~Z : Z; + wire [47:0] xor_xyz = X ^ Y ^ Z_muxinv; + wire [47:0] maj_xyz = (X & Y) | (X & Z) | (X & Y); + + + + always @* begin +`ifdef __ICARUS__ + if (CARRYINSEL != 3'b000) $fatal(1, "Unsupported CARRYINSEL value"); `endif - Pr[42:0] <= A_MULT * B_MULT; end generate - if (PREG == 1) begin always @(posedge CLK) if (RSTP) P <= 48'b0; else if (CEP) P <= Pr; end - else always @* P <= Pr; + if (PREG == 1) begin always @(posedge CLK) if (RSTP) P <= 48'b0; else if (CEP) P <= Mr; end + else always @* P <= Mr; endgenerate endmodule From fe95807f162704d1f9c09ba8d665092c92574cce Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 7 Aug 2019 13:09:12 +0100 Subject: [PATCH 099/356] [wip] DSP48E1 sim model improvements Signed-off-by: David Shah --- techlibs/xilinx/cells_sim.v | 88 ++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index bc8a2d8f0..7e7199f0b 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -382,9 +382,9 @@ endmodule module DSP48E1 ( output [29:0] ACOUT, output [17:0] BCOUT, - output CARRYCASCOUT, - output [3:0] CARRYOUT, - output MULTSIGNOUT, + output reg CARRYCASCOUT, + output reg [3:0] CARRYOUT, + output reg MULTSIGNOUT, output OVERFLOW, output reg signed [47:0] P, output PATTERNBDETECT, @@ -669,13 +669,70 @@ module DSP48E1 ( endcase end + // ALU core + wire alu_cin = 1'b0; // FIXME* wire [47:0] Z_muxinv = ALUMODEr[0] ? ~Z : Z; wire [47:0] xor_xyz = X ^ Y ^ Z_muxinv; wire [47:0] maj_xyz = (X & Y) | (X & Z) | (X & Y); - + wire [47:0] xor_xyz_muxed = ALUMODEr[3] ? maj_xyz : xor_xyz; + wire [47:0] maj_xyz_gated = ALUMODEr[2] ? 48'b0 : maj_xyz; + + wire [48:0] maj_xyz_simd_gated; + wire [3:0] int_carry_in, int_carry_out, ext_carry_out; + wire [47:0] alu_sum; + assign int_carry_in[0] = 1'b0; + + generate + if (USE_SIMD == "FOUR12") begin + assign maj_xyz_simd_gated = { + maj_xyz_gated[47:36], + 1'b0, maj_xyz_gated[34:24], + 1'b0, maj_xyz_gated[22:12], + 1'b0, maj_xyz_gated[10:0], + alu_cin + }; + assign int_carry_in[3:1] = 3'b000; + assign ext_carry_out = { + int_carry_out[3], + maj_xyz_gated[35] ^ int_carry_out[2], + maj_xyz_gated[23] ^ int_carry_out[1], + maj_xyz_gated[11] ^ int_carry_out[0] + }; + end else if (USE_SIMD == "TWO24") begin + assign maj_xyz_simd_gated = { + maj_xyz_gated[47:24], + 1'b0, maj_xyz_gated[22:0], + alu_cin + }; + assign int_carry_in[3:1] = {int_carry_out[2], 1'b0, int_carry_out[0]}; + assign ext_carry_out = { + int_carry_out[3], + 1'bx, + maj_xyz_gated[23] ^ int_carry_out[1], + 1'bx + }; + end else if (USE_SIMD == "FOUR48") begin + assign maj_xyz_simd_gated = {maj_xyz_gated, alu_cin}; + assign int_carry_in[3:1] = int_carry_out[2:0]; + assign ext_carry_out = { + int_carry_out[3], + 3'bxxx + }; + end + + genvar i; + for (i = 0; i < 4; i++) + assign {int_carry_out[i], alu_sum[i*12 +: 12]} = {1'b0, maj_xyz_simd_gated[i*12 +: ((i == 3) ? 13 : 12)]} + + xor_xyz_muxed[i*12 +: 12] + int_carry_in[i]; + endgenerate + + wire signed [47:0] Pd = ALUMODEr[1] ? ~alu_sum : alu_sum; + wire [3:0] CARRYOUTd = (ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out; + wire CARRYCASCOUTd = ext_carry_out[3]; + wire MULTSIGNOUTd = Mr[42]; always @* begin `ifdef __ICARUS__ @@ -684,8 +741,27 @@ module DSP48E1 ( end generate - if (PREG == 1) begin always @(posedge CLK) if (RSTP) P <= 48'b0; else if (CEP) P <= Mr; end - else always @* P <= Mr; + if (PREG == 1) begin + always @(posedge CLK) + if (RSTP) begin + P <= 48'b0; + CARRYOUT <= 4'b0; + CARRYCASCOUT <= 1'b0; + MULTSIGNOUT <= 1'b0; + end else if (CEP) begin + P <= Pd; + CARRYOUT <= CARRYOUTd; + CARRYCASCOUT <= CARRYCASCOUTd; + MULTSIGNOUT <= MULTSIGNOUTd; + end + end else begin + always @* begin + P = Pd; + CARRYOUT = CARRYOUTd; + CARRYCASCOUT = CARRYCASCOUTd; + MULTSIGNOUT = MULTSIGNOUTd; + end + end endgenerate endmodule From cdf9c801347693c273309694685b2080ef00fd02 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 7 Aug 2019 12:57:10 -0700 Subject: [PATCH 100/356] Do not pack registers if (* keep *) --- passes/pmgen/ice40_dsp.pmg | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index b6da1d2f6..f1f533187 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -23,6 +23,10 @@ code sigA clock clock_pol sigA = port(mul, \A); if (ffA) { + for (auto b : port(ffA, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + clock = port(ffA, \CLK).as_bit(); clock_pol = param(ffA, \CLK_POLARITY).as_bool(); @@ -41,6 +45,10 @@ code sigB clock clock_pol sigB = port(mul, \B); if (ffB) { + for (auto b : port(ffB, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + SigBit c = port(ffB, \CLK).as_bit(); bool cp = param(ffB, \CLK_POLARITY).as_bool(); @@ -67,6 +75,10 @@ code sigH sigO clock clock_pol if (ffH) { sigH = port(ffH, \Q); + for (auto b : sigH) + if (b.wire->get_bool_attribute(\keep)) + reject; + sigO = sigH; SigBit c = port(ffH, \CLK).as_bit(); @@ -159,6 +171,10 @@ endmatch code clock clock_pol sigO sigCD if (ffO_lo || ffO_hi) { if (ffO_lo) { + for (auto b : port(ffO_lo, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + SigBit c = port(ffO_lo, \CLK).as_bit(); bool cp = param(ffO_lo, \CLK_POLARITY).as_bool(); @@ -173,6 +189,10 @@ code clock clock_pol sigO sigCD } if (ffO_hi) { + for (auto b : port(ffO_hi, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + SigBit c = port(ffO_hi, \CLK).as_bit(); bool cp = param(ffO_hi, \CLK_POLARITY).as_bool(); From d90b8b081a6102303f2392fc21164fddde90e587 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 7 Aug 2019 13:58:26 -0700 Subject: [PATCH 101/356] Do not SigSpec::extract() beyond bounds --- passes/pmgen/ice40_dsp.cc | 4 ++-- passes/pmgen/ice40_dsp.pmg | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index f6ae3a13f..5e87d6497 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -224,11 +224,11 @@ void create_ice40_dsp(ice40_dsp_pm &pm) pm.autoremove(st.ffH); pm.autoremove(st.addAB); if (st.ffO_lo) { - SigSpec O = st.sigO.extract(0,16); + SigSpec O = st.sigO.extract(0,GetSize(st.ffO_lo)); st.ffO_lo->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); } if (st.ffO_hi) { - SigSpec O = st.sigO.extract(16,16); + SigSpec O = st.sigO.extract(16,GetSize(st.ffo_hi)); st.ffO_hi->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); } } diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index f1f533187..8b1ac2563 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -156,15 +156,17 @@ endcode match ffO_lo select ffO_lo->type.in($dff) - filter nusers(sigO.extract(0,16)) == 2 - filter includes(port(ffO_lo, \D).to_sigbit_set(), sigO.extract(0,16).to_sigbit_set()) + filter GetSize(sigO) >= param(ffO_lo, \WIDTH).as_int() + filter nusers(sigO.extract(0,param(ffO_lo, \WIDTH).as_int())) == 2 + filter includes(port(ffO_lo, \D).to_sigbit_set(), sigO.extract(0,param(ffO_lo, \WIDTH).as_int()).to_sigbit_set()) optional endmatch match ffO_hi select ffO_hi->type.in($dff) - filter nusers(sigO.extract(16,16)) == 2 - filter includes(port(ffO_hi, \D).to_sigbit_set(), sigO.extract(16,16).to_sigbit_set()) + filter GetSize(sigO) >= 16+param(ffO_hi, \WIDTH).as_int() + filter nusers(sigO.extract(16,param(ffO_hi, \WIDTH).as_int())) == 2 + filter includes(port(ffO_hi, \D).to_sigbit_set(), sigO.extract(16,param(ffO_hi, \WIDTH).as_int()).to_sigbit_set()) optional endmatch @@ -184,7 +186,7 @@ code clock clock_pol sigO sigCD clock = c; clock_pol = cp; - if (port(ffO_lo, \Q) != sigO.extract(0,16)) + if (port(ffO_lo, \Q) != sigO.extract(0,param(ffO_lo, \WIDTH).as_int())) sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q)); } @@ -202,7 +204,7 @@ code clock clock_pol sigO sigCD clock = c; clock_pol = cp; - if (port(ffO_hi, \Q) != sigO.extract(16,16)) + if (port(ffO_hi, \Q) != sigO.extract(16,param(ffO_hi, \WIDTH).as_int())) sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q)); } From a206aed977e92a63aa52137690e20897f27df458 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 7 Aug 2019 13:59:07 -0700 Subject: [PATCH 102/356] Run "opt_expr -fine" instead of "wreduce" due to #1213 --- techlibs/ice40/synth_ice40.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 2cc5fd5fd..09759f359 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -267,8 +267,7 @@ struct SynthIce40Pass : public ScriptPass run("opt_clean"); if (help_mode || dsp) { run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 -D DSP_NAME=$__MUL16X16", "(if -dsp)"); - run("opt_expr", " (if -dsp)"); - run("wreduce", " (if -dsp)"); + run("opt_expr -fine", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); run("chtype -set $mul t:$__soft_mul","(if -dsp)"); } From fb568ddb4e2ccaab352d9d062f6b4926aca75680 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 7 Aug 2019 14:31:55 -0700 Subject: [PATCH 103/356] Fix compile error --- passes/pmgen/ice40_dsp.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 5e87d6497..45d7a34df 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -224,11 +224,11 @@ void create_ice40_dsp(ice40_dsp_pm &pm) pm.autoremove(st.ffH); pm.autoremove(st.addAB); if (st.ffO_lo) { - SigSpec O = st.sigO.extract(0,GetSize(st.ffO_lo)); + SigSpec O = st.sigO.extract(0,st.ffO_lo->getParam("\\WIDTH").as_int()); st.ffO_lo->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); } if (st.ffO_hi) { - SigSpec O = st.sigO.extract(16,GetSize(st.ffo_hi)); + SigSpec O = st.sigO.extract(16,st.ffO_hi->getParam("\\WIDTH").as_int()); st.ffO_hi->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); } } From ccfb4ff2a9d1cdf8205481042b0c22c39fc20e88 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 8 Aug 2019 09:31:34 +0100 Subject: [PATCH 104/356] [wip] sim model testing Signed-off-by: David Shah --- techlibs/xilinx/cells_sim.v | 91 ++++---- techlibs/xilinx/tests/.gitignore | 1 + techlibs/xilinx/tests/test_dsp_model.v | 310 +++++++++++++++++++++++++ 3 files changed, 361 insertions(+), 41 deletions(-) create mode 100644 techlibs/xilinx/tests/test_dsp_model.v diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 7e7199f0b..a6ab98926 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -463,27 +463,10 @@ module DSP48E1 ( initial begin `ifdef __ICARUS__ - if (ACASCREG != 0) $fatal(1, "Unsupported ACASCREG value"); - if (ADREG != 0) $fatal(1, "Unsupported ADREG value"); - if (ALUMODEREG != 0) $fatal(1, "Unsupported ALUMODEREG value"); - if (AREG == 2) $fatal(1, "Unsupported AREG value"); if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value"); - if (A_INPUT != "DIRECT") $fatal(1, "Unsupported A_INPUT value"); - if (BCASCREG != 0) $fatal(1, "Unsupported BCASCREG value"); - if (BREG == 2) $fatal(1, "Unsupported BREG value"); - if (B_INPUT != "DIRECT") $fatal(1, "Unsupported B_INPUT value"); - if (CARRYINREG != 0) $fatal(1, "Unsupported CARRYINREG value"); - if (CARRYINSELREG != 0) $fatal(1, "Unsupported CARRYINSELREG value"); - if (CREG != 0) $fatal(1, "Unsupported CREG value"); - if (DREG != 0) $fatal(1, "Unsupported DREG value"); - if (INMODEREG != 0) $fatal(1, "Unsupported INMODEREG value"); - if (MREG != 0) $fatal(1, "Unsupported MREG value"); - if (OPMODEREG != 0) $fatal(1, "Unsupported OPMODEREG value"); //if (PREG != 0) $fatal(1, "Unsupported PREG value"); if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value"); if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value"); - if (USE_DPORT != "FALSE") $fatal(1, "Unsupported USE_DPORT value"); - if (USE_MULT != "MULTIPLY") $fatal(1, "Unsupported USE_MULT value"); if (USE_PATTERN_DETECT != "NO_PATDET") $fatal(1, "Unsupported USE_PATTERN_DETECT value"); if (USE_SIMD != "ONE48") $fatal(1, "Unsupported USE_SIMD value"); if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value"); @@ -505,14 +488,14 @@ module DSP48E1 ( else assign B_muxed = B; endgenerate - reg signed [29:0] Ar1, Ar2; - reg signed [24:0] Dr; - reg signed [17:0] Br1, Br2; - reg signed [47:0] Cr; - reg [4:0] INMODEr; - reg [6:0] OPMODEr; - reg [3:0] ALUMODEr; - reg [2:0] CARRYINSELr; + reg signed [29:0] Ar1 = 30'b0, Ar2 = 30'b0; + reg signed [24:0] Dr = 25'b0; + reg signed [17:0] Br1 = 18'b0, Br2 = 18'b0; + reg signed [47:0] Cr = 48'b0; + reg [4:0] INMODEr = 5'b0; + reg [6:0] OPMODEr = 7'b0; + reg [3:0] ALUMODEr = 4'b0; + reg [2:0] CARRYINSELr = 3'b0; generate // Configurable A register @@ -594,7 +577,7 @@ module DSP48E1 ( wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed; wire signed [24:0] Dr_gated = INMODEr[2] ? Dr : 25'b0; wire signed [24:0] AD_result = INMODEr[3] ? (Dr_gated - Ar12_gated) : (Dr_gated + Ar12_gated); - reg signed [24:0] ADr; + reg signed [24:0] ADr = 25'b0; generate if (ADREG == 1) begin always @(posedge CLK) if (RSTD) ADr <= 25'b0; else if (CEAD) ADr <= AD_result; end @@ -610,7 +593,7 @@ module DSP48E1 ( endgenerate wire signed [42:0] M = A_MULT * B_MULT; - reg signed [42:0] Mr; + reg signed [42:0] Mr = 43'b0; // Multiplier result register generate @@ -625,14 +608,16 @@ module DSP48E1 ( // X multiplexer case (OPMODEr[1:0]) 2'b00: X = 48'b0; - 2'b01: X = $signed(M); + 2'b01: begin X = $signed(M); `ifdef __ICARUS__ if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01"); `endif - 2'b10: X = P; + end + 2'b10: begin X = P; `ifdef __ICARUS__ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10"); `endif + end 2'b11: X = $signed({Ar2, Br2}); default: X = 48'bx; endcase @@ -640,10 +625,11 @@ module DSP48E1 ( // Y multiplexer case (OPMODEr[3:2]) 2'b00: Y = 48'b0; - 2'b01: Y = 48'b0; // FIXME: more accurate partial product modelling? + 2'b01: begin Y = 48'b0; // FIXME: more accurate partial product modelling? `ifdef __ICARUS__ if (OPMODEr[1:0] != 2'b01) $fatal(1, "OPMODEr[1:0] must be 2'b01 when OPMODEr[3:2] is 2'b01"); `endif + end 2'b10: Y = {48{1'b1}}; 2'b11: Y = C; default: Y = 48'bx; @@ -653,26 +639,54 @@ module DSP48E1 ( case (OPMODEr[6:4]) 3'b000: Z = 48'b0; 3'b001: Z = PCIN; - 3'b010: Z = P; + 3'b010: begin Z = P; `ifdef __ICARUS__ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010"); `endif + end 3'b011: Z = C; - 3'b100: Z = P; + 3'b100: begin Z = P; `ifdef __ICARUS__ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100"); if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100"); `endif + end 3'b101: Z = $signed(PCIN[47:17]); 3'b110: Z = $signed(P[47:17]); default: Z = 48'bx; endcase end + // Carry in + wire A24_xnor_B17d = A_MULT[24] ~^ B_MULT[17]; + reg CARRYINr, A24_xnor_B17; + generate + if (CARRYINREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) CARRYINr <= 1'b0; else if (CECARRYIN) CARRYINr <= CARRYIN; end + else always @* CARRYINr = CARRYIN; + + if (MREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) A24_xnor_B17 <= 1'b0; else if (CECARRYIN) A24_xnor_B17 <= A24_xnor_B17d; end + else always @* A24_xnor_B17 = A24_xnor_B17d; + endgenerate + + reg cin_muxed; + + always @(*) begin + case (CARRYINSELr) + 3'b000: cin_muxed = CARRYINr; + 3'b001: cin_muxed = ~PCIN[47]; + 3'b010: cin_muxed = CARRYCASCIN; + 3'b011: cin_muxed = PCIN[47]; + 3'b100: cin_muxed = CARRYCASCOUT; + 3'b101: cin_muxed = ~P[47]; + 3'b110: cin_muxed = A24_xnor_B17; + 3'b111: cin_muxed = P[47]; + default: cin_muxed = 1'bx; + endcase + end + + wire alu_cin = (ALUMODEr[3] || ALUMODEr[2]) ? 1'b0 : cin_muxed; + // ALU core - - wire alu_cin = 1'b0; // FIXME* - wire [47:0] Z_muxinv = ALUMODEr[0] ? ~Z : Z; wire [47:0] xor_xyz = X ^ Y ^ Z_muxinv; wire [47:0] maj_xyz = (X & Y) | (X & Z) | (X & Y); @@ -730,16 +744,11 @@ module DSP48E1 ( endgenerate wire signed [47:0] Pd = ALUMODEr[1] ? ~alu_sum : alu_sum; + initial P = 48'b0; wire [3:0] CARRYOUTd = (ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out; wire CARRYCASCOUTd = ext_carry_out[3]; wire MULTSIGNOUTd = Mr[42]; - always @* begin -`ifdef __ICARUS__ - if (CARRYINSEL != 3'b000) $fatal(1, "Unsupported CARRYINSEL value"); -`endif - end - generate if (PREG == 1) begin always @(posedge CLK) diff --git a/techlibs/xilinx/tests/.gitignore b/techlibs/xilinx/tests/.gitignore index 496b87461..40d61ccce 100644 --- a/techlibs/xilinx/tests/.gitignore +++ b/techlibs/xilinx/tests/.gitignore @@ -4,3 +4,4 @@ bram1_[0-9]*/ bram2.log bram2_syn.v bram2_tb +dsp_work*/ \ No newline at end of file diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v new file mode 100644 index 000000000..2ecaabfe7 --- /dev/null +++ b/techlibs/xilinx/tests/test_dsp_model.v @@ -0,0 +1,310 @@ +`timescale 1ns / 1ps + +module testbench; + parameter integer ACASCREG = 1; + parameter integer ADREG = 1; + parameter integer ALUMODEREG = 1; + parameter integer AREG = 1; + parameter AUTORESET_PATDET = "NO_RESET"; + parameter A_INPUT = "DIRECT"; + parameter integer BCASCREG = 1; + parameter integer BREG = 1; + parameter B_INPUT = "DIRECT"; + parameter integer CARRYINREG = 1; + parameter integer CARRYINSELREG = 1; + parameter integer CREG = 1; + parameter integer DREG = 1; + parameter integer INMODEREG = 1; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter SEL_MASK = "MASK"; + parameter SEL_PATTERN = "PATTERN"; + parameter USE_DPORT = "FALSE"; + parameter USE_MULT = "MULTIPLY"; + parameter USE_PATTERN_DETECT = "NO_PATDET"; + parameter USE_SIMD = "ONE48"; + parameter [47:0] MASK = 48'h3FFFFFFFFFFF; + parameter [47:0] PATTERN = 48'h000000000000; + parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; + parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + parameter [4:0] IS_INMODE_INVERTED = 5'b0; + parameter [6:0] IS_OPMODE_INVERTED = 7'b0; + + reg CLK; + reg CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL; + reg CED, CEINMODE, CEM, CEP; + reg RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP; + reg [29:0] A, ACIN; + reg [17:0] B, BCIN; + reg [47:0] C; + reg [24:0] D; + reg [47:0] PCIN; + reg [3:0] ALUMODE; + reg [2:0] CARRYINSEL; + reg [4:0] INMODE; + reg [6:0] OPMODE; + reg CARRYCASCIN, CARRYIN, MULTSIGNIN; + + output [29:0] ACOUT, REF_ACOUT; + output [17:0] BCOUT, REF_BCOUT; + output CARRYCASCOUT, REF_CARRYCASCOUT; + output [3:0] CARRYOUT, REF_CARRYOUT; + output MULTSIGNOUT, REF_MULTSIGNOUT; + output OVERFLOW, REF_OVERFLOW; + output [47:0] P, REF_P; + output PATTERNBDETECT, REF_PATTERNBDETECT; + output PATTERNDETECT, REF_PATTERNDETECT; + output [47:0] PCOUT, REF_PCOUT; + output UNDERFLOW, REF_UNDERFLOW; + + integer errcount = 0; + + task clkcycle; + begin + #5; + CLK = ~CLK; + #10; + CLK = ~CLK; + #2; + + if (REF_P !== P) begin + $display("ERROR at %1t: REF_P=%b UUT_P=%b DIFF=%b", $time, REF_P, P, REF_P ^ P); + errcount = errcount + 1; + end + if (REF_CARRYOUT !== CARRYOUT) begin + $display("ERROR at %1t: REF_CARRYOUT=%b UUT_CARRYOUT=%b", $time, REF_CARRYOUT, CARRYOUT); + errcount = errcount + 1; + end + #3; + end + endtask + + reg config_valid = 0; + task drc; + config_valid = 1; + if (AREG != 2 && INMODE[0]) config_valid = 0; + if (BREG != 2 && INMODE[4]) config_valid = 0; + if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0; + if ((OPMODE[6:4] == 3'b010) && PREG != 1) config_valid = 0; + if ((OPMODE[6:4] == 3'b010) && (PREG != 1 || OPMODE[3:0] != 4'b1000)) config_valid = 0; + endtask + + initial begin + $dumpfile("test_dsp_model.vcd"); + $dumpvars(0, testbench); + + #2; + CLK = 1'b0; + {CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL} = 9'b111111111; + {CED, CEINMODE, CEM, CEP} = 4'b1111; + + {A, B, C, D} = 0; + {ACIN, BCIN, PCIN} = 0; + {ALUMODE, CARRYINSEL, INMODE} = 0; + {OPMODE, CARRYCASCIN, CARRYIN, MULTSIGNIN} = 0; + + {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP} = ~0; + #5; + CLK = 1'b1; + #10; + CLK = 1'b0 + #5; + CLK = 1'b1; + #10; + CLK = 1'b0; + {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP} = 0; + + repeat (300) begin + clkcycle; + do begin + A = $urandom; + ACIN = $urandom; + B = $urandom; + BCIN = $urandom; + C = {$urandom, $urandom}; + D = $urandom; + PCIN = {$urandom, $urandom}; + + {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP} = $urandom & $urandom & $urandom; + {ALUMODE, CARRYINSEL, INMODE} = $urandom & $urandom & $urandom; + OPMODE = $urandom; + {CARRYCASCIN, CARRYIN, MULTSIGNIN} = $urandom; + drc; + end while (!config_valid); + end + + if (errcount == 0) begin + $display("All tests passed."); + $finish; + end else begin + $display("Caught %1d errors.", errcount); + $stop; + end + end + + DSP48E1 #( + .ACASCREG (ACASCREG), + .ADREG (ADREG), + .ALUMODEREG (ALUMODEREG), + .AREG (AREG), + .AUTORESET_PATDET (AUTORESET_PATDET), + .A_INPUT (A_INPUT), + .BCASCREG (BCASCREG), + .BREG (BREG), + .B_INPUT (B_INPUT), + .CARRYINREG (CARRYINREG), + .CARRYINSELREG (CARRYINSELREG), + .CREG (CREG), + .DREG (DREG), + .INMODEREG (INMODEREG), + .MREG (MREG), + .OPMODEREG (OPMODEREG), + .PREG (PREG), + .SEL_MASK (SEL_MASK), + .SEL_PATTERN (SEL_PATTERN), + .USE_DPORT (USE_DPORT), + .USE_MULT (USE_MULT), + .USE_PATTERN_DETECT (USE_PATTERN_DETECT), + .USE_SIMD (USE_SIMD), + .MASK (MASK), + .PATTERN (PATTERN), + .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), + .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), + .IS_CLK_INVERTED (IS_CLK_INVERTED), + .IS_INMODE_INVERTED (IS_INMODE_INVERTED), + .IS_OPMODE_INVERTED (IS_OPMODE_INVERTED) + ) ref ( + .ACOUT (REF_ACOUT), + .BCOUT (REF_BCOUT), + .CARRYCASCOUT (REF_CARRYCASCOUT), + .CARRYOUT (REF_CARRYOUT), + .MULTSIGNOUT (REF_MULTSIGNOUT), + .OVERFLOW (REF_OVERFLOW), + .P (REF_P), + .PATTERNBDETECT(REF_PATTERNBDETECT), + .PATTERNDETECT (REF_PATTERNDETECT), + .PCOUT (REF_PCOUT), + .UNDERFLOW (REF_UNDERFLOW), + .A (A), + .ACIN (ACIN), + .ALUMODE (ALUMODE), + .B (B), + .BCIN (BCIN), + .C (C), + .CARRYCASCIN (CARRYCASCIN), + .CEA1 (CEA1), + .CEA2 (CEA2), + .CEAD (CEAD), + .CEALUMODE (CEALUMODE), + .CEB1 (CEB1), + .CEB2 (CEB2), + .CEC (CEC), + .CECARRYIN (CECARRYIN), + .CECTRL (CECTRL), + .CED (CED), + .CEINMODE (CEINMODE), + .CEM (CEM), + .CEP (CEP), + .CLK (CLK), + .D (D), + .INMODE (INMODE), + .MULTSIGNIN (MULTSIGNIN), + .OPMODE (OPMODE), + .PCIN (PCIN), + .RSTA (RSTA), + .RSTALLCARRYIN (RSTALLCARRYIN), + .RSTALUMODE (RSTALUMODE), + .RSTB (RSTB), + .RSTC (RSTC), + .RSTCTRL (RSTCTRL), + .RSTD (RSTD), + .RSTINMODE (RSTINMODE), + .RSTM (RSTM), + .RSTP (RSTP) + ); + + DSP48E1_UUT #( + .ACASCREG (ACASCREG), + .ADREG (ADREG), + .ALUMODEREG (ALUMODEREG), + .AREG (AREG), + .AUTORESET_PATDET (AUTORESET_PATDET), + .A_INPUT (A_INPUT), + .BCASCREG (BCASCREG), + .BREG (BREG), + .B_INPUT (B_INPUT), + .CARRYINREG (CARRYINREG), + .CARRYINSELREG (CARRYINSELREG), + .CREG (CREG), + .DREG (DREG), + .INMODEREG (INMODEREG), + .MREG (MREG), + .OPMODEREG (OPMODEREG), + .PREG (PREG), + .SEL_MASK (SEL_MASK), + .SEL_PATTERN (SEL_PATTERN), + .USE_DPORT (USE_DPORT), + .USE_MULT (USE_MULT), + .USE_PATTERN_DETECT (USE_PATTERN_DETECT), + .USE_SIMD (USE_SIMD), + .MASK (MASK), + .PATTERN (PATTERN), + .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), + .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), + .IS_CLK_INVERTED (IS_CLK_INVERTED), + .IS_INMODE_INVERTED (IS_INMODE_INVERTED), + .IS_OPMODE_INVERTED (IS_OPMODE_INVERTED) + ) uut ( + .ACOUT (ACOUT), + .BCOUT (BCOUT), + .CARRYCASCOUT (CARRYCASCOUT), + .CARRYOUT (CARRYOUT), + .MULTSIGNOUT (MULTSIGNOUT), + .OVERFLOW (OVERFLOW), + .P (P), + .PATTERNBDETECT(PATTERNBDETECT), + .PATTERNDETECT (PATTERNDETECT), + .PCOUT (PCOUT), + .UNDERFLOW (UNDERFLOW), + .A (A), + .ACIN (ACIN), + .ALUMODE (ALUMODE), + .B (B), + .BCIN (BCIN), + .C (C), + .CARRYCASCIN (CARRYCASCIN), + .CEA1 (CEA1), + .CEA2 (CEA2), + .CEAD (CEAD), + .CEALUMODE (CEALUMODE), + .CEB1 (CEB1), + .CEB2 (CEB2), + .CEC (CEC), + .CECARRYIN (CECARRYIN), + .CECTRL (CECTRL), + .CED (CED), + .CEINMODE (CEINMODE), + .CEM (CEM), + .CEP (CEP), + .CLK (CLK), + .D (D), + .INMODE (INMODE), + .MULTSIGNIN (MULTSIGNIN), + .OPMODE (OPMODE), + .PCIN (PCIN), + .RSTA (RSTA), + .RSTALLCARRYIN (RSTALLCARRYIN), + .RSTALUMODE (RSTALUMODE), + .RSTB (RSTB), + .RSTC (RSTC), + .RSTCTRL (RSTCTRL), + .RSTD (RSTD), + .RSTINMODE (RSTINMODE), + .RSTM (RSTM), + .RSTP (RSTP) + ); + + +endmodule From f0f352e97164692572ce41801abd62cf5641c44f Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 8 Aug 2019 10:05:11 +0100 Subject: [PATCH 105/356] [wip] sim model testing Signed-off-by: David Shah --- techlibs/xilinx/cells_sim.v | 4 +- techlibs/xilinx/tests/.gitignore | 6 ++- techlibs/xilinx/tests/test_dsp_model.sh | 11 ++++ techlibs/xilinx/tests/test_dsp_model.v | 71 ++++++++++++++++++++----- 4 files changed, 77 insertions(+), 15 deletions(-) create mode 100644 techlibs/xilinx/tests/test_dsp_model.sh diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index a6ab98926..4e26ea5c9 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -728,7 +728,7 @@ module DSP48E1 ( maj_xyz_gated[23] ^ int_carry_out[1], 1'bx }; - end else if (USE_SIMD == "FOUR48") begin + end else begin assign maj_xyz_simd_gated = {maj_xyz_gated, alu_cin}; assign int_carry_in[3:1] = int_carry_out[2:0]; assign ext_carry_out = { @@ -738,7 +738,7 @@ module DSP48E1 ( end genvar i; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i = i + 1) assign {int_carry_out[i], alu_sum[i*12 +: 12]} = {1'b0, maj_xyz_simd_gated[i*12 +: ((i == 3) ? 13 : 12)]} + xor_xyz_muxed[i*12 +: 12] + int_carry_in[i]; endgenerate diff --git a/techlibs/xilinx/tests/.gitignore b/techlibs/xilinx/tests/.gitignore index 40d61ccce..ef3699bd2 100644 --- a/techlibs/xilinx/tests/.gitignore +++ b/techlibs/xilinx/tests/.gitignore @@ -4,4 +4,8 @@ bram1_[0-9]*/ bram2.log bram2_syn.v bram2_tb -dsp_work*/ \ No newline at end of file +dsp_work*/ +test_dsp_model_ref.v +test_dsp_model_uut.v +test_dsp_model +*.vcd diff --git a/techlibs/xilinx/tests/test_dsp_model.sh b/techlibs/xilinx/tests/test_dsp_model.sh new file mode 100644 index 000000000..5455294da --- /dev/null +++ b/techlibs/xilinx/tests/test_dsp_model.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -ex +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 +fi +for tb in mult_noreg_nopreadd_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 + vvp -N ./test_dsp_model +done diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v index 2ecaabfe7..f8039aa15 100644 --- a/techlibs/xilinx/tests/test_dsp_model.v +++ b/techlibs/xilinx/tests/test_dsp_model.v @@ -83,12 +83,21 @@ module testbench; reg config_valid = 0; task drc; - config_valid = 1; - if (AREG != 2 && INMODE[0]) config_valid = 0; - if (BREG != 2 && INMODE[4]) config_valid = 0; - if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0; - if ((OPMODE[6:4] == 3'b010) && PREG != 1) config_valid = 0; - if ((OPMODE[6:4] == 3'b010) && (PREG != 1 || OPMODE[3:0] != 4'b1000)) config_valid = 0; + begin + config_valid = 1; + if (AREG != 2 && INMODE[0]) config_valid = 0; + if (BREG != 2 && INMODE[4]) config_valid = 0; + if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0; + if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0; + if ((OPMODE[6:4] == 3'b010 || OPMODE[6:4] == 3'b110) && PREG != 1) config_valid = 0; + if ((OPMODE[6:4] == 3'b100) && (PREG != 1 || OPMODE[3:0] != 4'b1000)) config_valid = 0; + if ((CARRYINSEL == 3'b100 || CARRYINSEL == 3'b101 || CARRYINSEL == 3'b111) && (PREG != 1)) config_valid = 0; + if (OPMODE[6:4] == 3'b111) config_valid = 0; + if ((ALUMODE[3:2] == 2'b01 || ALUMODE[3:2] == 2'b11) && OPMODE[3:2] != 2'b00 && OPMODE[3:2] != 2'b10) config_valid = 0; + if ((OPMODE[3:0] == 4'b0101) && CARRYINSEL == 3'b010) config_valid = 0; + if (CARRYINSEL == 3'b010 && OPMODE != 7'b0001010) config_valid = 0; + if (CARRYINSEL == 3'b001 && OPMODE != 7'b1010101) config_valid = 0; + end endtask initial begin @@ -109,7 +118,7 @@ module testbench; #5; CLK = 1'b1; #10; - CLK = 1'b0 + CLK = 1'b0; #5; CLK = 1'b1; #10; @@ -118,7 +127,8 @@ module testbench; repeat (300) begin clkcycle; - do begin + config_valid = 0; + while (!config_valid) begin A = $urandom; ACIN = $urandom; B = $urandom; @@ -129,10 +139,12 @@ module testbench; {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP} = $urandom & $urandom & $urandom; {ALUMODE, CARRYINSEL, INMODE} = $urandom & $urandom & $urandom; - OPMODE = $urandom; + OPMODE = $urandom; + if ($urandom & 1'b1) + OPMODE[3:0] = 4'b0101; // test multiply more than other modes {CARRYCASCIN, CARRYIN, MULTSIGNIN} = $urandom; drc; - end while (!config_valid); + end end if (errcount == 0) begin @@ -194,6 +206,7 @@ module testbench; .BCIN (BCIN), .C (C), .CARRYCASCIN (CARRYCASCIN), + .CARRYINSEL (CARRYINSEL), .CEA1 (CEA1), .CEA2 (CEA2), .CEAD (CEAD), @@ -275,6 +288,7 @@ module testbench; .BCIN (BCIN), .C (C), .CARRYCASCIN (CARRYCASCIN), + .CARRYINSEL (CARRYINSEL), .CEA1 (CEA1), .CEA2 (CEA2), .CEAD (CEAD), @@ -305,6 +319,39 @@ module testbench; .RSTM (RSTM), .RSTP (RSTP) ); - - endmodule + +module mult_noreg_nopreadd_nocasc; + testbench #( + .ACASCREG (0), + .ADREG (0), + .ALUMODEREG (0), + .AREG (0), + .AUTORESET_PATDET ("NO_RESET"), + .A_INPUT ("DIRECT"), + .BCASCREG (0), + .BREG (0), + .B_INPUT ("DIRECT"), + .CARRYINREG (0), + .CARRYINSELREG (0), + .CREG (0), + .DREG (0), + .INMODEREG (0), + .MREG (0), + .OPMODEREG (0), + .PREG (0), + .SEL_MASK ("MASK"), + .SEL_PATTERN ("PATTERN"), + .USE_DPORT ("FALSE"), + .USE_MULT ("DYNAMIC"), + .USE_PATTERN_DETECT ("NO_PATDET"), + .USE_SIMD ("ONE48"), + .MASK (48'h3FFFFFFFFFFF), + .PATTERN (48'h000000000000), + .IS_ALUMODE_INVERTED(4'b0), + .IS_CARRYIN_INVERTED(1'b0), + .IS_CLK_INVERTED (1'b0), + .IS_INMODE_INVERTED (5'b0), + .IS_OPMODE_INVERTED (7'b0) + ) testbench (); +endmodule \ No newline at end of file From f6605c7dc0b1bcbc091b8283a741e24be25478b1 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 8 Aug 2019 10:26:40 +0100 Subject: [PATCH 106/356] DSP48E1 sim model: Comb, no pre-adder, mode working Signed-off-by: David Shah --- techlibs/xilinx/cells_sim.v | 5 +++-- techlibs/xilinx/tests/test_dsp_model.v | 16 ++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 4e26ea5c9..3817c6a1d 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -689,7 +689,7 @@ module DSP48E1 ( // ALU core wire [47:0] Z_muxinv = ALUMODEr[0] ? ~Z : Z; wire [47:0] xor_xyz = X ^ Y ^ Z_muxinv; - wire [47:0] maj_xyz = (X & Y) | (X & Z) | (X & Y); + wire [47:0] maj_xyz = (X & Y) | (X & Z_muxinv) | (Y & Z_muxinv); wire [47:0] xor_xyz_muxed = ALUMODEr[3] ? maj_xyz : xor_xyz; wire [47:0] maj_xyz_gated = ALUMODEr[2] ? 48'b0 : maj_xyz; @@ -745,7 +745,8 @@ module DSP48E1 ( wire signed [47:0] Pd = ALUMODEr[1] ? ~alu_sum : alu_sum; initial P = 48'b0; - wire [3:0] CARRYOUTd = (ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out; + wire [3:0] CARRYOUTd = (OPMODEr[3:0] == 4'b0101 || ALUMODEr[3:2] != 2'b00) ? 4'bxxxx : + ((ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out); wire CARRYCASCOUTd = ext_carry_out[3]; wire MULTSIGNOUTd = Mr[42]; diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v index f8039aa15..86ff7ab40 100644 --- a/techlibs/xilinx/tests/test_dsp_model.v +++ b/techlibs/xilinx/tests/test_dsp_model.v @@ -35,7 +35,7 @@ module testbench; reg CLK; reg CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL; reg CED, CEINMODE, CEM, CEP; - reg RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP; + reg RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP; reg [29:0] A, ACIN; reg [17:0] B, BCIN; reg [47:0] C; @@ -61,6 +61,8 @@ module testbench; integer errcount = 0; + reg ERROR_FLAG = 0; + task clkcycle; begin #5; @@ -68,14 +70,16 @@ module testbench; #10; CLK = ~CLK; #2; - + ERROR_FLAG = 0; if (REF_P !== P) begin $display("ERROR at %1t: REF_P=%b UUT_P=%b DIFF=%b", $time, REF_P, P, REF_P ^ P); errcount = errcount + 1; + ERROR_FLAG = 1; end if (REF_CARRYOUT !== CARRYOUT) begin $display("ERROR at %1t: REF_CARRYOUT=%b UUT_CARRYOUT=%b", $time, REF_CARRYOUT, CARRYOUT); errcount = errcount + 1; + ERROR_FLAG = 1; end #3; end @@ -114,7 +118,7 @@ module testbench; {ALUMODE, CARRYINSEL, INMODE} = 0; {OPMODE, CARRYCASCIN, CARRYIN, MULTSIGNIN} = 0; - {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP} = ~0; + {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = ~0; #5; CLK = 1'b1; #10; @@ -123,7 +127,7 @@ module testbench; CLK = 1'b1; #10; CLK = 1'b0; - {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP} = 0; + {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = 0; repeat (300) begin clkcycle; @@ -137,8 +141,8 @@ module testbench; D = $urandom; PCIN = {$urandom, $urandom}; - {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP} = $urandom & $urandom & $urandom; - {ALUMODE, CARRYINSEL, INMODE} = $urandom & $urandom & $urandom; + {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom; + {ALUMODE, CARRYINSEL, INMODE} = $urandom; OPMODE = $urandom; if ($urandom & 1'b1) OPMODE[3:0] = 4'b0101; // test multiply more than other modes From e7dbe7bb3de256f0ea89eb07647799b1e8d65bbe Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 8 Aug 2019 10:52:04 +0100 Subject: [PATCH 107/356] DSP48E1 sim model: seq test working Signed-off-by: David Shah --- techlibs/xilinx/cells_sim.v | 19 ++++++--- techlibs/xilinx/tests/test_dsp_model.sh | 2 +- techlibs/xilinx/tests/test_dsp_model.v | 55 +++++++++++++++++++++---- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 3817c6a1d..53061808b 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -547,7 +547,7 @@ module DSP48E1 ( end // C and D registers - if (CREG == 1) begin always @(posedge CLK) if (RSTC) Cr <= 48'b0; else if (CEC) Cr <= D; end + if (CREG == 1) begin always @(posedge CLK) if (RSTC) Cr <= 48'b0; else if (CEC) Cr <= C; end else always @* Cr <= C; if (DREG == 1) begin always @(posedge CLK) if (RSTD) Dr <= 25'b0; else if (CED) Dr <= D; end @@ -608,7 +608,7 @@ module DSP48E1 ( // X multiplexer case (OPMODEr[1:0]) 2'b00: X = 48'b0; - 2'b01: begin X = $signed(M); + 2'b01: begin X = $signed(Mr); `ifdef __ICARUS__ if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01"); `endif @@ -631,7 +631,7 @@ module DSP48E1 ( `endif end 2'b10: Y = {48{1'b1}}; - 2'b11: Y = C; + 2'b11: Y = Cr; default: Y = 48'bx; endcase @@ -644,7 +644,7 @@ module DSP48E1 ( if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010"); `endif end - 3'b011: Z = C; + 3'b011: Z = Cr; 3'b100: begin Z = P; `ifdef __ICARUS__ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100"); @@ -659,7 +659,7 @@ module DSP48E1 ( // Carry in wire A24_xnor_B17d = A_MULT[24] ~^ B_MULT[17]; - reg CARRYINr, A24_xnor_B17; + reg CARRYINr = 1'b0, A24_xnor_B17 = 1'b0; generate if (CARRYINREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) CARRYINr <= 1'b0; else if (CECARRYIN) CARRYINr <= CARRYIN; end else always @* CARRYINr = CARRYIN; @@ -698,6 +698,7 @@ module DSP48E1 ( wire [3:0] int_carry_in, int_carry_out, ext_carry_out; wire [47:0] alu_sum; assign int_carry_in[0] = 1'b0; + wire [3:0] carryout_reset; generate if (USE_SIMD == "FOUR12") begin @@ -715,6 +716,7 @@ module DSP48E1 ( maj_xyz_gated[23] ^ int_carry_out[1], maj_xyz_gated[11] ^ int_carry_out[0] }; + assign carryout_reset = 4'b0000; end else if (USE_SIMD == "TWO24") begin assign maj_xyz_simd_gated = { maj_xyz_gated[47:24], @@ -728,6 +730,7 @@ module DSP48E1 ( maj_xyz_gated[23] ^ int_carry_out[1], 1'bx }; + assign carryout_reset = 4'b0x0x; end else begin assign maj_xyz_simd_gated = {maj_xyz_gated, alu_cin}; assign int_carry_in[3:1] = int_carry_out[2:0]; @@ -735,6 +738,7 @@ module DSP48E1 ( int_carry_out[3], 3'bxxx }; + assign carryout_reset = 4'b0xxx; end genvar i; @@ -745,6 +749,9 @@ module DSP48E1 ( wire signed [47:0] Pd = ALUMODEr[1] ? ~alu_sum : alu_sum; initial P = 48'b0; + initial CARRYOUT = carryout_reset; + initial CARRYCASCOUT = 1'b0; + initial MULTSIGNOUT = 1'b0; wire [3:0] CARRYOUTd = (OPMODEr[3:0] == 4'b0101 || ALUMODEr[3:2] != 2'b00) ? 4'bxxxx : ((ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out); wire CARRYCASCOUTd = ext_carry_out[3]; @@ -755,7 +762,7 @@ module DSP48E1 ( always @(posedge CLK) if (RSTP) begin P <= 48'b0; - CARRYOUT <= 4'b0; + CARRYOUT <= carryout_reset; CARRYCASCOUT <= 1'b0; MULTSIGNOUT <= 1'b0; end else if (CEP) begin diff --git a/techlibs/xilinx/tests/test_dsp_model.sh b/techlibs/xilinx/tests/test_dsp_model.sh index 5455294da..3c7cfac30 100644 --- a/techlibs/xilinx/tests/test_dsp_model.sh +++ b/techlibs/xilinx/tests/test_dsp_model.sh @@ -4,7 +4,7 @@ sed 's/DSP48E1/DSP48E1_UUT/; /DSP48E1_UUT/,/endmodule/ p; d;' < ../cells_sim.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 fi -for tb in mult_noreg_nopreadd_nocasc +for tb in mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_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 vvp -N ./test_dsp_model diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v index 86ff7ab40..b5574911b 100644 --- a/techlibs/xilinx/tests/test_dsp_model.v +++ b/techlibs/xilinx/tests/test_dsp_model.v @@ -94,7 +94,7 @@ module testbench; if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0; if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0; if ((OPMODE[6:4] == 3'b010 || OPMODE[6:4] == 3'b110) && PREG != 1) config_valid = 0; - if ((OPMODE[6:4] == 3'b100) && (PREG != 1 || OPMODE[3:0] != 4'b1000)) config_valid = 0; + if ((OPMODE[6:4] == 3'b100) && (PREG != 1 || OPMODE[3:0] != 4'b1000 || ALUMODE[3:2] == 2'b01 || ALUMODE[3:2] == 2'b11)) config_valid = 0; if ((CARRYINSEL == 3'b100 || CARRYINSEL == 3'b101 || CARRYINSEL == 3'b111) && (PREG != 1)) config_valid = 0; if (OPMODE[6:4] == 3'b111) config_valid = 0; if ((ALUMODE[3:2] == 2'b01 || ALUMODE[3:2] == 2'b11) && OPMODE[3:2] != 2'b00 && OPMODE[3:2] != 2'b10) config_valid = 0; @@ -119,14 +119,16 @@ module testbench; {OPMODE, CARRYCASCIN, CARRYIN, MULTSIGNIN} = 0; {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = ~0; - #5; - CLK = 1'b1; - #10; - CLK = 1'b0; - #5; - CLK = 1'b1; - #10; - CLK = 1'b0; + repeat (10) begin + #10; + CLK = 1'b1; + #10; + CLK = 1'b0; + #10; + CLK = 1'b1; + #10; + CLK = 1'b0; + end {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = 0; repeat (300) begin @@ -358,4 +360,39 @@ module mult_noreg_nopreadd_nocasc; .IS_INMODE_INVERTED (5'b0), .IS_OPMODE_INVERTED (7'b0) ) testbench (); +endmodule + +module mult_allreg_nopreadd_nocasc; + testbench #( + .ACASCREG (1), + .ADREG (1), + .ALUMODEREG (1), + .AREG (2), + .AUTORESET_PATDET ("NO_RESET"), + .A_INPUT ("DIRECT"), + .BCASCREG (1), + .BREG (2), + .B_INPUT ("DIRECT"), + .CARRYINREG (1), + .CARRYINSELREG (1), + .CREG (1), + .DREG (1), + .INMODEREG (1), + .MREG (1), + .OPMODEREG (1), + .PREG (1), + .SEL_MASK ("MASK"), + .SEL_PATTERN ("PATTERN"), + .USE_DPORT ("FALSE"), + .USE_MULT ("DYNAMIC"), + .USE_PATTERN_DETECT ("NO_PATDET"), + .USE_SIMD ("ONE48"), + .MASK (48'h3FFFFFFFFFFF), + .PATTERN (48'h000000000000), + .IS_ALUMODE_INVERTED(4'b0), + .IS_CARRYIN_INVERTED(1'b0), + .IS_CLK_INVERTED (1'b0), + .IS_INMODE_INVERTED (5'b0), + .IS_OPMODE_INVERTED (7'b0) + ) testbench (); endmodule \ No newline at end of file From d60b3c0dc8ca9ce1b14c4acf2b602acc1fac00c5 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 8 Aug 2019 11:18:37 +0100 Subject: [PATCH 108/356] DSP48E1 sim model: fix seq tests and add preadder tests Signed-off-by: David Shah --- techlibs/xilinx/tests/test_dsp_model.sh | 3 +- techlibs/xilinx/tests/test_dsp_model.v | 94 +++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/tests/test_dsp_model.sh b/techlibs/xilinx/tests/test_dsp_model.sh index 3c7cfac30..337530e87 100644 --- a/techlibs/xilinx/tests/test_dsp_model.sh +++ b/techlibs/xilinx/tests/test_dsp_model.sh @@ -4,7 +4,8 @@ sed 's/DSP48E1/DSP48E1_UUT/; /DSP48E1_UUT/,/endmodule/ p; d;' < ../cells_sim.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 fi -for tb in mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc +for tb in mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc \ + mult_allreg_preadd_nocasc mult_noreg_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 vvp -N ./test_dsp_model diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v index b5574911b..6f1ca045a 100644 --- a/techlibs/xilinx/tests/test_dsp_model.v +++ b/techlibs/xilinx/tests/test_dsp_model.v @@ -91,16 +91,19 @@ module testbench; config_valid = 1; if (AREG != 2 && INMODE[0]) config_valid = 0; if (BREG != 2 && INMODE[4]) config_valid = 0; + if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0; if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0; if ((OPMODE[6:4] == 3'b010 || OPMODE[6:4] == 3'b110) && PREG != 1) config_valid = 0; if ((OPMODE[6:4] == 3'b100) && (PREG != 1 || OPMODE[3:0] != 4'b1000 || ALUMODE[3:2] == 2'b01 || ALUMODE[3:2] == 2'b11)) config_valid = 0; if ((CARRYINSEL == 3'b100 || CARRYINSEL == 3'b101 || CARRYINSEL == 3'b111) && (PREG != 1)) config_valid = 0; if (OPMODE[6:4] == 3'b111) config_valid = 0; - if ((ALUMODE[3:2] == 2'b01 || ALUMODE[3:2] == 2'b11) && OPMODE[3:2] != 2'b00 && OPMODE[3:2] != 2'b10) config_valid = 0; if ((OPMODE[3:0] == 4'b0101) && CARRYINSEL == 3'b010) config_valid = 0; - if (CARRYINSEL == 3'b010 && OPMODE != 7'b0001010) config_valid = 0; - if (CARRYINSEL == 3'b001 && OPMODE != 7'b1010101) config_valid = 0; + if (CARRYINSEL == 3'b000 && OPMODE == 7'b1001000) config_valid = 0; + + if ((ALUMODE[3:2] == 2'b01 || ALUMODE[3:2] == 2'b11) && OPMODE[3:2] != 2'b00 && OPMODE[3:2] != 2'b10) config_valid = 0; + + end endtask @@ -131,7 +134,7 @@ module testbench; end {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = 0; - repeat (300) begin + repeat (5000) begin clkcycle; config_valid = 0; while (!config_valid) begin @@ -144,11 +147,22 @@ module testbench; PCIN = {$urandom, $urandom}; {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom; - {ALUMODE, CARRYINSEL, INMODE} = $urandom; + {ALUMODE, INMODE} = $urandom; + CARRYINSEL = $urandom & $urandom & $urandom; OPMODE = $urandom; if ($urandom & 1'b1) OPMODE[3:0] = 4'b0101; // test multiply more than other modes {CARRYCASCIN, CARRYIN, MULTSIGNIN} = $urandom; + + // So few valid options in these modes, just force one valid option + if (CARRYINSEL == 3'b001) OPMODE = 7'b1010101; + if (CARRYINSEL == 3'b010) OPMODE = 7'b0001010; + if (CARRYINSEL == 3'b011) OPMODE = 7'b0011011; + if (CARRYINSEL == 3'b100) OPMODE = 7'b0110011; + if (CARRYINSEL == 3'b101) OPMODE = 7'b0011010; + if (CARRYINSEL == 3'b110) OPMODE = 7'b0010101; + if (CARRYINSEL == 3'b111) OPMODE = 7'b0100011; + drc; end end @@ -395,4 +409,74 @@ module mult_allreg_nopreadd_nocasc; .IS_INMODE_INVERTED (5'b0), .IS_OPMODE_INVERTED (7'b0) ) testbench (); +endmodule + +module mult_noreg_preadd_nocasc; + testbench #( + .ACASCREG (0), + .ADREG (0), + .ALUMODEREG (0), + .AREG (0), + .AUTORESET_PATDET ("NO_RESET"), + .A_INPUT ("DIRECT"), + .BCASCREG (0), + .BREG (0), + .B_INPUT ("DIRECT"), + .CARRYINREG (0), + .CARRYINSELREG (0), + .CREG (0), + .DREG (0), + .INMODEREG (0), + .MREG (0), + .OPMODEREG (0), + .PREG (0), + .SEL_MASK ("MASK"), + .SEL_PATTERN ("PATTERN"), + .USE_DPORT ("TRUE"), + .USE_MULT ("DYNAMIC"), + .USE_PATTERN_DETECT ("NO_PATDET"), + .USE_SIMD ("ONE48"), + .MASK (48'h3FFFFFFFFFFF), + .PATTERN (48'h000000000000), + .IS_ALUMODE_INVERTED(4'b0), + .IS_CARRYIN_INVERTED(1'b0), + .IS_CLK_INVERTED (1'b0), + .IS_INMODE_INVERTED (5'b0), + .IS_OPMODE_INVERTED (7'b0) + ) testbench (); +endmodule + +module mult_allreg_preadd_nocasc; + testbench #( + .ACASCREG (1), + .ADREG (1), + .ALUMODEREG (1), + .AREG (2), + .AUTORESET_PATDET ("NO_RESET"), + .A_INPUT ("DIRECT"), + .BCASCREG (1), + .BREG (2), + .B_INPUT ("DIRECT"), + .CARRYINREG (1), + .CARRYINSELREG (1), + .CREG (1), + .DREG (1), + .INMODEREG (1), + .MREG (1), + .OPMODEREG (1), + .PREG (1), + .SEL_MASK ("MASK"), + .SEL_PATTERN ("PATTERN"), + .USE_DPORT ("TRUE"), + .USE_MULT ("DYNAMIC"), + .USE_PATTERN_DETECT ("NO_PATDET"), + .USE_SIMD ("ONE48"), + .MASK (48'h3FFFFFFFFFFF), + .PATTERN (48'h000000000000), + .IS_ALUMODE_INVERTED(4'b0), + .IS_CARRYIN_INVERTED(1'b0), + .IS_CLK_INVERTED (1'b0), + .IS_INMODE_INVERTED (5'b0), + .IS_OPMODE_INVERTED (7'b0) + ) testbench (); endmodule \ No newline at end of file From 57aeb4cc01058c0167e5a4eda9def97b0bb1741b Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 8 Aug 2019 11:32:43 +0100 Subject: [PATCH 109/356] DSP48E1 model: test CE inputs Signed-off-by: David Shah --- techlibs/xilinx/cells_sim.v | 13 ++++++++----- techlibs/xilinx/tests/test_dsp_model.v | 11 +++++++++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 53061808b..b738d9712 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -593,14 +593,17 @@ module DSP48E1 ( endgenerate wire signed [42:0] M = A_MULT * B_MULT; + wire signed [42:0] Mx = (CARRYINSEL == 3'b010) ? 43'bx : M; reg signed [42:0] Mr = 43'b0; // Multiplier result register generate - if (MREG == 1) begin always @(posedge CLK) if (RSTM) Mr <= 43'b0; else if (CEM) Mr <= M; end - else always @* Mr <= M; + if (MREG == 1) begin always @(posedge CLK) if (RSTM) Mr <= 43'b0; else if (CEM) Mr <= Mx; end + else always @* Mr <= Mx; endgenerate + wire signed [42:0] Mrx = (CARRYINSELr == 3'b010) ? 43'bx : Mr; + // X, Y and Z ALU inputs reg signed [47:0] X, Y, Z; @@ -608,7 +611,7 @@ module DSP48E1 ( // X multiplexer case (OPMODEr[1:0]) 2'b00: X = 48'b0; - 2'b01: begin X = $signed(Mr); + 2'b01: begin X = $signed(Mrx); `ifdef __ICARUS__ if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01"); `endif @@ -664,7 +667,7 @@ module DSP48E1 ( if (CARRYINREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) CARRYINr <= 1'b0; else if (CECARRYIN) CARRYINr <= CARRYIN; end else always @* CARRYINr = CARRYIN; - if (MREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) A24_xnor_B17 <= 1'b0; else if (CECARRYIN) A24_xnor_B17 <= A24_xnor_B17d; end + if (MREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) A24_xnor_B17 <= 1'b0; else if (CEM) A24_xnor_B17 <= A24_xnor_B17d; end else always @* A24_xnor_B17 = A24_xnor_B17d; endgenerate @@ -755,7 +758,7 @@ module DSP48E1 ( wire [3:0] CARRYOUTd = (OPMODEr[3:0] == 4'b0101 || ALUMODEr[3:2] != 2'b00) ? 4'bxxxx : ((ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out); wire CARRYCASCOUTd = ext_carry_out[3]; - wire MULTSIGNOUTd = Mr[42]; + wire MULTSIGNOUTd = Mrx[42]; generate if (PREG == 1) begin diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v index 6f1ca045a..7086634d2 100644 --- a/techlibs/xilinx/tests/test_dsp_model.v +++ b/techlibs/xilinx/tests/test_dsp_model.v @@ -134,7 +134,7 @@ module testbench; end {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = 0; - repeat (5000) begin + repeat (10000) begin clkcycle; config_valid = 0; while (!config_valid) begin @@ -146,6 +146,13 @@ module testbench; D = $urandom; PCIN = {$urandom, $urandom}; + {CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL} = $urandom | $urandom | $urandom; + {CED, CEINMODE, CEM, CEP} = $urandom | $urandom | $urandom | $urandom; + + // Otherwise we can accidentally create illegal configs + CEINMODE = CECTRL; + CEALUMODE = CECTRL; + {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom; {ALUMODE, INMODE} = $urandom; CARRYINSEL = $urandom & $urandom & $urandom; @@ -162,7 +169,7 @@ module testbench; if (CARRYINSEL == 3'b101) OPMODE = 7'b0011010; if (CARRYINSEL == 3'b110) OPMODE = 7'b0010101; if (CARRYINSEL == 3'b111) OPMODE = 7'b0100011; - + drc; end end From b8cd4ad64ae9a45faecffc1a6b92a8219755bc60 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 8 Aug 2019 11:39:35 +0100 Subject: [PATCH 110/356] DSP48E1 sim model: add SIMD tests Signed-off-by: David Shah --- techlibs/xilinx/cells_sim.v | 2 +- techlibs/xilinx/tests/test_dsp_model.sh | 6 +- techlibs/xilinx/tests/test_dsp_model.v | 108 ++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index b738d9712..8b6eaae5d 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -468,7 +468,7 @@ module DSP48E1 ( if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value"); if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value"); if (USE_PATTERN_DETECT != "NO_PATDET") $fatal(1, "Unsupported USE_PATTERN_DETECT value"); - if (USE_SIMD != "ONE48") $fatal(1, "Unsupported USE_SIMD value"); + if (USE_SIMD != "ONE48" && USE_SIMD != "TWO24" && USE_SIMD != "FOUR12") $fatal(1, "Unsupported USE_SIMD value"); if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value"); if (IS_CARRYIN_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CARRYIN_INVERTED value"); if (IS_CLK_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CLK_INVERTED value"); diff --git a/techlibs/xilinx/tests/test_dsp_model.sh b/techlibs/xilinx/tests/test_dsp_model.sh index 337530e87..2acd97eb4 100644 --- a/techlibs/xilinx/tests/test_dsp_model.sh +++ b/techlibs/xilinx/tests/test_dsp_model.sh @@ -4,8 +4,10 @@ sed 's/DSP48E1/DSP48E1_UUT/; /DSP48E1_UUT/,/endmodule/ p; d;' < ../cells_sim.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 fi -for tb in mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc \ - mult_allreg_preadd_nocasc mult_noreg_preadd_nocasc +for tb in 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 vvp -N ./test_dsp_model diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v index 7086634d2..04d5b26ab 100644 --- a/techlibs/xilinx/tests/test_dsp_model.v +++ b/techlibs/xilinx/tests/test_dsp_model.v @@ -92,6 +92,8 @@ module testbench; if (AREG != 2 && INMODE[0]) config_valid = 0; if (BREG != 2 && INMODE[4]) config_valid = 0; + if (USE_SIMD != "ONE48" && OPMODE[3:0] == 4'b0101) config_valid = 0; + if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0; if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0; if ((OPMODE[6:4] == 3'b010 || OPMODE[6:4] == 3'b110) && PREG != 1) config_valid = 0; @@ -486,4 +488,110 @@ module mult_allreg_preadd_nocasc; .IS_INMODE_INVERTED (5'b0), .IS_OPMODE_INVERTED (7'b0) ) testbench (); +endmodule + +module mult_inreg_preadd_nocasc; + testbench #( + .ACASCREG (1), + .ADREG (0), + .ALUMODEREG (0), + .AREG (1), + .AUTORESET_PATDET ("NO_RESET"), + .A_INPUT ("DIRECT"), + .BCASCREG (1), + .BREG (1), + .B_INPUT ("DIRECT"), + .CARRYINREG (0), + .CARRYINSELREG (0), + .CREG (1), + .DREG (1), + .INMODEREG (0), + .MREG (0), + .OPMODEREG (0), + .PREG (0), + .SEL_MASK ("MASK"), + .SEL_PATTERN ("PATTERN"), + .USE_DPORT ("TRUE"), + .USE_MULT ("DYNAMIC"), + .USE_PATTERN_DETECT ("NO_PATDET"), + .USE_SIMD ("ONE48"), + .MASK (48'h3FFFFFFFFFFF), + .PATTERN (48'h000000000000), + .IS_ALUMODE_INVERTED(4'b0), + .IS_CARRYIN_INVERTED(1'b0), + .IS_CLK_INVERTED (1'b0), + .IS_INMODE_INVERTED (5'b0), + .IS_OPMODE_INVERTED (7'b0) + ) testbench (); +endmodule + +module simd12_preadd_noreg_nocasc; + testbench #( + .ACASCREG (0), + .ADREG (0), + .ALUMODEREG (0), + .AREG (0), + .AUTORESET_PATDET ("NO_RESET"), + .A_INPUT ("DIRECT"), + .BCASCREG (0), + .BREG (0), + .B_INPUT ("DIRECT"), + .CARRYINREG (0), + .CARRYINSELREG (0), + .CREG (0), + .DREG (0), + .INMODEREG (0), + .MREG (0), + .OPMODEREG (0), + .PREG (0), + .SEL_MASK ("MASK"), + .SEL_PATTERN ("PATTERN"), + .USE_DPORT ("TRUE"), + .USE_MULT ("DYNAMIC"), + .USE_PATTERN_DETECT ("NO_PATDET"), + .USE_SIMD ("FOUR12"), + .MASK (48'h3FFFFFFFFFFF), + .PATTERN (48'h000000000000), + .IS_ALUMODE_INVERTED(4'b0), + .IS_CARRYIN_INVERTED(1'b0), + .IS_CLK_INVERTED (1'b0), + .IS_INMODE_INVERTED (5'b0), + .IS_OPMODE_INVERTED (7'b0) + ) testbench (); +endmodule + + +module simd24_preadd_noreg_nocasc; + testbench #( + .ACASCREG (0), + .ADREG (0), + .ALUMODEREG (0), + .AREG (0), + .AUTORESET_PATDET ("NO_RESET"), + .A_INPUT ("DIRECT"), + .BCASCREG (0), + .BREG (0), + .B_INPUT ("DIRECT"), + .CARRYINREG (0), + .CARRYINSELREG (0), + .CREG (0), + .DREG (0), + .INMODEREG (0), + .MREG (0), + .OPMODEREG (0), + .PREG (0), + .SEL_MASK ("MASK"), + .SEL_PATTERN ("PATTERN"), + .USE_DPORT ("TRUE"), + .USE_MULT ("DYNAMIC"), + .USE_PATTERN_DETECT ("NO_PATDET"), + .USE_SIMD ("TWO24"), + .MASK (48'h3FFFFFFFFFFF), + .PATTERN (48'h000000000000), + .IS_ALUMODE_INVERTED(4'b0), + .IS_CARRYIN_INVERTED(1'b0), + .IS_CLK_INVERTED (1'b0), + .IS_INMODE_INVERTED (5'b0), + .IS_OPMODE_INVERTED (7'b0) + ) testbench (); endmodule \ No newline at end of file From cb84ed23263f8cad8f878a327061ac2c990af812 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 8 Aug 2019 15:14:09 +0100 Subject: [PATCH 111/356] ecp5: Bring up to date with mul2dsp changes Signed-off-by: David Shah --- techlibs/ecp5/dsp_map.v | 9 ++++++++- techlibs/ecp5/synth_ecp5.cc | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/techlibs/ecp5/dsp_map.v b/techlibs/ecp5/dsp_map.v index 24e28869e..cb95ddb1c 100644 --- a/techlibs/ecp5/dsp_map.v +++ b/techlibs/ecp5/dsp_map.v @@ -1,9 +1,16 @@ module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); + + parameter A_WIDTH = 18; + parameter B_WIDTH = 18; + parameter Y_WIDTH = 36; + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + MULT18X18D _TECHMAP_REPLACE_ ( .A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .A4(A[4]), .A5(A[5]), .A6(A[6]), .A7(A[7]), .A8(A[8]), .A9(A[9]), .A10(A[10]), .A11(A[11]), .A12(A[12]), .A13(A[13]), .A14(A[14]), .A15(A[15]), .A16(A[16]), .A17(A[17]), .B0(B[0]), .B1(B[1]), .B2(B[2]), .B3(B[3]), .B4(B[4]), .B5(B[5]), .B6(B[6]), .B7(B[7]), .B8(B[8]), .B9(B[9]), .B10(B[10]), .B11(B[11]), .B12(B[12]), .B13(B[13]), .B14(B[14]), .B15(B[15]), .B16(B[16]), .B17(B[17]), .C17(1'b0), .C16(1'b0), .C15(1'b0), .C14(1'b0), .C13(1'b0), .C12(1'b0), .C11(1'b0), .C10(1'b0), .C9(1'b0), .C8(1'b0), .C7(1'b0), .C6(1'b0), .C5(1'b0), .C4(1'b0), .C3(1'b0), .C2(1'b0), .C1(1'b0), .C0(1'b0), - .SIGNEDA(1'b0), .SIGNEDB(1'b0), .SOURCEA(1'b0), .SOURCEB(1'b0), + .SIGNEDA(A_SIGNED), .SIGNEDB(B_SIGNED), .SOURCEA(1'b0), .SOURCEB(1'b0), .P0(Y[0]), .P1(Y[1]), .P2(Y[2]), .P3(Y[3]), .P4(Y[4]), .P5(Y[5]), .P6(Y[6]), .P7(Y[7]), .P8(Y[8]), .P9(Y[9]), .P10(Y[10]), .P11(Y[11]), .P12(Y[12]), .P13(Y[13]), .P14(Y[14]), .P15(Y[15]), .P16(Y[16]), .P17(Y[17]), .P18(Y[18]), .P19(Y[19]), .P20(Y[20]), .P21(Y[21]), .P22(Y[22]), .P23(Y[23]), .P24(Y[24]), .P25(Y[25]), .P26(Y[26]), .P27(Y[27]), .P28(Y[28]), .P29(Y[29]), .P30(Y[30]), .P31(Y[31]), .P32(Y[32]), .P33(Y[33]), .P34(Y[34]), .P35(Y[35]) ); diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 3129ba929..7be377280 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -248,9 +248,10 @@ struct SynthEcp5Pass : public ScriptPass run("opt_expr"); run("opt_clean"); if (dsp) { - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_NAME=$__MUL18X18"); + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18"); run("clean"); run("techmap -map +/ecp5/dsp_map.v"); + run("chtype -set $mul t:$__soft_mul","(if -dsp)"); } run("alumacc"); run("opt"); From 0492b8b5412683392bc19ad7f15ba6c14e6668f8 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 8 Aug 2019 15:18:59 +0100 Subject: [PATCH 112/356] ecp5: Replace '-dsp' with inverse logic '-nodsp' to match synth_xilinx Signed-off-by: David Shah --- techlibs/ecp5/synth_ecp5.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 7be377280..1a5359e85 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -89,8 +89,8 @@ struct SynthEcp5Pass : public ScriptPass log(" generate an output netlist (and BLIF file) suitable for VPR\n"); log(" (this feature is experimental and incomplete)\n"); log("\n"); - log(" -dsp\n"); - log(" map multipliers to MULT18X18D (EXPERIMENTAL)\n"); + log(" -nodsp\n"); + log(" do not map multipliers to MULT18X18D\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -99,7 +99,7 @@ struct SynthEcp5Pass : public ScriptPass } string top_opt, blif_file, edif_file, json_file; - bool noccu2, nodffe, nobram, nolutram, nowidelut, flatten, retime, abc2, abc9, dsp, vpr; + bool noccu2, nodffe, nobram, nolutram, nowidelut, flatten, retime, abc2, abc9, nodsp, vpr; void clear_flags() YS_OVERRIDE { @@ -117,7 +117,7 @@ struct SynthEcp5Pass : public ScriptPass abc2 = false; vpr = false; abc9 = false; - dsp = false; + nodsp = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -196,8 +196,8 @@ struct SynthEcp5Pass : public ScriptPass abc9 = true; continue; } - if (args[argidx] == "-dsp") { - dsp = true; + if (args[argidx] == "-nodsp") { + nodsp = true; continue; } break; @@ -247,11 +247,11 @@ struct SynthEcp5Pass : public ScriptPass run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4"); run("opt_expr"); run("opt_clean"); - if (dsp) { - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18"); - run("clean"); - run("techmap -map +/ecp5/dsp_map.v"); - run("chtype -set $mul t:$__soft_mul","(if -dsp)"); + if (!nodsp) { + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18", "(unless -nodsp)"); + run("clean", "(unless -nodsp)"); + run("techmap -map +/ecp5/dsp_map.v", "(unless -nodsp)"); + run("chtype -set $mul t:$__soft_mul", "(unless -nodsp)"); } run("alumacc"); run("opt"); From 13cc106cf7409570936f441af2cc133896f4ecb4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 8 Aug 2019 10:44:26 -0700 Subject: [PATCH 113/356] Fix copy-pasta typo --- techlibs/xilinx/cells_sim.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 8b6eaae5d..2731cb454 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -522,7 +522,7 @@ module DSP48E1 ( always @* Ar2 <= A_muxed; end - // Configurable A register + // Configurable B register if (BREG == 2) begin always @(posedge CLK) if (RSTB) begin @@ -532,7 +532,7 @@ module DSP48E1 ( if (CEB1) Br1 <= B_muxed; if (CEB2) Br2 <= Br1; end - end else if (AREG == 1) begin + end else if (BREG == 1) begin always @(posedge CLK) if (RSTB) begin Br1 <= 18'b0; From 57b2e4b9c1dda6d092e261f90a311087c62d0bc4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 8 Aug 2019 10:44:35 -0700 Subject: [PATCH 114/356] INMODE is 5 bits --- techlibs/xilinx/dsp_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v index 3d7b09d69..423e12fbe 100644 --- a/techlibs/xilinx/dsp_map.v +++ b/techlibs/xilinx/dsp_map.v @@ -32,7 +32,7 @@ module \$__MUL25X18 (input signed [24:0] A, input signed [17:0] B, output signed .D(24'b0), .P(P_48), - .INMODE(4'b0000), + .INMODE(5'b00000), .ALUMODE(4'b0000), .OPMODE(7'b000101), .CARRYINSEL(3'b000), From 911129e3ef9196a2f775d97746d704ed761da40d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 8 Aug 2019 10:44:49 -0700 Subject: [PATCH 115/356] Disable $dffe --- passes/pmgen/xilinx_dsp.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index be510b4cb..74bcbf451 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -58,11 +58,11 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) SigSpec Q = st.ffA->getPort("\\Q"); A.replace(Q, D); cell->setPort("\\A", A); - cell->setParam("\\AREG", State::S1); + cell->setParam("\\AREG", 1); if (st.ffA->type == "$dff") cell->setPort("\\CEA2", State::S1); - else if (st.ffA->type == "$dffe") - cell->setPort("\\CEA2", st.ffA->getPort("\\EN")); + //else if (st.ffA->type == "$dffe") + // cell->setPort("\\CEA2", st.ffA->getPort("\\EN")); else log_abort(); } if (st.ffB) { @@ -71,11 +71,11 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) SigSpec Q = st.ffB->getPort("\\Q"); B.replace(Q, D); cell->setPort("\\B", B); - cell->setParam("\\BREG", State::S1); + cell->setParam("\\BREG", 1); if (st.ffB->type == "$dff") cell->setPort("\\CEB2", State::S1); - else if (st.ffB->type == "$dffe") - cell->setPort("\\CEB2", st.ffB->getPort("\\EN")); + //else if (st.ffB->type == "$dffe") + // cell->setPort("\\CEB2", st.ffB->getPort("\\EN")); else log_abort(); } if (st.ffP) { @@ -91,8 +91,8 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) cell->setParam("\\PREG", State::S1); if (st.ffP->type == "$dff") cell->setPort("\\CEP", State::S1); - else if (st.ffP->type == "$dffe") - cell->setPort("\\CEP", st.ffP->getPort("\\EN")); + //else if (st.ffP->type == "$dffe") + // cell->setPort("\\CEP", st.ffP->getPort("\\EN")); else log_abort(); st.ffP->connections_.at("\\Q").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); From 716024387468285f0d5ee2719b86fe6ddbfff93e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 8 Aug 2019 10:45:56 -0700 Subject: [PATCH 116/356] Move xilinx_dsp to before alumacc --- techlibs/xilinx/synth_xilinx.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a787c7c4c..49beaa565 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -286,7 +286,10 @@ struct SynthXilinxPass : public ScriptPass if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); + run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); + run("techmap -map +/xilinx/dsp_map.v", "(skip if '-nodsp')"); // TODO: fold into xilinx_dsp + run("xilinx_dsp", " (skip if '-nodsp')"); + run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); } run("alumacc"); @@ -331,11 +334,6 @@ struct SynthXilinxPass : public ScriptPass run("memory_map"); run("dffsr2dff"); run("dff2dffe"); - if (help_mode || !nodsp) { - run("techmap -map +/xilinx/dsp_map.v", "(skip if '-nodsp')"); - run("xilinx_dsp", " (skip if '-nodsp')"); - run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); - } if (help_mode) { run("simplemap t:$mux", " ('-widemux' only)"); run("muxcover , ('-widemux' only)"); From 07e50b9c256358b2800a5272258a083f7e4d67d3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 8 Aug 2019 10:51:19 -0700 Subject: [PATCH 117/356] Only pack registers if {A,B,P}REG = 0, do not pack $dffe --- passes/pmgen/xilinx_dsp.pmg | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index a97ab4dd5..6fd1207fa 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -8,9 +8,10 @@ match dsp endmatch match ffA - select ffA->type.in($dff, $dffe) + select ffA->type.in($dff) // DSP48E1 does not support clock inversion select param(ffA, \CLK_POLARITY).as_bool() + filter param(dsp, \AREG).as_int() == 0 filter !port(dsp, \A).remove_const().empty() filter includes(port(ffA, \Q).to_sigbit_set(), port(dsp, \A).remove_const().to_sigbit_set()) optional @@ -22,9 +23,10 @@ code clock endcode match ffB - select ffB->type.in($dff, $dffe) + select ffB->type.in($dff) // DSP48E1 does not support clock inversion select param(ffB, \CLK_POLARITY).as_bool() + filter param(dsp, \BREG).as_int() == 0 filter !port(dsp, \B).remove_const().empty() filter includes(port(ffB, \Q).to_sigbit_set(), port(dsp, \B).remove_const().to_sigbit_set()) optional @@ -54,10 +56,11 @@ endcode match ffP if !sigPused.empty() - select ffP->type.in($dff, $dffe) + select ffP->type.in($dff) select nusers(port(ffP, \D)) == 2 // DSP48E1 does not support clock inversion select param(ffP, \CLK_POLARITY).as_bool() + filter param(dsp, \PREG).as_int() == 0 filter param(ffP, \WIDTH).as_int() >= GetSize(sigPused) filter includes(port(ffP, \D).to_sigbit_set(), sigPused.to_sigbit_set()) optional From 162eab6b7422754c4c88d794f8024cfc1e03a419 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 8 Aug 2019 10:55:48 -0700 Subject: [PATCH 118/356] Combine techmap calls --- techlibs/xilinx/synth_xilinx.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 49beaa565..7b1fe5e3b 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -286,8 +286,7 @@ struct SynthXilinxPass : public ScriptPass if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); - run("techmap -map +/xilinx/dsp_map.v", "(skip if '-nodsp')"); // TODO: fold into xilinx_dsp + run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); run("xilinx_dsp", " (skip if '-nodsp')"); run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); } From 2c0be7aa5d7dcdf18678fb7b09ba1b3b5dd00998 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 8 Aug 2019 12:56:05 -0700 Subject: [PATCH 119/356] Rework ice40_dsp to map to SB_MAC16 earlier, and check before packing --- passes/pmgen/ice40_dsp.cc | 21 +++++--- passes/pmgen/ice40_dsp.pmg | 99 ++++++++++++++++++++++++----------- passes/pmgen/xilinx_dsp.pmg | 2 +- techlibs/ice40/Makefile.inc | 1 + techlibs/ice40/dsp_map.v | 34 ++++++++++++ techlibs/ice40/synth_ice40.cc | 2 +- 6 files changed, 119 insertions(+), 40 deletions(-) create mode 100644 techlibs/ice40/dsp_map.v diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 45d7a34df..bb45b8a4e 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -32,7 +32,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) { auto &st = pm.st_ice40_dsp; -#if 0 +#if 1 log("\n"); log("ffA: %s\n", log_id(st.ffA, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); @@ -66,10 +66,14 @@ void create_ice40_dsp(ice40_dsp_pm &pm) return; } - log(" replacing %s with SB_MAC16 cell.\n", log_id(st.mul->type)); + Cell *cell = st.mul; + if (cell->type == "$mul") { + log(" replacing %s with SB_MAC16 cell.\n", log_id(st.mul->type)); - Cell *cell = pm.module->addCell(NEW_ID, "\\SB_MAC16"); - pm.module->swap_names(cell, st.mul); + cell = pm.module->addCell(NEW_ID, "\\SB_MAC16"); + pm.module->swap_names(cell, st.mul); + } + else log_assert(cell->type == "\\SB_MAC16"); // SB_MAC16 Input Interface SigSpec A = st.sigA; @@ -220,15 +224,18 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\A_SIGNED", st.mul->getParam("\\A_SIGNED").as_bool()); cell->setParam("\\B_SIGNED", st.mul->getParam("\\B_SIGNED").as_bool()); - pm.autoremove(st.mul); + if (cell != st.mul) + pm.autoremove(st.mul); + else + pm.blacklist(st.mul); pm.autoremove(st.ffH); pm.autoremove(st.addAB); if (st.ffO_lo) { - SigSpec O = st.sigO.extract(0,st.ffO_lo->getParam("\\WIDTH").as_int()); + SigSpec O = st.sigO.extract(0,std::min(16,st.ffO_lo->getParam("\\WIDTH").as_int())); st.ffO_lo->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); } if (st.ffO_hi) { - SigSpec O = st.sigO.extract(16,st.ffO_hi->getParam("\\WIDTH").as_int()); + SigSpec O = st.sigO.extract_end(16); st.ffO_hi->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); } } diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 8b1ac2563..1a62c7bda 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -2,18 +2,27 @@ pattern ice40_dsp state clock state clock_pol -state sigA sigB sigCD sigH sigO +state sigA sigB sigCD sigH sigO sigOused state addAB muxAB match mul - select mul->type.in($mul, $__MUL16X16) + select mul->type.in($mul, \SB_MAC16) select GetSize(mul->getPort(\A)) + GetSize(mul->getPort(\B)) > 10 - select GetSize(mul->getPort(\Y)) > 10 endmatch +code sigH + if (mul->type == $mul) + sigH = mul->getPort(\Y); + else if (mul->type == \SB_MAC16) + sigH = mul->getPort(\O); + else log_abort(); + if (GetSize(sigH) <= 10) + reject; +endcode + match ffA - // TODO: Support $dffe too by checking if all enable signals are identical select ffA->type.in($dff) + filter mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool() filter !port(mul, \A).remove_const().empty() filter includes(port(ffA, \Q).to_sigbit_set(), port(mul, \A).remove_const().to_sigbit_set()) optional @@ -23,9 +32,9 @@ code sigA clock clock_pol sigA = port(mul, \A); if (ffA) { - for (auto b : port(ffA, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; + for (auto b : port(ffA, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; clock = port(ffA, \CLK).as_bit(); clock_pol = param(ffA, \CLK_POLARITY).as_bool(); @@ -36,6 +45,7 @@ endcode match ffB select ffB->type.in($dff) + filter mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool() filter !port(mul, \B).remove_const().empty() filter includes(port(ffB, \Q).to_sigbit_set(), port(mul, \B).remove_const().to_sigbit_set()) optional @@ -45,9 +55,9 @@ code sigB clock clock_pol sigB = port(mul, \B); if (ffB) { - for (auto b : port(ffB, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; + for (auto b : port(ffB, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; SigBit c = port(ffB, \CLK).as_bit(); bool cp = param(ffB, \CLK_POLARITY).as_bool(); @@ -65,19 +75,20 @@ endcode match ffH select ffH->type.in($dff) select nusers(port(ffH, \D)) == 2 - index port(ffH, \D) === port(mul, \Y) + index port(ffH, \D) === sigH + // Ensure pipeline register is not already used + filter mul->type != \SB_MAC16 || (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool()) optional endmatch code sigH sigO clock clock_pol - sigH = port(mul, \Y); sigO = sigH; if (ffH) { sigH = port(ffH, \Q); - for (auto b : sigH) - if (b.wire->get_bool_attribute(\keep)) - reject; + for (auto b : sigH) + if (b.wire->get_bool_attribute(\keep)) + reject; sigO = sigH; @@ -119,6 +130,13 @@ code addAB sigCD sigO sigCD.extend_u0(32, param(addAB, \A_SIGNED).as_bool()); } if (addAB) { + if (mul->type == \SB_MAC16) { + // Ensure that adder is not used + if (param(mul, \TOPOUTPUT_SELECT).as_int() != 3 || + param(mul, \BOTOUTPUT_SELECT).as_int() != 3) + reject; + } + int natural_mul_width = GetSize(sigA) + GetSize(sigB); int actual_mul_width = GetSize(sigH); int actual_acc_width = GetSize(sigO); @@ -154,28 +172,49 @@ code muxAB muxAB = muxB; endcode +// Extract the bits of P that actually have a consumer +// (as opposed to being a dummy) +code sigOused + for (int i = 0; i < GetSize(sigO); i++) + if (!sigO[i].wire || nusers(sigO[i]) == 1) + sigOused.append(State::Sx); + else + sigOused.append(sigO[i]); +endcode + match ffO_lo select ffO_lo->type.in($dff) - filter GetSize(sigO) >= param(ffO_lo, \WIDTH).as_int() - filter nusers(sigO.extract(0,param(ffO_lo, \WIDTH).as_int())) == 2 - filter includes(port(ffO_lo, \D).to_sigbit_set(), sigO.extract(0,param(ffO_lo, \WIDTH).as_int()).to_sigbit_set()) + filter nusers(sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int()))) == 2 + filter includes(port(ffO_lo, \D).to_sigbit_set(), sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int())).remove_const().to_sigbit_set()) optional endmatch match ffO_hi select ffO_hi->type.in($dff) - filter GetSize(sigO) >= 16+param(ffO_hi, \WIDTH).as_int() - filter nusers(sigO.extract(16,param(ffO_hi, \WIDTH).as_int())) == 2 - filter includes(port(ffO_hi, \D).to_sigbit_set(), sigO.extract(16,param(ffO_hi, \WIDTH).as_int()).to_sigbit_set()) + filter GetSize(sigOused) > 16 + filter nusers(sigOused.extract_end(16)) == 2 + filter includes(port(ffO_hi, \D).to_sigbit_set(), sigOused.extract_end(16).remove_const().to_sigbit_set()) optional endmatch code clock clock_pol sigO sigCD if (ffO_lo || ffO_hi) { + if (mul->type == \SB_MAC16) { + // Ensure that register is not already used + if (param(mul, \TOPOUTPUT_SELECT).as_int() == 1 || + param(mul, \BOTOUTPUT_SELECT).as_int() == 1) + reject; + + // Ensure that OLOADTOP/OLOADBOT is unused or zero + if ((mul->hasPort(\OLOADTOP) && !port(mul, \OLOADTOP).is_fully_zero()) + || (mul->hasPort(\OLOADBOT) && !port(mul, \OLOADBOT).is_fully_zero())) + reject; + } + if (ffO_lo) { - for (auto b : port(ffO_lo, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; + for (auto b : port(ffO_lo, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; SigBit c = port(ffO_lo, \CLK).as_bit(); bool cp = param(ffO_lo, \CLK_POLARITY).as_bool(); @@ -186,14 +225,13 @@ code clock clock_pol sigO sigCD clock = c; clock_pol = cp; - if (port(ffO_lo, \Q) != sigO.extract(0,param(ffO_lo, \WIDTH).as_int())) - sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q)); + sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q)); } if (ffO_hi) { - for (auto b : port(ffO_hi, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; + for (auto b : port(ffO_hi, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; SigBit c = port(ffO_hi, \CLK).as_bit(); bool cp = param(ffO_hi, \CLK_POLARITY).as_bool(); @@ -204,8 +242,7 @@ code clock clock_pol sigO sigCD clock = c; clock_pol = cp; - if (port(ffO_hi, \Q) != sigO.extract(16,param(ffO_hi, \WIDTH).as_int())) - sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q)); + sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q)); } // Loading value into output register is not diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 6fd1207fa..8abae9316 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -44,7 +44,7 @@ code clock endcode // Extract the bits of P that actually have a consumer -// (as opposed to being a sign extension) +// (as opposed to being a dummy) code sigPused SigSpec P = port(dsp, \P); int i; diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index d258d5a5d..b0eadab44 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -28,6 +28,7 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/dsp_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.box)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.lut)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.box)) diff --git a/techlibs/ice40/dsp_map.v b/techlibs/ice40/dsp_map.v new file mode 100644 index 000000000..06fa73956 --- /dev/null +++ b/techlibs/ice40/dsp_map.v @@ -0,0 +1,34 @@ +module \$__MUL16X16 (input [15:0] A, input [15:0] B, output [31:0] Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 0; + parameter B_WIDTH = 0; + parameter Y_WIDTH = 0; + + SB_MAC16 #( + .NEG_TRIGGER(1'b0), + .C_REG(1'b0), + .A_REG(1'b0), + .B_REG(1'b0), + .D_REG(1'b0), + .TOP_8x8_MULT_REG(1'b0), + .BOT_8x8_MULT_REG(1'b0), + .PIPELINE_16x16_MULT_REG1(1'b0), + .PIPELINE_16x16_MULT_REG2(1'b0), + .TOPOUTPUT_SELECT(2'b11), + .TOPADDSUB_LOWERINPUT(2'b0), + .TOPADDSUB_UPPERINPUT(1'b0), + .TOPADDSUB_CARRYSELECT(2'b0), + .BOTOUTPUT_SELECT(2'b11), + .BOTADDSUB_LOWERINPUT(2'b0), + .BOTADDSUB_UPPERINPUT(1'b0), + .BOTADDSUB_CARRYSELECT(2'b0), + .MODE_8x8(1'b0), + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED) + ) _TECHMAP_REPLACE_ ( + .A(A), + .B(B), + .O(Y), + ); +endmodule diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 09759f359..9c3670c7c 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -266,7 +266,7 @@ struct SynthIce40Pass : public ScriptPass run("opt_expr"); run("opt_clean"); if (help_mode || dsp) { - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 -D DSP_NAME=$__MUL16X16", "(if -dsp)"); + run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 -D DSP_NAME=$__MUL16X16", "(if -dsp)"); run("opt_expr -fine", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); run("chtype -set $mul t:$__soft_mul","(if -dsp)"); From 1f722b35009275ad9a3f4ce4224fcb6973e3bc80 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 8 Aug 2019 16:33:20 -0700 Subject: [PATCH 120/356] Remove signed from ports in +/xilinx/dsp_map.v --- techlibs/xilinx/dsp_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v index 423e12fbe..fdd55afe3 100644 --- a/techlibs/xilinx/dsp_map.v +++ b/techlibs/xilinx/dsp_map.v @@ -1,4 +1,4 @@ -module \$__MUL25X18 (input signed [24:0] A, input signed [17:0] B, output signed [42:0] Y); +module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 0; From 747690a6df9e51b4065003b50b0f07042712f112 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 8 Aug 2019 16:33:37 -0700 Subject: [PATCH 121/356] Remove muxY and ffY for now --- passes/pmgen/xilinx_dsp.cc | 10 +++---- passes/pmgen/xilinx_dsp.pmg | 58 ++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 74bcbf451..389f0cb56 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -38,7 +38,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("ffB: %s\n", log_id(st.ffB, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); - log("muxP: %s\n", log_id(st.muxP, "--")); + //log("muxP: %s\n", log_id(st.muxP, "--")); log("sigPused: %s\n", log_signal(st.sigPused)); log_module(pm.module); #endif @@ -81,9 +81,9 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) if (st.ffP) { SigSpec P = cell->getPort("\\P"); SigSpec D; - if (st.muxP) - D = st.muxP->getPort("\\B"); - else + //if (st.muxP) + // D = st.muxP->getPort("\\B"); + //else D = st.ffP->getPort("\\D"); SigSpec Q = st.ffP->getPort("\\Q"); P.replace(pm.sigmap(D), Q); @@ -107,7 +107,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log(" ffB:%s", log_id(st.ffB)); if (st.ffP) - log(" ffY:%s", log_id(st.ffP)); + log(" ffP:%s", log_id(st.ffP)); log("\n"); } diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 8abae9316..f95de9410 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -47,11 +47,9 @@ endcode // (as opposed to being a dummy) code sigPused SigSpec P = port(dsp, \P); - int i; - for (i = GetSize(P); i > 0; i--) - if (nusers(P[i-1]) > 1) - break; - sigPused = P.extract(0, i).remove_const(); + for (int i = 0; i < GetSize(P); i++) + if (P[i].wire && nusers(P[i]) > 1) + sigPused.append(P[i]); endcode match ffP @@ -66,33 +64,33 @@ match ffP optional endmatch -// $mux cell left behind by dff2dffe -// would prefer not to run 'opt_expr -mux_undef' -// since that would lose information helpful for -// efficient wide-mux inference -match muxP - if !sigPused.empty() && !ffP - select muxP->type.in($mux) - select nusers(port(muxP, \B)) == 2 - select port(muxP, \A).is_fully_undef() - filter param(muxP, \WIDTH).as_int() >= GetSize(sigPused) - filter includes(port(muxP, \B).to_sigbit_set(), sigPused.to_sigbit_set()) - optional -endmatch - -match ffY - if muxP - select ffY->type.in($dff, $dffe) - select nusers(port(ffY, \D)) == 2 - // DSP48E1 does not support clock inversion - select param(ffY, \CLK_POLARITY).as_bool() - filter param(ffY, \WIDTH).as_int() >= GetSize(sigPused) - filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set()) -endmatch +//// $mux cell left behind by dff2dffe +//// would prefer not to run 'opt_expr -mux_undef' +//// since that would lose information helpful for +//// efficient wide-mux inference +//match muxP +// if !sigPused.empty() && !ffP +// select muxP->type.in($mux) +// select nusers(port(muxP, \B)) == 2 +// select port(muxP, \A).is_fully_undef() +// filter param(muxP, \WIDTH).as_int() >= GetSize(sigPused) +// filter includes(port(muxP, \B).to_sigbit_set(), sigPused.to_sigbit_set()) +// optional +//endmatch +// +//match ffY +// if muxP +// select ffY->type.in($dff, $dffe) +// select nusers(port(ffY, \D)) == 2 +// // DSP48E1 does not support clock inversion +// select param(ffY, \CLK_POLARITY).as_bool() +// filter param(ffY, \WIDTH).as_int() >= GetSize(sigPused) +// filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set()) +//endmatch code ffP clock - if (ffY) - ffP = ffY; +// if (ffY) +// ffP = ffY; if (ffP) { SigBit c = port(ffP, \CLK).as_bit(); From 82cbfada1bd826fad2407010ceb243ab614ae875 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 14:14:28 -0700 Subject: [PATCH 122/356] Revert "Fix typo" This reverts commit e3c39cc450a0317ad7e8234bb866d55465548c9c. --- passes/pmgen/ice40_dsp.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 1a62c7bda..c57d3f1b3 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -143,7 +143,7 @@ code addAB sigCD sigO if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) reject; - if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \B_SIGNED).as_bool())) + if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) reject; sigO = port(addAB, \Y); From a002eba14a9895c7330a2741a49de02faf1af06f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 14:27:08 -0700 Subject: [PATCH 123/356] Fix check --- passes/pmgen/ice40_dsp.pmg | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index c57d3f1b3..41f34b4bd 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -119,15 +119,16 @@ match addB endmatch code addAB sigCD sigO + bool CD_SIGNED = false; if (addA) { addAB = addA; sigCD = port(addAB, \B); - sigCD.extend_u0(32, param(addAB, \B_SIGNED).as_bool()); + CD_SIGNED = param(addAB, \B_SIGNED).as_bool(); } if (addB) { addAB = addB; sigCD = port(addAB, \A); - sigCD.extend_u0(32, param(addAB, \A_SIGNED).as_bool()); + CD_SIGNED = param(addAB, \A_SIGNED).as_bool(); } if (addAB) { if (mul->type == \SB_MAC16) { @@ -139,7 +140,7 @@ code addAB sigCD sigO int natural_mul_width = GetSize(sigA) + GetSize(sigB); int actual_mul_width = GetSize(sigH); - int actual_acc_width = GetSize(sigO); + int actual_acc_width = GetSize(sigCD); if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) reject; @@ -147,6 +148,7 @@ code addAB sigCD sigO reject; sigO = port(addAB, \Y); + sigCD.extend_u0(32, CD_SIGNED); } endcode @@ -255,7 +257,7 @@ code clock clock_pol sigO sigCD else if (muxB) sigCD = port(muxAB, \A); else log_abort(); - sigCD.extend_u0(32, addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool()); + sigCD.extend_u0(32, addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool()); } } endcode From 0b5b56c1ecab78d126bbab13598c184f5e28cccc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 15:19:33 -0700 Subject: [PATCH 124/356] Pack partial-product adder DSP48E1 packing --- passes/pmgen/xilinx_dsp.cc | 22 ++++++++--- passes/pmgen/xilinx_dsp.pmg | 67 ++++++++++++++++++++++++++++++--- techlibs/xilinx/synth_xilinx.cc | 2 + 3 files changed, 81 insertions(+), 10 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 389f0cb56..cd88f9449 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -37,16 +37,26 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("ffA: %s\n", log_id(st.ffA, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); + log("addAB: %s\n", log_id(st.addAB, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); //log("muxP: %s\n", log_id(st.muxP, "--")); log("sigPused: %s\n", log_signal(st.sigPused)); - log_module(pm.module); #endif - log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.dsp)); + log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); Cell *cell = st.dsp; - log_assert(cell); + SigSpec P = st.sigP; + + if (st.addAB) { + log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + cell->setPort("\\C", st.sigC.extend_u0(48, true)); + SigSpec &opmode = cell->connections_.at("\\OPMODE"); + opmode[6] = State::S0; + opmode[5] = State::S1; + opmode[4] = State::S1; + pm.autoremove(st.addAB); + } if (st.clock != SigBit()) { @@ -79,7 +89,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) else log_abort(); } if (st.ffP) { - SigSpec P = cell->getPort("\\P"); SigSpec D; //if (st.muxP) // D = st.muxP->getPort("\\B"); @@ -87,7 +96,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) D = st.ffP->getPort("\\D"); SigSpec Q = st.ffP->getPort("\\Q"); P.replace(pm.sigmap(D), Q); - cell->setPort("\\P", P); cell->setParam("\\PREG", State::S1); if (st.ffP->type == "$dff") cell->setPort("\\CEP", State::S1); @@ -112,6 +120,10 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("\n"); } + if (GetSize(P) < 48) + P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); + cell->setPort("\\P", P); + pm.blacklist(cell); } diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index f95de9410..4f5fae8df 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,7 +1,8 @@ pattern xilinx_dsp state clock -state sigPused +state sigC sigP sigPused +state addAB match dsp select dsp->type.in(\DSP48E1) @@ -43,13 +44,69 @@ code clock } endcode +code sigP + sigP = port(dsp, \P); +endcode + +match addA + select addA->type.in($add) + select param(addA, \A_SIGNED).as_bool() && param(addA, \B_SIGNED).as_bool() + select nusers(port(addA, \A)) == 2 + //index port(addA, \A) === sigP.extract(0, param(addA, \A_WIDTH).as_int()) + filter GetSize(sigP) >= param(addA, \A_WIDTH).as_int() + filter port(addA, \A) == sigP.extract(0, param(addA, \A_WIDTH).as_int()) + optional +endmatch + +match addB + if !addA + select addB->type.in($add, $sub) + select param(addB, \A_SIGNED).as_bool() && param(addB, \B_SIGNED).as_bool() + select nusers(port(addB, \B)) == 2 + //index port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int()) + filter GetSize(sigP) >= param(addB, \B_WIDTH).as_int() + filter port(addB, \B) == sigP.extract(0, param(addB, \B_WIDTH).as_int()) + optional +endmatch + +code addAB sigC sigP + bool C_SIGNED = false; + if (addA) { + addAB = addA; + sigC = port(addAB, \B); + C_SIGNED = param(addAB, \B_SIGNED).as_bool(); + } + if (addB) { + addAB = addB; + sigC = port(addAB, \A); + C_SIGNED = param(addAB, \B_SIGNED).as_bool(); + } + if (addAB) { + // Ensure that adder is not used + SigSpec opmodeZ = port(dsp, \OPMODE).extract(4,3); + if (!opmodeZ.is_fully_zero()) + reject; + + int natural_mul_width = GetSize(port(dsp, \A)) + GetSize(port(dsp, \B)); + int actual_mul_width = GetSize(sigP); + int actual_acc_width = GetSize(sigC); + + if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) + reject; + //if ((actual_acc_width != actual_mul_width) && (param(dsp, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) + // reject; + + sigP = port(addAB, \Y); + sigC.extend_u0(32, C_SIGNED); + } +endcode + // Extract the bits of P that actually have a consumer // (as opposed to being a dummy) code sigPused - SigSpec P = port(dsp, \P); - for (int i = 0; i < GetSize(P); i++) - if (P[i].wire && nusers(P[i]) > 1) - sigPused.append(P[i]); + for (int i = 0; i < GetSize(sigP); i++) + if (sigP[i].wire && nusers(sigP[i]) > 1) + sigPused.append(sigP[i]); endcode match ffP diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7b1fe5e3b..a54b3ac52 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -287,6 +287,8 @@ struct SynthXilinxPass : public ScriptPass if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); + run("opt_expr -fine", " (skip if '-nodsp')"); + run("wreduce", " (skip if '-nodsp')"); run("xilinx_dsp", " (skip if '-nodsp')"); run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); } From e83f231927c41e1771da2e8d1a2153361afc30b0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 15:47:40 -0700 Subject: [PATCH 125/356] Cleanup --- passes/pmgen/ice40_dsp.pmg | 16 ++++++++-------- passes/pmgen/xilinx_dsp.pmg | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 41f34b4bd..a1b0b5004 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -21,8 +21,8 @@ code sigH endcode match ffA + if mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool() select ffA->type.in($dff) - filter mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool() filter !port(mul, \A).remove_const().empty() filter includes(port(ffA, \Q).to_sigbit_set(), port(mul, \A).remove_const().to_sigbit_set()) optional @@ -44,8 +44,8 @@ code sigA clock clock_pol endcode match ffB + if mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool() select ffB->type.in($dff) - filter mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool() filter !port(mul, \B).remove_const().empty() filter includes(port(ffB, \Q).to_sigbit_set(), port(mul, \B).remove_const().to_sigbit_set()) optional @@ -73,11 +73,11 @@ code sigB clock clock_pol endcode match ffH + if mul->type != \SB_MAC16 || (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool()) select ffH->type.in($dff) select nusers(port(ffH, \D)) == 2 index port(ffH, \D) === sigH // Ensure pipeline register is not already used - filter mul->type != \SB_MAC16 || (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool()) optional endmatch @@ -154,7 +154,7 @@ endcode match muxA select muxA->type.in($mux) - select nusers(port(muxA, \A)) == 2 + index nusers(port(muxA, \A)) === 2 index port(muxA, \A) === sigO optional endmatch @@ -162,7 +162,7 @@ endmatch match muxB if !muxA select muxB->type.in($mux) - select nusers(port(muxB, \B)) == 2 + index nusers(port(muxB, \B)) === 2 index port(muxB, \B) === sigO optional endmatch @@ -185,16 +185,16 @@ code sigOused endcode match ffO_lo + if nusers(sigOused.extract(0,std::min(16,GetSize(sigOused)))) == 2 select ffO_lo->type.in($dff) - filter nusers(sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int()))) == 2 filter includes(port(ffO_lo, \D).to_sigbit_set(), sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int())).remove_const().to_sigbit_set()) optional endmatch match ffO_hi + if GetSize(sigOused) > 16 + if nusers(sigOused.extract_end(16)) == 2 select ffO_hi->type.in($dff) - filter GetSize(sigOused) > 16 - filter nusers(sigOused.extract_end(16)) == 2 filter includes(port(ffO_hi, \D).to_sigbit_set(), sigOused.extract_end(16).remove_const().to_sigbit_set()) optional endmatch diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 4f5fae8df..f982a10cf 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -9,11 +9,11 @@ match dsp endmatch match ffA + if param(dsp, \AREG).as_int() == 0 + if !port(dsp, \A).remove_const().empty() select ffA->type.in($dff) // DSP48E1 does not support clock inversion select param(ffA, \CLK_POLARITY).as_bool() - filter param(dsp, \AREG).as_int() == 0 - filter !port(dsp, \A).remove_const().empty() filter includes(port(ffA, \Q).to_sigbit_set(), port(dsp, \A).remove_const().to_sigbit_set()) optional endmatch @@ -24,11 +24,11 @@ code clock endcode match ffB + if param(dsp, \BREG).as_int() == 0 + if !port(dsp, \B).remove_const().empty() select ffB->type.in($dff) // DSP48E1 does not support clock inversion select param(ffB, \CLK_POLARITY).as_bool() - filter param(dsp, \BREG).as_int() == 0 - filter !port(dsp, \B).remove_const().empty() filter includes(port(ffB, \Q).to_sigbit_set(), port(dsp, \B).remove_const().to_sigbit_set()) optional endmatch @@ -51,9 +51,9 @@ endcode match addA select addA->type.in($add) select param(addA, \A_SIGNED).as_bool() && param(addA, \B_SIGNED).as_bool() - select nusers(port(addA, \A)) == 2 + index nusers(port(addA, \A)) === 2 //index port(addA, \A) === sigP.extract(0, param(addA, \A_WIDTH).as_int()) - filter GetSize(sigP) >= param(addA, \A_WIDTH).as_int() + filter param(addA, \A_WIDTH).as_int() <= GetSize(sigP) filter port(addA, \A) == sigP.extract(0, param(addA, \A_WIDTH).as_int()) optional endmatch @@ -62,9 +62,9 @@ match addB if !addA select addB->type.in($add, $sub) select param(addB, \A_SIGNED).as_bool() && param(addB, \B_SIGNED).as_bool() - select nusers(port(addB, \B)) == 2 + index nusers(port(addB, \B)) === 2 //index port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int()) - filter GetSize(sigP) >= param(addB, \B_WIDTH).as_int() + filter param(addB, \B_WIDTH).as_int() <= GetSize(sigP) filter port(addB, \B) == sigP.extract(0, param(addB, \B_WIDTH).as_int()) optional endmatch @@ -110,12 +110,12 @@ code sigPused endcode match ffP + if param(dsp, \PREG).as_int() == 0 if !sigPused.empty() select ffP->type.in($dff) - select nusers(port(ffP, \D)) == 2 + index nusers(port(ffP, \D)) === 2 // DSP48E1 does not support clock inversion select param(ffP, \CLK_POLARITY).as_bool() - filter param(dsp, \PREG).as_int() == 0 filter param(ffP, \WIDTH).as_int() >= GetSize(sigPused) filter includes(port(ffP, \D).to_sigbit_set(), sigPused.to_sigbit_set()) optional From dfc878deb4caadbb058588b2b70b374b37978b27 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 16:23:32 -0700 Subject: [PATCH 126/356] Another filter -> if --- passes/pmgen/ice40_dsp.pmg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index a1b0b5004..e0a213e85 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -22,8 +22,8 @@ endcode match ffA if mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool() + if !port(mul, \A).remove_const().empty() select ffA->type.in($dff) - filter !port(mul, \A).remove_const().empty() filter includes(port(ffA, \Q).to_sigbit_set(), port(mul, \A).remove_const().to_sigbit_set()) optional endmatch @@ -45,8 +45,8 @@ endcode match ffB if mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool() + if !port(mul, \B).remove_const().empty() select ffB->type.in($dff) - filter !port(mul, \B).remove_const().empty() filter includes(port(ffB, \Q).to_sigbit_set(), port(mul, \B).remove_const().to_sigbit_set()) optional endmatch From 6d254f2de802ccd71b6514b0f5e4c0b44c415ae4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 17:05:56 -0700 Subject: [PATCH 127/356] Add wreduce to synth_ice40 -dsp as well --- techlibs/ice40/synth_ice40.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 9c3670c7c..02598401c 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -268,6 +268,7 @@ struct SynthIce40Pass : public ScriptPass if (help_mode || dsp) { run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 -D DSP_NAME=$__MUL16X16", "(if -dsp)"); run("opt_expr -fine", " (if -dsp)"); + run("wreduce", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); run("chtype -set $mul t:$__soft_mul","(if -dsp)"); } From 3dd3ab98c2bb83f644fb1962d4de27a7416b0113 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 17:23:12 -0700 Subject: [PATCH 128/356] Improve ice40_dsp for non-fully-32-bit adders --- passes/pmgen/ice40_dsp.pmg | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index e0a213e85..c59c5d20a 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -106,7 +106,9 @@ endcode match addA select addA->type.in($add) select nusers(port(addA, \A)) == 2 - index port(addA, \A) === sigH + filter param(addA, \A_WIDTH).as_int() <= GetSize(sigH) + //index port(addA, \A) === sigH.extract(0, param(addA, \A_WIDTH).as_int()) + filter port(addA, \A) == sigH.extract(0, param(addA, \A_WIDTH).as_int()) optional endmatch @@ -114,7 +116,9 @@ match addB if !addA select addB->type.in($add, $sub) select nusers(port(addB, \B)) == 2 - index port(addB, \B) === sigH + filter param(addB, \B_WIDTH).as_int() <= GetSize(sigH) + //index port(addB, \B) === sigH.extract(0, param(addB, \B_WIDTH).as_int()) + filter port(addB, \B) == sigH.extract(0, param(addB, \B_WIDTH).as_int()) optional endmatch @@ -144,7 +148,8 @@ code addAB sigCD sigO if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) reject; - if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) + // If accumulator, check adder width and signedness + if (sigCD == sigH && (actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) reject; sigO = port(addAB, \Y); From ab1d63a56595f11e10a5326bd83ce84d08badabe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 17:35:13 -0700 Subject: [PATCH 129/356] Check nusers of DSP output, not whole flop --- passes/pmgen/xilinx_dsp.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index f982a10cf..5dee36a11 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -112,8 +112,8 @@ endcode match ffP if param(dsp, \PREG).as_int() == 0 if !sigPused.empty() + if nusers(sigPused) == 2 select ffP->type.in($dff) - index nusers(port(ffP, \D)) === 2 // DSP48E1 does not support clock inversion select param(ffP, \CLK_POLARITY).as_bool() filter param(ffP, \WIDTH).as_int() >= GetSize(sigPused) From edff79a25a802e5b1816608b48e3ac335ad87147 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 13 Aug 2019 10:29:42 +0100 Subject: [PATCH 130/356] xilinx: Rework labels for faster Verilator testing Signed-off-by: David Shah --- techlibs/xilinx/synth_xilinx.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 265cee6d6..546d67337 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -255,7 +255,7 @@ struct SynthXilinxPass : public ScriptPass run(stringf("hierarchy -check %s", top_opt.c_str())); } - if (check_label("coarse")) { + if (check_label("prepare")) { run("proc"); if (flatten || help_mode) run("flatten", "(with '-flatten')"); @@ -283,7 +283,9 @@ struct SynthXilinxPass : public ScriptPass } run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); + } + if (check_label("dsp")) { if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); @@ -292,7 +294,9 @@ struct SynthXilinxPass : public ScriptPass run("xilinx_dsp", " (skip if '-nodsp')"); run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); } + } + if (check_label("coarse")) { run("alumacc"); run("share"); run("opt"); From 2a1b98d478918b0a17c7e509ada6e7a71bbab526 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 13 Aug 2019 10:21:24 -0700 Subject: [PATCH 131/356] Add DSP_A_MAXWIDTH_PARTIAL, refactor --- techlibs/common/mul2dsp.v | 254 ++++++++++++++------------------ techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 111 insertions(+), 145 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 8e37201e2..71d5a5454 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -27,20 +27,30 @@ */ `ifndef DSP_A_MAXWIDTH -$error("Macro DSP_A_MAXWIDTH must be defined"); +$fatal(1, "Macro DSP_A_MAXWIDTH must be defined"); `endif `ifndef DSP_B_MAXWIDTH -$error("Macro DSP_B_MAXWIDTH must be defined"); +$fatal(1, "Macro DSP_B_MAXWIDTH must be defined"); +`endif +`ifndef DSP_B_MAXWIDTH +$fatal(1, "Macro DSP_B_MAXWIDTH must be defined"); +`endif +`ifndef DSP_A_MAXWIDTH_PARTIAL +`define DSP_A_MAXWIDTH_PARTIAL `DSP_A_MAXWIDTH +`endif +`ifndef DSP_B_MAXWIDTH_PARTIAL +`define DSP_B_MAXWIDTH_PARTIAL `DSP_B_MAXWIDTH `endif `ifndef DSP_NAME -$error("Macro DSP_NAME must be defined"); +$fatal(1, "Macro DSP_NAME must be defined"); `endif `define MAX(a,b) (a > b ? a : b) `define MIN(a,b) (a < b ? a : b) -module \$mul (A, B, Y); +(* techmap_celltype = "$mul $__mul" *) +module _80_mul (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -51,12 +61,26 @@ module \$mul (A, B, Y); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; + parameter _TECHMAP_CELLTYPE_ = ""; + generate - if (A_SIGNED != B_SIGNED) + if (0) begin end +`ifdef DSP_A_MINWIDTH + else if (A_WIDTH < `DSP_A_MINWIDTH) + wire _TECHMAP_FAIL_ = 1; +`endif +`ifdef DSP_B_MINWIDTH + else if (B_WIDTH < `DSP_B_MINWIDTH) + wire _TECHMAP_FAIL_ = 1; +`endif +`ifdef DSP_Y_MINWIDTH + else if (Y_WIDTH < `DSP_Y_MINWIDTH) + wire _TECHMAP_FAIL_ = 1; +`endif + else if (_TECHMAP_CELLTYPE_ == "$mul" && A_SIGNED != B_SIGNED) wire _TECHMAP_FAIL_ = 1; - // NB: A_SIGNED == B_SIGNED from here `ifdef DSP_SIGNEDONLY - else if (!A_SIGNED) + else if (_TECHMAP_CELLTYPE_ == "$mul" && !A_SIGNED) \$mul #( .A_SIGNED(1), .B_SIGNED(1), @@ -81,102 +105,53 @@ module \$mul (A, B, Y); .B(A), .Y(Y) ); - else - \$__mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(A), - .B(B), - .Y(Y) - ); - endgenerate -endmodule - -module \$__mul (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire [1023:0] _TECHMAP_DO_ = "proc; clean"; + else begin + wire [1023:0] _TECHMAP_DO_ = "proc; clean"; `ifdef DSP_SIGNEDONLY - localparam sign_headroom = 1; + localparam sign_headroom = 1; `else - localparam sign_headroom = 0; + localparam sign_headroom = 0; `endif - genvar i; - generate - if (0) begin end -`ifdef DSP_A_MINWIDTH - else if (A_WIDTH < `DSP_A_MINWIDTH) - wire _TECHMAP_FAIL_ = 1; -`endif -`ifdef DSP_B_MINWIDTH - else if (B_WIDTH < `DSP_B_MINWIDTH) - wire _TECHMAP_FAIL_ = 1; -`endif -`ifdef DSP_Y_MINWIDTH - else if (Y_WIDTH < `DSP_Y_MINWIDTH) - wire _TECHMAP_FAIL_ = 1; -`endif - else if (A_WIDTH > `DSP_A_MAXWIDTH) begin - localparam n = (A_WIDTH+`DSP_A_MAXWIDTH-sign_headroom-1) / (`DSP_A_MAXWIDTH-sign_headroom); - localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH); - localparam last_Y_WIDTH = `MIN(partial_Y_WIDTH, B_WIDTH+A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)); + genvar i; + if (A_WIDTH > `DSP_A_MAXWIDTH) begin + localparam n = (A_WIDTH-`DSP_A_MAXWIDTH+`DSP_A_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_A_MAXWIDTH_PARTIAL-sign_headroom); + localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH_PARTIAL); + localparam last_A_WIDTH = A_WIDTH-n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom); + localparam last_Y_WIDTH = B_WIDTH+last_A_WIDTH; if (A_SIGNED && B_SIGNED) begin - wire signed [partial_Y_WIDTH-1:0] partial [n-2:0]; + wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; wire signed [last_Y_WIDTH-1:0] last_partial; - wire signed [Y_WIDTH-1:0] partial_sum [n-1:0]; + wire signed [Y_WIDTH-1:0] partial_sum [n:0]; end else begin wire [partial_Y_WIDTH-1:0] partial [n-1:0]; wire [last_Y_WIDTH-1:0] last_partial; - wire [Y_WIDTH-1:0] partial_sum [n-1:0]; + wire [Y_WIDTH-1:0] partial_sum [n:0]; end - \$__mul #( - .A_SIGNED(sign_headroom), - .B_SIGNED(B_SIGNED), - .A_WIDTH(`DSP_A_MAXWIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(partial_Y_WIDTH) - ) mul_slice_first ( - .A({{sign_headroom{1'b0}}, A[`DSP_A_MAXWIDTH-sign_headroom-1 : 0]}), - .B(B), - .Y(partial[0]) - ); - assign partial_sum[0] = partial[0]; - - for (i = 1; i < n-1; i=i+1) begin:slice + for (i = 0; i < n; i=i+1) begin:slice \$__mul #( .A_SIGNED(sign_headroom), .B_SIGNED(B_SIGNED), - .A_WIDTH(`DSP_A_MAXWIDTH), + .A_WIDTH(`DSP_A_MAXWIDTH_PARTIAL), .B_WIDTH(B_WIDTH), .Y_WIDTH(partial_Y_WIDTH) ) mul_slice ( - .A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH-sign_headroom) +: `DSP_A_MAXWIDTH-sign_headroom]}), + .A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_A_MAXWIDTH_PARTIAL-sign_headroom]}), .B(B), .Y(partial[i]) ); // TODO: Currently a 'cascade' approach to summing the partial // products is taken here, but a more efficient 'binary // reduction' approach also exists... - assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; + if (i == 0) + assign partial_sum[i] = partial[i]; + else + assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; end - localparam last_A_WIDTH = A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom); \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), @@ -188,56 +163,46 @@ module \$__mul (A, B, Y); .B(B), .Y(last_partial) ); - assign partial_sum[n-1] = (last_partial << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; - assign Y = partial_sum[n-1]; + assign partial_sum[n] = (last_partial << n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; + assign Y = partial_sum[n]; end else if (B_WIDTH > `DSP_B_MAXWIDTH) begin - localparam n = (B_WIDTH+`DSP_B_MAXWIDTH-sign_headroom-1) / (`DSP_B_MAXWIDTH-sign_headroom); - localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH); - localparam last_Y_WIDTH = `MIN(partial_Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom)); + localparam n = (B_WIDTH-`DSP_B_MAXWIDTH+`DSP_B_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_B_MAXWIDTH_PARTIAL-sign_headroom); + localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH_PARTIAL); + localparam last_B_WIDTH = B_WIDTH-n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom); + localparam last_Y_WIDTH = A_WIDTH+last_B_WIDTH; if (A_SIGNED && B_SIGNED) begin - wire signed [partial_Y_WIDTH-1:0] partial [n-2:0]; + wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; wire signed [last_Y_WIDTH-1:0] last_partial; - wire signed [Y_WIDTH-1:0] partial_sum [n-1:0]; + wire signed [Y_WIDTH-1:0] partial_sum [n:0]; end else begin wire [partial_Y_WIDTH-1:0] partial [n-1:0]; wire [last_Y_WIDTH-1:0] last_partial; - wire [Y_WIDTH-1:0] partial_sum [n-1:0]; + wire [Y_WIDTH-1:0] partial_sum [n:0]; end - \$__mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(sign_headroom), - .A_WIDTH(A_WIDTH), - .B_WIDTH(`DSP_B_MAXWIDTH), - .Y_WIDTH(partial_Y_WIDTH) - ) mul_first ( - .A(A), - .B({{sign_headroom{1'b0}}, B[`DSP_B_MAXWIDTH-sign_headroom-1 : 0]}), - .Y(partial[0]) - ); - assign partial_sum[0] = partial[0]; - - for (i = 1; i < n-1; i=i+1) begin:slice + for (i = 0; i < n; i=i+1) begin:slice \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(sign_headroom), .A_WIDTH(A_WIDTH), - .B_WIDTH(`DSP_B_MAXWIDTH), + .B_WIDTH(`DSP_B_MAXWIDTH_PARTIAL), .Y_WIDTH(partial_Y_WIDTH) ) mul ( .A(A), - .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH-sign_headroom) +: `DSP_B_MAXWIDTH-sign_headroom]}), + .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_B_MAXWIDTH_PARTIAL-sign_headroom]}), .Y(partial[i]) ); - // TODO: Currently a 'cascade' approach to summing the partial + // TODO: Currently a 'cascade' approach to summing the partial // products is taken here, but a more efficient 'binary // reduction' approach also exists... - assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[i-1]; + if (i == 0) + assign partial_sum[i] = partial[i]; + else + assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; end - localparam last_B_WIDTH = B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom); \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), @@ -249,10 +214,10 @@ module \$__mul (A, B, Y); .B(B[B_WIDTH-1 -: last_B_WIDTH]), .Y(last_partial) ); - assign partial_sum[n-1] = (last_partial << (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[n-2]; - assign Y = partial_sum[n-1]; + assign partial_sum[n] = (last_partial << n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; + assign Y = partial_sum[n]; end - else begin + else begin if (A_SIGNED) wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A); else @@ -274,11 +239,12 @@ module \$__mul (A, B, Y); .Y(Y) ); end + end endgenerate endmodule -(* techmap_celltype = "$__mul" *) -module $__soft_mul (A, B, Y); +(* techmap_celltype = "$mul $__mul" *) +module _90_soft_mul (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -292,41 +258,41 @@ module $__soft_mul (A, B, Y); // Indirection necessary since mapping // back to $mul will cause recursion generate - if (A_SIGNED && !B_SIGNED) - \$__soft__mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(1), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH+1), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(A), - .B({1'b0,B}), - .Y(Y) - ); - else if (!A_SIGNED && B_SIGNED) - \$__soft_mul #( - .A_SIGNED(1), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH+1), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A({1'b0,A}), - .B(B), - .Y(Y) - ); - else - \$__soft_mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(A), - .B(B), - .Y(Y) - ); + if (A_SIGNED && !B_SIGNED) + \$__soft_mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(1), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH+1), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A), + .B({1'b0,B}), + .Y(Y) + ); + else if (!A_SIGNED && B_SIGNED) + \$__soft_mul #( + .A_SIGNED(1), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH+1), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A({1'b0,A}), + .B(B), + .Y(Y) + ); + else + \$__soft_mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A), + .B(B), + .Y(Y) + ); endgenerate endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 265cee6d6..477b2f6f7 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -286,7 +286,7 @@ struct SynthXilinxPass : public ScriptPass if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only - run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); + run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); run("opt_expr -fine", " (skip if '-nodsp')"); run("wreduce", " (skip if '-nodsp')"); run("xilinx_dsp", " (skip if '-nodsp')"); From 0597a3ea238ee100607271fb25a2d09fbd128bf0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 13 Aug 2019 10:23:07 -0700 Subject: [PATCH 132/356] Rename to XilinxDspPass --- passes/pmgen/xilinx_dsp.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index cd88f9449..31c0d48c5 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -127,8 +127,8 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) pm.blacklist(cell); } -struct Ice40DspPass : public Pass { - Ice40DspPass() : Pass("xilinx_dsp", "Xilinx: pack DSP registers") { } +struct XilinxDspPass : public Pass { + XilinxDspPass() : Pass("xilinx_dsp", "Xilinx: pack DSP registers") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -156,6 +156,6 @@ struct Ice40DspPass : public Pass { for (auto module : design->selected_modules()) xilinx_dsp_pm(module, module->selected_cells()).run_xilinx_dsp(pack_xilinx_dsp); } -} Ice40DspPass; +} XilinxDspPass; PRIVATE_NAMESPACE_END From ed4b2834ef6ed811318c897bd6f8b19b6ec15f38 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 13 Aug 2019 12:19:26 -0700 Subject: [PATCH 133/356] Add assign PCOUT = P to DSP48E1 --- techlibs/xilinx/cells_sim.v | 2 ++ 1 file changed, 2 insertions(+) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 2731cb454..02ce0d61b 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -784,4 +784,6 @@ module DSP48E1 ( end endgenerate + assign PCOUT = P; + endmodule From e35dfc5ab591968d86259b90a643f1545e79e661 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 13 Aug 2019 16:52:15 -0700 Subject: [PATCH 134/356] Only swap ports if $mul and not $__mul --- techlibs/common/mul2dsp.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 71d5a5454..75b1242a2 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -93,7 +93,7 @@ module _80_mul (A, B, Y); .Y(Y) ); `endif - else if (A_WIDTH < B_WIDTH) + else if (_TECHMAP_CELLTYPE_ == "$mul" && A_WIDTH < B_WIDTH) \$mul #( .A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), From 1b0e68db945ee8a62a445cf41668844812c436eb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 13 Aug 2019 17:09:28 -0700 Subject: [PATCH 135/356] Revert changes to RTLIL::SigSpec methods --- kernel/rtlil.cc | 6 ++---- kernel/rtlil.h | 8 ++++---- passes/pmgen/ice40_dsp.cc | 3 ++- passes/pmgen/ice40_dsp.pmg | 34 ++++++++++++++++++++++++++++------ 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 909f60dd9..fade0bc36 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3299,7 +3299,7 @@ void RTLIL::SigSpec::replace(int offset, const RTLIL::SigSpec &with) check(); } -RTLIL::SigSpec& RTLIL::SigSpec::remove_const() +void RTLIL::SigSpec::remove_const() { if (packed()) { @@ -3333,7 +3333,6 @@ RTLIL::SigSpec& RTLIL::SigSpec::remove_const() } check(); - return *this; } void RTLIL::SigSpec::remove(int offset, int length) @@ -3429,7 +3428,7 @@ void RTLIL::SigSpec::append_bit(const RTLIL::SigBit &bit) check(); } -RTLIL::SigSpec& RTLIL::SigSpec::extend_u0(int width, bool is_signed) +void RTLIL::SigSpec::extend_u0(int width, bool is_signed) { cover("kernel.rtlil.sigspec.extend_u0"); @@ -3446,7 +3445,6 @@ RTLIL::SigSpec& RTLIL::SigSpec::extend_u0(int width, bool is_signed) append(padding); } - return *this; } RTLIL::SigSpec RTLIL::SigSpec::repeat(int num) const diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 16fd852ba..37b5f984c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -754,8 +754,8 @@ public: inline int size() const { return width_; } inline bool empty() const { return width_ == 0; } - inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return index >= 0 ? bits_.at(index) : bits_.at(width_ + index); } - inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return index >= 0 ? bits_.at(index) : bits_.at(width_ + index); } + inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return bits_.at(index); } + inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return bits_.at(index); } inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; } inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = width_; return it; } @@ -787,7 +787,7 @@ public: void remove2(const std::set &pattern, RTLIL::SigSpec *other); void remove(int offset, int length = 1); - RTLIL::SigSpec& remove_const(); + void remove_const(); RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; RTLIL::SigSpec extract(const pool &pattern, const RTLIL::SigSpec *other = NULL) const; @@ -797,7 +797,7 @@ public: void append(const RTLIL::SigSpec &signal); void append_bit(const RTLIL::SigBit &bit); - RTLIL::SigSpec& extend_u0(int width, bool is_signed = false); + void extend_u0(int width, bool is_signed = false); RTLIL::SigSpec repeat(int num) const; diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index bb45b8a4e..66f70399d 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -23,9 +23,10 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -template bool includes(const T &lhs, const T &rhs) { +template inline bool includes(const T &lhs, const T &rhs) { return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } +#include #include "passes/pmgen/ice40_dsp_pm.h" void create_ice40_dsp(ice40_dsp_pm &pm) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index c59c5d20a..cda7535f3 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -2,6 +2,7 @@ pattern ice40_dsp state clock state clock_pol +state > sigAset sigBset state sigA sigB sigCD sigH sigO sigOused state addAB muxAB @@ -10,6 +11,15 @@ match mul select GetSize(mul->getPort(\A)) + GetSize(mul->getPort(\B)) > 10 endmatch +code sigAset sigBset + SigSpec A = port(mul, \A); + A.remove_const(); + sigAset = A.to_sigbit_set(); + SigSpec B = port(mul, \B); + B.remove_const(); + sigBset = B.to_sigbit_set(); +endcode + code sigH if (mul->type == $mul) sigH = mul->getPort(\Y); @@ -22,9 +32,9 @@ endcode match ffA if mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool() - if !port(mul, \A).remove_const().empty() + if !sigAset.empty() select ffA->type.in($dff) - filter includes(port(ffA, \Q).to_sigbit_set(), port(mul, \A).remove_const().to_sigbit_set()) + filter includes(port(ffA, \Q).to_sigbit_set(), sigAset) optional endmatch @@ -45,9 +55,9 @@ endcode match ffB if mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool() - if !port(mul, \B).remove_const().empty() + if !sigBset.empty() select ffB->type.in($dff) - filter includes(port(ffB, \Q).to_sigbit_set(), port(mul, \B).remove_const().to_sigbit_set()) + filter includes(port(ffB, \Q).to_sigbit_set(), sigBset) optional endmatch @@ -192,18 +202,30 @@ endcode match ffO_lo if nusers(sigOused.extract(0,std::min(16,GetSize(sigOused)))) == 2 select ffO_lo->type.in($dff) - filter includes(port(ffO_lo, \D).to_sigbit_set(), sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int())).remove_const().to_sigbit_set()) optional endmatch +code + SigSpec O = sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int())); + O.remove_const(); + if (!includes(port(ffO_lo, \D).to_sigbit_set(), O.to_sigbit_set())) + reject; +endcode + match ffO_hi if GetSize(sigOused) > 16 if nusers(sigOused.extract_end(16)) == 2 select ffO_hi->type.in($dff) - filter includes(port(ffO_hi, \D).to_sigbit_set(), sigOused.extract_end(16).remove_const().to_sigbit_set()) optional endmatch +code + SigSpec O = sigOused.extract_end(16); + O.remove_const(); + if (!includes(port(ffO_hi, \D).to_sigbit_set(), O.to_sigbit_set())) + reject; +endcode + code clock clock_pol sigO sigCD if (ffO_lo || ffO_hi) { if (mul->type == \SB_MAC16) { From 2f04beeeb5114058ce762d0393859d517a9a35eb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 13 Aug 2019 17:11:35 -0700 Subject: [PATCH 136/356] Perform C -> PCIN optimisation after pattern matcher --- passes/pmgen/xilinx_dsp.cc | 67 +++++++++++++++++++++++++++++++------ passes/pmgen/xilinx_dsp.pmg | 24 ++++++++----- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 31c0d48c5..e7b72e312 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -23,22 +23,23 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -template bool includes(const T &lhs, const T &rhs) { +template inline bool includes(const T &lhs, const T &rhs) { return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } +#include #include "passes/pmgen/xilinx_dsp_pm.h" -void pack_xilinx_dsp(xilinx_dsp_pm &pm) +void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) { auto &st = pm.st_xilinx_dsp; #if 1 log("\n"); - log("ffA: %s\n", log_id(st.ffA, "--")); - log("ffB: %s\n", log_id(st.ffB, "--")); - log("dsp: %s\n", log_id(st.dsp, "--")); - log("addAB: %s\n", log_id(st.addAB, "--")); - log("ffP: %s\n", log_id(st.ffP, "--")); + log("ffA: %s\n", log_id(st.ffA, "--")); + log("ffB: %s\n", log_id(st.ffB, "--")); + log("dsp: %s\n", log_id(st.dsp, "--")); + log("addAB: %s\n", log_id(st.addAB, "--")); + log("ffP: %s\n", log_id(st.ffP, "--")); //log("muxP: %s\n", log_id(st.muxP, "--")); log("sigPused: %s\n", log_signal(st.sigPused)); #endif @@ -46,11 +47,17 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); Cell *cell = st.dsp; + bit_to_driver.insert(std::make_pair(cell->getPort("\\P")[17], cell)); SigSpec P = st.sigP; if (st.addAB) { + log_assert(st.addAB->getParam("\\A_SIGNED").as_bool()); + log_assert(st.addAB->getParam("\\B_SIGNED").as_bool()); log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); - cell->setPort("\\C", st.sigC.extend_u0(48, true)); + + SigSpec C = st.sigC; + C.extend_u0(48, true); + cell->setPort("\\C", C); SigSpec &opmode = cell->connections_.at("\\OPMODE"); opmode[6] = State::S0; opmode[5] = State::S1; @@ -153,8 +160,48 @@ struct XilinxDspPass : public Pass { } extra_args(args, argidx, design); - for (auto module : design->selected_modules()) - xilinx_dsp_pm(module, module->selected_cells()).run_xilinx_dsp(pack_xilinx_dsp); + for (auto module : design->selected_modules()) { + xilinx_dsp_pm pm(module, module->selected_cells()); + dict bit_to_driver; + auto f = [&bit_to_driver](xilinx_dsp_pm &pm){ pack_xilinx_dsp(bit_to_driver, pm); }; + pm.run_xilinx_dsp(f); + + // Look for ability to convert C input from another DSP into PCIN + // NB: Needs to be done after pattern matcher has folded all + // $add cells into the DSP + for (auto cell : module->cells()) { + if (cell->type != "\\DSP48E1") + continue; + SigSpec &opmode = cell->connections_.at("\\OPMODE"); + if (opmode.extract(4,3) != Const::from_string("011")) + continue; + SigSpec C = pm.sigmap(cell->getPort("\\C")); + if (C.has_const()) + continue; + auto it = bit_to_driver.find(C[0]); + if (it == bit_to_driver.end()) + continue; + auto driver = it->second; + + // Unextend C + int i; + for (i = GetSize(C)-1; i > 0; i--) + if (C[i] != C[i-1]) + break; + if (i > 48-17) + continue; + if (driver->getPort("\\P").extract(17, i) == C.extract(0, i)) { + cell->setPort("\\C", Const(0, 48)); + Wire *cascade = module->addWire(NEW_ID, 48); + driver->setPort("\\PCOUT", cascade); + cell->setPort("\\PCIN", cascade); + opmode[6] = State::S1; + opmode[5] = State::S0; + opmode[4] = State::S1; + bit_to_driver.erase(it); + } + } + } } } XilinxDspPass; diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 5dee36a11..1a3dcdcbb 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,6 +1,7 @@ pattern xilinx_dsp state clock +state > sigAset sigBset state sigC sigP sigPused state addAB @@ -8,13 +9,22 @@ match dsp select dsp->type.in(\DSP48E1) endmatch +code sigAset sigBset + SigSpec A = port(dsp, \A); + A.remove_const(); + sigAset = A.to_sigbit_set(); + SigSpec B = port(dsp, \B); + B.remove_const(); + sigBset = B.to_sigbit_set(); +endcode + match ffA if param(dsp, \AREG).as_int() == 0 - if !port(dsp, \A).remove_const().empty() + if !sigAset.empty() select ffA->type.in($dff) // DSP48E1 does not support clock inversion select param(ffA, \CLK_POLARITY).as_bool() - filter includes(port(ffA, \Q).to_sigbit_set(), port(dsp, \A).remove_const().to_sigbit_set()) + filter includes(port(ffA, \Q).to_sigbit_set(), sigAset) optional endmatch @@ -25,11 +35,11 @@ endcode match ffB if param(dsp, \BREG).as_int() == 0 - if !port(dsp, \B).remove_const().empty() + if !sigBset.empty() select ffB->type.in($dff) // DSP48E1 does not support clock inversion select param(ffB, \CLK_POLARITY).as_bool() - filter includes(port(ffB, \Q).to_sigbit_set(), port(dsp, \B).remove_const().to_sigbit_set()) + filter includes(port(ffB, \Q).to_sigbit_set(), sigBset) optional endmatch @@ -65,21 +75,18 @@ match addB index nusers(port(addB, \B)) === 2 //index port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int()) filter param(addB, \B_WIDTH).as_int() <= GetSize(sigP) - filter port(addB, \B) == sigP.extract(0, param(addB, \B_WIDTH).as_int()) + filter port(addB, \B) == sigP.extract(0, param(addB, \B_WIDTH).as_int()) optional endmatch code addAB sigC sigP - bool C_SIGNED = false; if (addA) { addAB = addA; sigC = port(addAB, \B); - C_SIGNED = param(addAB, \B_SIGNED).as_bool(); } if (addB) { addAB = addB; sigC = port(addAB, \A); - C_SIGNED = param(addAB, \B_SIGNED).as_bool(); } if (addAB) { // Ensure that adder is not used @@ -97,7 +104,6 @@ code addAB sigC sigP // reject; sigP = port(addAB, \Y); - sigC.extend_u0(32, C_SIGNED); } endcode From aad97168b070509b7bd479ed3b9956452a28e3ec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 14 Aug 2019 10:22:33 -0700 Subject: [PATCH 137/356] Fixes for reverting SigSpec helper functions --- passes/pmgen/ice40_dsp.cc | 4 ++-- passes/pmgen/ice40_dsp.pmg | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 66f70399d..6f0539679 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -155,9 +155,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // If we have a signed multiply-add, then perform sign extension // TODO: Need to check CD[31:16] is sign extension of CD[15:0]? if (st.addAB->getParam("\\A_SIGNED").as_bool() && st.addAB->getParam("\\B_SIGNED").as_bool()) - pm.module->connect(O[-1], O[-2]); + pm.module->connect(O[32], O[31]); else - cell->setPort("\\CO", O[-1]); + cell->setPort("\\CO", O[32]); O.remove(O_width-1); } else diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index cda7535f3..d64c8a391 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -206,10 +206,12 @@ match ffO_lo endmatch code - SigSpec O = sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int())); - O.remove_const(); - if (!includes(port(ffO_lo, \D).to_sigbit_set(), O.to_sigbit_set())) - reject; + if (ffO_lo) { + SigSpec O = sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int())); + O.remove_const(); + if (!includes(port(ffO_lo, \D).to_sigbit_set(), O.to_sigbit_set())) + reject; + } endcode match ffO_hi @@ -220,10 +222,12 @@ match ffO_hi endmatch code - SigSpec O = sigOused.extract_end(16); - O.remove_const(); - if (!includes(port(ffO_hi, \D).to_sigbit_set(), O.to_sigbit_set())) - reject; + if (ffO_hi) { + SigSpec O = sigOused.extract_end(16); + O.remove_const(); + if (!includes(port(ffO_hi, \D).to_sigbit_set(), O.to_sigbit_set())) + reject; + } endcode code clock clock_pol sigO sigCD From 27d5df9467fb425234a466d0d63b8a94e37ca596 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 15 Aug 2019 12:19:34 -0700 Subject: [PATCH 138/356] ffH -> ffFJKG --- passes/pmgen/ice40_dsp.cc | 14 +++++++------- passes/pmgen/ice40_dsp.pmg | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 6f0539679..a1a397b83 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -38,7 +38,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log("ffA: %s\n", log_id(st.ffA, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); log("mul: %s\n", log_id(st.mul, "--")); - log("ffH: %s\n", log_id(st.ffH, "--")); + log("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); log("addAB: %s\n", log_id(st.addAB, "--")); log("muxAB: %s\n", log_id(st.muxAB, "--")); log("ffO_lo: %s\n", log_id(st.ffO_lo, "--")); @@ -119,8 +119,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (st.ffB) log(" ffB:%s", log_id(st.ffB)); - if (st.ffH) - log(" ffH:%s", log_id(st.ffH)); + if (st.ffFJKG) + log(" ffFJKG:%s", log_id(st.ffFJKG)); if (st.ffO_lo) log(" ffO_lo:%s", log_id(st.ffO_lo)); @@ -206,9 +206,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\C_REG", State::S0); cell->setParam("\\D_REG", State::S0); - cell->setParam("\\TOP_8x8_MULT_REG", st.ffH ? State::S1 : State::S0); - cell->setParam("\\BOT_8x8_MULT_REG", st.ffH ? State::S1 : State::S0); - cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffH ? State::S1 : State::S0); + cell->setParam("\\TOP_8x8_MULT_REG", st.ffFJKG ? State::S1 : State::S0); + cell->setParam("\\BOT_8x8_MULT_REG", st.ffFJKG ? State::S1 : State::S0); + cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffFJKG ? State::S1 : State::S0); cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0); cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffO_hi ? 1 : (st.addAB ? 0 : 3), 2)); @@ -229,7 +229,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) pm.autoremove(st.mul); else pm.blacklist(st.mul); - pm.autoremove(st.ffH); + pm.autoremove(st.ffFJKG); pm.autoremove(st.addAB); if (st.ffO_lo) { SigSpec O = st.sigO.extract(0,std::min(16,st.ffO_lo->getParam("\\WIDTH").as_int())); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index d64c8a391..11064e072 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -82,11 +82,11 @@ code sigB clock clock_pol } endcode -match ffH +match ffFJKG if mul->type != \SB_MAC16 || (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool()) - select ffH->type.in($dff) - select nusers(port(ffH, \D)) == 2 - index port(ffH, \D) === sigH + select ffFJKG->type.in($dff) + select nusers(port(ffFJKG, \D)) == 2 + index port(ffFJKG, \D) === sigH // Ensure pipeline register is not already used optional endmatch @@ -94,16 +94,16 @@ endmatch code sigH sigO clock clock_pol sigO = sigH; - if (ffH) { - sigH = port(ffH, \Q); + if (ffFJKG) { + sigH = port(ffFJKG, \Q); for (auto b : sigH) if (b.wire->get_bool_attribute(\keep)) reject; sigO = sigH; - SigBit c = port(ffH, \CLK).as_bit(); - bool cp = param(ffH, \CLK_POLARITY).as_bool(); + SigBit c = port(ffFJKG, \CLK).as_bit(); + bool cp = param(ffFJKG, \CLK_POLARITY).as_bool(); if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; From 96ee7b9cf7a6a9010bc820dc110bf945c35cb32e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 15 Aug 2019 12:30:46 -0700 Subject: [PATCH 139/356] Simplify --- passes/pmgen/ice40_dsp.pmg | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 11064e072..b387ca0a2 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -92,16 +92,12 @@ match ffFJKG endmatch code sigH sigO clock clock_pol - sigO = sigH; - if (ffFJKG) { sigH = port(ffFJKG, \Q); for (auto b : sigH) if (b.wire->get_bool_attribute(\keep)) reject; - sigO = sigH; - SigBit c = port(ffFJKG, \CLK).as_bit(); bool cp = param(ffFJKG, \CLK_POLARITY).as_bool(); @@ -111,6 +107,8 @@ code sigH sigO clock clock_pol clock = c; clock_pol = cp; } + + sigO = sigH; endcode match addA From c320abc3f490b09b21804581c2b386c30d186a1e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 15 Aug 2019 12:34:11 -0700 Subject: [PATCH 140/356] xilinx_dsp to be sensitive to keep attribute --- passes/pmgen/xilinx_dsp.pmg | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 1a3dcdcbb..7f1958d5d 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -29,8 +29,13 @@ match ffA endmatch code clock - if (ffA) + if (ffA) { clock = port(ffA, \CLK).as_bit(); + + for (auto b : port(ffA, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + } endcode match ffB @@ -45,6 +50,10 @@ endmatch code clock if (ffB) { + for (auto b : port(ffB, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + SigBit c = port(ffB, \CLK).as_bit(); if (clock != SigBit() && c != clock) @@ -156,6 +165,10 @@ code ffP clock // ffP = ffY; if (ffP) { + for (auto b : port(ffP, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + SigBit c = port(ffP, \CLK).as_bit(); if (clock != SigBit() && c != clock) From 4cc74346f11e96b9a2bce1c984c674a22771a00a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 20 Aug 2019 20:27:05 -0700 Subject: [PATCH 141/356] Fix compile error --- passes/pmgen/ice40_dsp.cc | 4 ---- passes/pmgen/ice40_dsp.pmg | 18 ++++++++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index a1a397b83..31e11c742 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -23,10 +23,6 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -template inline bool includes(const T &lhs, const T &rhs) { - return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); -} -#include #include "passes/pmgen/ice40_dsp_pm.h" void create_ice40_dsp(ice40_dsp_pm &pm) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index cf7957ff3..24bdfd3f2 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -34,7 +34,6 @@ match ffA if mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool() if !sigAset.empty() select ffA->type.in($dff) - filter includes(port(ffA, \Q).to_sigbit_set(), sigAset) optional endmatch @@ -42,6 +41,10 @@ code sigA clock clock_pol sigA = port(mul, \A); if (ffA) { + auto ffAset = port(ffA, \Q).to_sigbit_set(); + if (!std::includes(ffAset.begin(), ffAset.end(), sigAset.begin(), sigAset.end())) + reject; + for (auto b : port(ffA, \Q)) if (b.wire->get_bool_attribute(\keep)) reject; @@ -57,7 +60,6 @@ match ffB if mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool() if !sigBset.empty() select ffB->type.in($dff) - filter includes(port(ffB, \Q).to_sigbit_set(), sigBset) optional endmatch @@ -65,6 +67,10 @@ code sigB clock clock_pol sigB = port(mul, \B); if (ffB) { + auto ffBset = port(ffB, \Q).to_sigbit_set(); + if (!std::includes(ffBset.begin(), ffBset.end(), sigBset.begin(), sigBset.end())) + reject; + for (auto b : port(ffB, \Q)) if (b.wire->get_bool_attribute(\keep)) reject; @@ -207,7 +213,9 @@ code if (ffO_lo) { SigSpec O = sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int())); O.remove_const(); - if (!includes(port(ffO_lo, \D).to_sigbit_set(), O.to_sigbit_set())) + auto ffO_loSet = port(ffO_lo, \D).to_sigbit_set(); + auto Oset = O.to_sigbit_set(); + if (!std::includes(ffO_loSet.begin(), ffO_loSet.end(), Oset.begin(), Oset.end())) reject; } endcode @@ -223,7 +231,9 @@ code if (ffO_hi) { SigSpec O = sigOused.extract_end(16); O.remove_const(); - if (!includes(port(ffO_hi, \D).to_sigbit_set(), O.to_sigbit_set())) + auto ffO_hiSet = port(ffO_hi, \D).to_sigbit_set(); + auto Oset = O.to_sigbit_set(); + if (!std::includes(ffO_hiSet.begin(), ffO_hiSet.end(), Oset.begin(), Oset.end())) reject; } endcode From 4e782f1509e74bbb69ac99fa3c443112327e4f39 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 11:02:10 -0700 Subject: [PATCH 142/356] New pmgen requires explicit accept --- passes/pmgen/xilinx_dsp.pmg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 7f1958d5d..47e6a0050 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -176,4 +176,6 @@ code ffP clock clock = c; } + + accept; endcode From 89359b6927c012f5d683dd37401d36566ad0c419 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 14:00:40 -0700 Subject: [PATCH 143/356] Missing dep for test_pmgen --- passes/pmgen/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 1c66f47c2..fa3b1ef2f 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -4,7 +4,7 @@ # -------------------------------------- OBJS += passes/pmgen/test_pmgen.o -passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h passes/pmgen/ice40_dsp_pm.h passes/pmgen/peepopt_pm.h +passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h passes/pmgen/ice40_dsp_pm.h passes/pmgen/peepopt_pm.h passes/pmgen/xilinx_srl_pm.h $(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h)) # -------------------------------------- From 7df0e77565ea9dc46d0eeca536d1be47851326e5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 14:35:05 -0700 Subject: [PATCH 144/356] Add mul_unsigned test --- tests/xilinx/mul_unsigned.v | 30 ++++++++++++++++++++++++++++++ tests/xilinx/mul_unsigned.ys | 11 +++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/xilinx/mul_unsigned.v create mode 100644 tests/xilinx/mul_unsigned.ys diff --git a/tests/xilinx/mul_unsigned.v b/tests/xilinx/mul_unsigned.v new file mode 100644 index 000000000..e3713a642 --- /dev/null +++ b/tests/xilinx/mul_unsigned.v @@ -0,0 +1,30 @@ +/* +Example from: https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_1/ug901-vivado-synthesis.pdf [p. 89]. +*/ + +// Unsigned 16x24-bit Multiplier +// 1 latency stage on operands +// 3 latency stage after the multiplication +// File: multipliers2.v +// +module mul_unsigned (clk, A, B, RES); +parameter WIDTHA = /*16*/ 6; +parameter WIDTHB = /*24*/ 9; +input clk; +input [WIDTHA-1:0] A; +input [WIDTHB-1:0] B; +output [WIDTHA+WIDTHB-1:0] RES; +reg [WIDTHA-1:0] rA; +reg [WIDTHB-1:0] rB; +reg [WIDTHA+WIDTHB-1:0] M [3:0]; +integer i; +always @(posedge clk) + begin + rA <= A; + rB <= B; + M[0] <= rA * rB; + for (i = 0; i < 3; i = i+1) + M[i+1] <= M[i]; + end +assign RES = M[3]; +endmodule diff --git a/tests/xilinx/mul_unsigned.ys b/tests/xilinx/mul_unsigned.ys new file mode 100644 index 000000000..72d1f37d7 --- /dev/null +++ b/tests/xilinx/mul_unsigned.ys @@ -0,0 +1,11 @@ +read_verilog mul_unsigned.v +proc +hierarchy -top mul_unsigned +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mul_unsigned # Constrain all select calls below inside the top module +stat +select -assert-count 1 t:BUFG +select -assert-count 1 t:DSP48E1 +select -assert-count 15 t:SRL16E +select -assert-none t:DSP48E1 t:SRL16E t:BUFG %% t:* %D From 2983a35dc058a5f5a1ab7b23cc55dd6f83667d88 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 15:00:40 -0700 Subject: [PATCH 145/356] Update comment --- passes/pmgen/ice40_dsp.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 24bdfd3f2..8221cdb69 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -89,11 +89,11 @@ code sigB clock clock_pol endcode match ffFJKG + // Ensure pipeline register is not already used if mul->type != \SB_MAC16 || (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool()) select ffFJKG->type.in($dff) select nusers(port(ffFJKG, \D)) == 2 index port(ffFJKG, \D) === sigH - // Ensure pipeline register is not already used optional endmatch From 390cf34d0a8f815ea9828f9a455b36164f9d5607 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 15:00:56 -0700 Subject: [PATCH 146/356] Add support for ffM --- passes/pmgen/xilinx_dsp.cc | 12 ++++++++++++ passes/pmgen/xilinx_dsp.pmg | 39 ++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index e7b72e312..105ad1fa1 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -39,6 +39,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("ffB: %s\n", log_id(st.ffB, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); log("addAB: %s\n", log_id(st.addAB, "--")); + log("ffM: %s\n", log_id(st.ffM, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); //log("muxP: %s\n", log_id(st.muxP, "--")); log("sigPused: %s\n", log_signal(st.sigPused)); @@ -95,6 +96,17 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) // cell->setPort("\\CEB2", st.ffB->getPort("\\EN")); else log_abort(); } + if (st.ffM) { + SigSpec D = st.ffM->getPort("\\D"); + SigSpec Q = st.ffM->getPort("\\Q"); + P.replace(pm.sigmap(D), Q); + cell->setParam("\\MREG", State::S1); + if (st.ffP->type == "$dff") + cell->setPort("\\CEM", State::S1); + //else if (st.ffP->type == "$dffe") + // cell->setPort("\\CEP", st.ffP->getPort("\\EN")); + else log_abort(); + } if (st.ffP) { SigSpec D; //if (st.muxP) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 47e6a0050..08b432b8e 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -2,7 +2,7 @@ pattern xilinx_dsp state clock state > sigAset sigBset -state sigC sigP sigPused +state sigC sigM sigMused sigP sigPused state addAB match dsp @@ -18,6 +18,12 @@ code sigAset sigBset sigBset = B.to_sigbit_set(); endcode +code sigM + sigM = port(dsp, \P); + //if (GetSize(sigH) <= 10) + // reject; +endcode + match ffA if param(dsp, \AREG).as_int() == 0 if !sigAset.empty() @@ -63,8 +69,35 @@ code clock } endcode -code sigP - sigP = port(dsp, \P); +match ffM + if param(dsp, \MREG).as_int() == 0 + select ffM->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ffM, \CLK_POLARITY).as_bool() + select nusers(port(ffM, \D)) == 2 + //index port(ffM, \D) === sigM.extract(0, GetSize(port(ffM, \D))) // TODO: Why doesn't this work!?! + filter port(ffM, \D) == sigM.extract(0, GetSize(port(ffM, \D))) + filter nusers(sigM.extract_end(param(ffM, \WIDTH).as_int())) == 1 + optional +endmatch + +code clock sigM sigP + if (ffM) { + log_warning("M FOUND!\n"); + sigM = port(ffM, \Q); + for (auto b : sigM) + if (b.wire->get_bool_attribute(\keep)) + reject; + + SigBit c = port(ffB, \CLK).as_bit(); + + if (clock != SigBit() && c != clock) + reject; + + clock = c; + } + + sigP = sigM; endcode match addA From d508dc2906f27b088e9c1c40e7cf2f475e80c15b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 15:01:08 -0700 Subject: [PATCH 147/356] Update test for ffM --- tests/xilinx/mul_unsigned.ys | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/xilinx/mul_unsigned.ys b/tests/xilinx/mul_unsigned.ys index 72d1f37d7..30c034afe 100644 --- a/tests/xilinx/mul_unsigned.ys +++ b/tests/xilinx/mul_unsigned.ys @@ -7,5 +7,5 @@ cd mul_unsigned # Constrain all select calls below inside the top module stat select -assert-count 1 t:BUFG select -assert-count 1 t:DSP48E1 -select -assert-count 15 t:SRL16E -select -assert-none t:DSP48E1 t:SRL16E t:BUFG %% t:* %D +select -assert-count 30 t:FDRE +select -assert-none t:DSP48E1 t:FDRE t:BUFG %% t:* %D From 44a35015b308adbbf5f87408d2928a36245f57e7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 15:01:38 -0700 Subject: [PATCH 148/356] Update commented out --- passes/pmgen/xilinx_dsp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 105ad1fa1..b03fff8ec 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -104,7 +104,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffP->type == "$dff") cell->setPort("\\CEM", State::S1); //else if (st.ffP->type == "$dffe") - // cell->setPort("\\CEP", st.ffP->getPort("\\EN")); + // cell->setPort("\\CEM", st.ffM->getPort("\\EN")); else log_abort(); } if (st.ffP) { From c497114e94286c06fe16a6ae32e2873578a861f4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 15:02:53 -0700 Subject: [PATCH 149/356] Another oops --- passes/pmgen/xilinx_dsp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index b03fff8ec..66fe7736b 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -101,7 +101,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) SigSpec Q = st.ffM->getPort("\\Q"); P.replace(pm.sigmap(D), Q); cell->setParam("\\MREG", State::S1); - if (st.ffP->type == "$dff") + if (st.ffM->type == "$dff") cell->setPort("\\CEM", State::S1); //else if (st.ffP->type == "$dffe") // cell->setPort("\\CEM", st.ffM->getPort("\\EN")); From 15bab02a1b1e20b25b6ac40914e82b31a3756382 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 15:03:12 -0700 Subject: [PATCH 150/356] ffM before addAB --- passes/pmgen/xilinx_dsp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 66fe7736b..50af5de1c 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -38,8 +38,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("ffA: %s\n", log_id(st.ffA, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); - log("addAB: %s\n", log_id(st.addAB, "--")); log("ffM: %s\n", log_id(st.ffM, "--")); + log("addAB: %s\n", log_id(st.addAB, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); //log("muxP: %s\n", log_id(st.muxP, "--")); log("sigPused: %s\n", log_signal(st.sigPused)); From e67f049e3b1c1ed643b86b5237b31075d0f2f212 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 15:03:43 -0700 Subject: [PATCH 151/356] Remove debug --- passes/pmgen/xilinx_dsp.pmg | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 08b432b8e..a4e1bf86d 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -83,7 +83,6 @@ endmatch code clock sigM sigP if (ffM) { - log_warning("M FOUND!\n"); sigM = port(ffM, \Q); for (auto b : sigM) if (b.wire->get_bool_attribute(\keep)) From 8f503fe3e65ba9be2ef7438b2f4143f88ea8a025 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 15:30:04 -0700 Subject: [PATCH 152/356] autoremove ffM --- passes/pmgen/xilinx_dsp.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 50af5de1c..631b93afa 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -106,6 +106,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) //else if (st.ffP->type == "$dffe") // cell->setPort("\\CEM", st.ffM->getPort("\\EN")); else log_abort(); + pm.autoremove(st.ffM); } if (st.ffP) { SigSpec D; From 9be9631e5acaa570804e1772caae55f5cfc7a918 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 16:18:14 -0700 Subject: [PATCH 153/356] Add macc test, with equiv_opt not currently passing --- tests/xilinx/macc.v | 37 +++++++++++++++++++++++++++++++++++++ tests/xilinx/macc.ys | 17 +++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 tests/xilinx/macc.v create mode 100644 tests/xilinx/macc.ys diff --git a/tests/xilinx/macc.v b/tests/xilinx/macc.v new file mode 100644 index 000000000..bae63b5a4 --- /dev/null +++ b/tests/xilinx/macc.v @@ -0,0 +1,37 @@ +// Signed 40-bit streaming accumulator with 16-bit inputs +// File: HDL_Coding_Techniques/multipliers/multipliers4.v +// +module macc # (parameter SIZEIN = /*16*/7, SIZEOUT = 40) + (input clk, ce, sload, + input signed [SIZEIN-1:0] a, b, + output signed [SIZEOUT-1:0] accum_out); + // Declare registers for intermediate values + reg signed [SIZEIN-1:0] a_reg, b_reg; + reg sload_reg; + reg signed [2*SIZEIN:0] mult_reg; + reg signed [SIZEOUT-1:0] adder_out, old_result; + always @(adder_out or sload_reg) begin + //if (sload_reg) + //old_result <= 0; + //else + // 'sload' is now active (=low) and opens the accumulation loop. + // The accumulator takes the next multiplier output in + // the same cycle. + old_result <= adder_out; + a_reg <= a; + b_reg <= b; + end + + always @(posedge clk) + //if (ce) + begin + mult_reg <= a_reg * b_reg; + sload_reg <= sload; + // Store accumulation result into a register + adder_out <= old_result + mult_reg; + end + + // Output accumulation result + assign accum_out = adder_out; + +endmodule // macc diff --git a/tests/xilinx/macc.ys b/tests/xilinx/macc.ys new file mode 100644 index 000000000..62b69f4d2 --- /dev/null +++ b/tests/xilinx/macc.ys @@ -0,0 +1,17 @@ +read_verilog macc.v +proc +hierarchy -top macc +equiv_opt -run :restore -map +/xilinx/cells_sim.v synth_xilinx # equivalency check + +#equiv_miter -trigger miter equiv +#sat -verify -prove-asserts -tempinduct -show-inputs -show-outputs miter + +#equiv_opt -assert -run :prove -map +/xilinx/cells_sim.v synth_xilinx # equivalency check +#miter -equiv -flatten -make_assert -make_outputs gold gate miter +#sat -set-init-zero -verify -prove-asserts -seq 10 -show-inputs -show-outputs miter + +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd macc # Constrain all select calls below inside the top module +select -assert-count 1 t:BUFG +select -assert-count 1 t:DSP48E1 +select -assert-none t:BUFG t:DSP48E1 %% t:* %D From a09e69dd56da677f016fceeb90a68eead8a85c2f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 16:18:58 -0700 Subject: [PATCH 154/356] Fine tune xilinx_dsp pattern matcher --- passes/pmgen/xilinx_dsp.pmg | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index a4e1bf86d..132b09b2b 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -76,8 +76,9 @@ match ffM select param(ffM, \CLK_POLARITY).as_bool() select nusers(port(ffM, \D)) == 2 //index port(ffM, \D) === sigM.extract(0, GetSize(port(ffM, \D))) // TODO: Why doesn't this work!?! + filter GetSize(port(ffM, \D)) <= GetSize(sigM) filter port(ffM, \D) == sigM.extract(0, GetSize(port(ffM, \D))) - filter nusers(sigM.extract_end(param(ffM, \WIDTH).as_int())) == 1 + filter nusers(sigM.extract_end(GetSize(port(ffM, \D)))) <= 1 optional endmatch @@ -88,7 +89,7 @@ code clock sigM sigP if (b.wire->get_bool_attribute(\keep)) reject; - SigBit c = port(ffB, \CLK).as_bit(); + SigBit c = port(ffM, \CLK).as_bit(); if (clock != SigBit() && c != clock) reject; @@ -102,10 +103,11 @@ endcode match addA select addA->type.in($add) select param(addA, \A_SIGNED).as_bool() && param(addA, \B_SIGNED).as_bool() - index nusers(port(addA, \A)) === 2 - //index port(addA, \A) === sigP.extract(0, param(addA, \A_WIDTH).as_int()) - filter param(addA, \A_WIDTH).as_int() <= GetSize(sigP) - filter port(addA, \A) == sigP.extract(0, param(addA, \A_WIDTH).as_int()) + select nusers(port(addA, \A)) == 2 + //index port(addA, \A) === sigP.extract(0, param(addA, \A_WIDTH).as_int()) // TODO: Why doesn't this work!?! + filter GetSize(port(addA, \A)) <= GetSize(sigP) + filter port(addA, \A) == sigP.extract(0, GetSize(port(addA, \A))) + filter nusers(sigP.extract_end(GetSize(port(addA, \A)))) <= 1 optional endmatch @@ -114,9 +116,10 @@ match addB select addB->type.in($add, $sub) select param(addB, \A_SIGNED).as_bool() && param(addB, \B_SIGNED).as_bool() index nusers(port(addB, \B)) === 2 - //index port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int()) - filter param(addB, \B_WIDTH).as_int() <= GetSize(sigP) - filter port(addB, \B) == sigP.extract(0, param(addB, \B_WIDTH).as_int()) + //index port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int()) // TODO: Why doesn't this work!?! + filter GetSize(port(addB, \B)) <= GetSize(sigP) + filter port(addB, \B) == sigP.extract(0, GetSize(port(addB, \B))) + filter nusers(sigP.extract_end(GetSize(port(addB, \B)))) <= 1 optional endmatch @@ -135,12 +138,13 @@ code addAB sigC sigP if (!opmodeZ.is_fully_zero()) reject; - int natural_mul_width = GetSize(port(dsp, \A)) + GetSize(port(dsp, \B)); - int actual_mul_width = GetSize(sigP); - int actual_acc_width = GetSize(sigC); + // TODO for DSP48E1, which will have sign extended inputs/outputs + //int natural_mul_width = GetSize(port(dsp, \A)) + GetSize(port(dsp, \B)); + //int actual_mul_width = GetSize(sigP); + //int actual_acc_width = GetSize(sigC); - if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) - reject; + //if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) + // reject; //if ((actual_acc_width != actual_mul_width) && (param(dsp, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) // reject; From 97d11708e0104f722578b98ea70a0ba41f9e03cc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Sep 2019 14:37:32 -0700 Subject: [PATCH 155/356] Use feedback path for MACC --- passes/pmgen/xilinx_dsp.cc | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 631b93afa..9307b3d37 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -51,21 +51,6 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) bit_to_driver.insert(std::make_pair(cell->getPort("\\P")[17], cell)); SigSpec P = st.sigP; - if (st.addAB) { - log_assert(st.addAB->getParam("\\A_SIGNED").as_bool()); - log_assert(st.addAB->getParam("\\B_SIGNED").as_bool()); - log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); - - SigSpec C = st.sigC; - C.extend_u0(48, true); - cell->setPort("\\C", C); - SigSpec &opmode = cell->connections_.at("\\OPMODE"); - opmode[6] = State::S0; - opmode[5] = State::S1; - opmode[4] = State::S1; - pm.autoremove(st.addAB); - } - if (st.clock != SigBit()) { cell->setPort("\\CLK", st.clock); @@ -140,6 +125,27 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("\n"); } + if (st.addAB) { + log_assert(st.addAB->getParam("\\A_SIGNED").as_bool()); + log_assert(st.addAB->getParam("\\B_SIGNED").as_bool()); + log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + + SigSpec C = st.sigC; + SigSpec &opmode = cell->connections_.at("\\OPMODE"); + if (cell->getParam("\\PREG").as_bool() && C == P) { + opmode[4] = State::S0; + } + else { + C.extend_u0(48, true); + cell->setPort("\\C", C); + opmode[4] = State::S1; + } + opmode[6] = State::S0; + opmode[5] = State::S1; + + pm.autoremove(st.addAB); + } + if (GetSize(P) < 48) P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); cell->setPort("\\P", P); From 682153de4bb1869187e567a41c22fbed23bcdfd1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Sep 2019 14:57:59 -0700 Subject: [PATCH 156/356] Process post-adder first since C could be used for load-P --- passes/pmgen/xilinx_dsp.cc | 40 +++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 9307b3d37..1732a2d6a 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -49,8 +49,27 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) Cell *cell = st.dsp; bit_to_driver.insert(std::make_pair(cell->getPort("\\P")[17], cell)); + SigSpec C = st.sigC; SigSpec P = st.sigP; + if (st.addAB) { + log_assert(st.addAB->getParam("\\A_SIGNED").as_bool()); + log_assert(st.addAB->getParam("\\B_SIGNED").as_bool()); + log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + + SigSpec &opmode = cell->connections_.at("\\OPMODE"); + if (st.ffP && C == P) { + C = SigSpec(); + opmode[4] = State::S0; + } + else + opmode[4] = State::S1; + opmode[6] = State::S0; + opmode[5] = State::S1; + + pm.autoremove(st.addAB); + } + if (st.clock != SigBit()) { cell->setPort("\\CLK", st.clock); @@ -125,25 +144,10 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("\n"); } - if (st.addAB) { - log_assert(st.addAB->getParam("\\A_SIGNED").as_bool()); - log_assert(st.addAB->getParam("\\B_SIGNED").as_bool()); - log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); - - SigSpec C = st.sigC; - SigSpec &opmode = cell->connections_.at("\\OPMODE"); - if (cell->getParam("\\PREG").as_bool() && C == P) { - opmode[4] = State::S0; - } - else { + if (!C.empty()) { + if (GetSize(C) < 48) C.extend_u0(48, true); - cell->setPort("\\C", C); - opmode[4] = State::S1; - } - opmode[6] = State::S0; - opmode[5] = State::S1; - - pm.autoremove(st.addAB); + cell->setPort("\\C", C); } if (GetSize(P) < 48) From 2d80866dafe9e2e2edd2d49e999c1f6a35541852 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Sep 2019 15:53:10 -0700 Subject: [PATCH 157/356] Add support for load value into DSP48E1.P --- passes/pmgen/xilinx_dsp.cc | 7 +++- passes/pmgen/xilinx_dsp.pmg | 72 +++++++++++++++++++++---------------- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 1732a2d6a..b3d302071 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -40,6 +40,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("dsp: %s\n", log_id(st.dsp, "--")); log("ffM: %s\n", log_id(st.ffM, "--")); log("addAB: %s\n", log_id(st.addAB, "--")); + log("muxAB: %s\n", log_id(st.muxAB, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); //log("muxP: %s\n", log_id(st.muxP, "--")); log("sigPused: %s\n", log_signal(st.sigPused)); @@ -58,7 +59,11 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); SigSpec &opmode = cell->connections_.at("\\OPMODE"); - if (st.ffP && C == P) { + if (st.ffP && st.muxAB) { + opmode[4] = st.muxAB->getPort("\\S"); + pm.autoremove(st.muxAB); + } + else if (st.ffP && C == P) { C = SigSpec(); opmode[4] = State::S0; } diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 132b09b2b..fdc3fa5e7 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -3,7 +3,7 @@ pattern xilinx_dsp state clock state > sigAset sigBset state sigC sigM sigMused sigP sigPused -state addAB +state addAB muxAB match dsp select dsp->type.in(\DSP48E1) @@ -172,34 +172,7 @@ match ffP optional endmatch -//// $mux cell left behind by dff2dffe -//// would prefer not to run 'opt_expr -mux_undef' -//// since that would lose information helpful for -//// efficient wide-mux inference -//match muxP -// if !sigPused.empty() && !ffP -// select muxP->type.in($mux) -// select nusers(port(muxP, \B)) == 2 -// select port(muxP, \A).is_fully_undef() -// filter param(muxP, \WIDTH).as_int() >= GetSize(sigPused) -// filter includes(port(muxP, \B).to_sigbit_set(), sigPused.to_sigbit_set()) -// optional -//endmatch -// -//match ffY -// if muxP -// select ffY->type.in($dff, $dffe) -// select nusers(port(ffY, \D)) == 2 -// // DSP48E1 does not support clock inversion -// select param(ffY, \CLK_POLARITY).as_bool() -// filter param(ffY, \WIDTH).as_int() >= GetSize(sigPused) -// filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set()) -//endmatch - -code ffP clock -// if (ffY) -// ffP = ffY; - +code ffP sigP clock if (ffP) { for (auto b : port(ffP, \Q)) if (b.wire->get_bool_attribute(\keep)) @@ -211,7 +184,46 @@ code ffP clock reject; clock = c; - } + sigP = port(ffP, \Q); + } +endcode + +match muxA + if addAB + select muxA->type.in($mux) + select nusers(port(muxA, \Y)) == 2 + index port(muxA, \A) === sigP + index port(muxA, \Y) === sigC + optional +endmatch + +match muxB + if addAB + select muxB->type.in($mux) + select nusers(port(muxB, \Y)) == 2 + index port(muxB, \B) === sigP + index port(muxB, \Y) === sigC + optional +endmatch + +code sigC muxAB + if (muxA) { + muxAB = muxA; + sigC = port(muxAB, \B); + } + if (muxB) { + muxAB = muxB; + sigC = port(muxAB, \A); + } + if (muxAB) { + // Ensure that adder is not used + SigSpec opmodeZ = port(dsp, \OPMODE).extract(4,3); + if (!opmodeZ.is_fully_zero()) + reject; + } +endcode + +code accept; endcode From cd002ad3fb20bb98027f29e0c1005bf1df7c432c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Sep 2019 16:10:16 -0700 Subject: [PATCH 158/356] Use choices for addAB, now called postAdd --- passes/pmgen/xilinx_dsp.cc | 12 +++---- passes/pmgen/xilinx_dsp.pmg | 63 ++++++++++++++----------------------- 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index b3d302071..7f51d29f6 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -39,7 +39,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("ffB: %s\n", log_id(st.ffB, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); log("ffM: %s\n", log_id(st.ffM, "--")); - log("addAB: %s\n", log_id(st.addAB, "--")); + log("postAdd: %s\n", log_id(st.postAdd, "--")); log("muxAB: %s\n", log_id(st.muxAB, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); //log("muxP: %s\n", log_id(st.muxP, "--")); @@ -53,10 +53,10 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) SigSpec C = st.sigC; SigSpec P = st.sigP; - if (st.addAB) { - log_assert(st.addAB->getParam("\\A_SIGNED").as_bool()); - log_assert(st.addAB->getParam("\\B_SIGNED").as_bool()); - log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + if (st.postAdd) { + log_assert(st.postAdd->getParam("\\A_SIGNED").as_bool()); + log_assert(st.postAdd->getParam("\\B_SIGNED").as_bool()); + log(" adder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); SigSpec &opmode = cell->connections_.at("\\OPMODE"); if (st.ffP && st.muxAB) { @@ -72,7 +72,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) opmode[6] = State::S0; opmode[5] = State::S1; - pm.autoremove(st.addAB); + pm.autoremove(st.postAdd); } if (st.clock != SigBit()) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index fdc3fa5e7..0aafc9e40 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -3,7 +3,8 @@ pattern xilinx_dsp state clock state > sigAset sigBset state sigC sigM sigMused sigP sigPused -state addAB muxAB +state postAdd muxAB +state postAddAB match dsp select dsp->type.in(\DSP48E1) @@ -100,43 +101,25 @@ code clock sigM sigP sigP = sigM; endcode -match addA - select addA->type.in($add) - select param(addA, \A_SIGNED).as_bool() && param(addA, \B_SIGNED).as_bool() - select nusers(port(addA, \A)) == 2 - //index port(addA, \A) === sigP.extract(0, param(addA, \A_WIDTH).as_int()) // TODO: Why doesn't this work!?! - filter GetSize(port(addA, \A)) <= GetSize(sigP) - filter port(addA, \A) == sigP.extract(0, GetSize(port(addA, \A))) - filter nusers(sigP.extract_end(GetSize(port(addA, \A)))) <= 1 +match postAdd + // Ensure that Z mux is not already used + if port(dsp, \OPMODE).extract(4,3).is_fully_zero() + + select postAdd->type.in($postAdd) + select param(postAdd, \A_SIGNED).as_bool() && param(postAdd, \B_SIGNED).as_bool() + choice AB {\A, \B} + define AB_WIDTH (AB == \A ? \A_WIDTH : \B_WIDTH) + select nusers(port(postAdd, AB)) == 2 + filter GetSize(port(postAdd, AB)) <= GetSize(sigP) + filter port(postAdd, AB) == sigP.extract(0, GetSize(port(postAdd, AB))) + filter nusers(sigP.extract_end(GetSize(port(postAdd, AB)))) <= 1 + set postAddAB AB optional endmatch -match addB - if !addA - select addB->type.in($add, $sub) - select param(addB, \A_SIGNED).as_bool() && param(addB, \B_SIGNED).as_bool() - index nusers(port(addB, \B)) === 2 - //index port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int()) // TODO: Why doesn't this work!?! - filter GetSize(port(addB, \B)) <= GetSize(sigP) - filter port(addB, \B) == sigP.extract(0, GetSize(port(addB, \B))) - filter nusers(sigP.extract_end(GetSize(port(addB, \B)))) <= 1 - optional -endmatch - -code addAB sigC sigP - if (addA) { - addAB = addA; - sigC = port(addAB, \B); - } - if (addB) { - addAB = addB; - sigC = port(addAB, \A); - } - if (addAB) { - // Ensure that adder is not used - SigSpec opmodeZ = port(dsp, \OPMODE).extract(4,3); - if (!opmodeZ.is_fully_zero()) - reject; +code sigC sigP + if (postAdd) { + sigC = port(postAdd, postAddAB == \A ? \B : \A); // TODO for DSP48E1, which will have sign extended inputs/outputs //int natural_mul_width = GetSize(port(dsp, \A)) + GetSize(port(dsp, \B)); @@ -145,10 +128,10 @@ code addAB sigC sigP //if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) // reject; - //if ((actual_acc_width != actual_mul_width) && (param(dsp, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) + //if ((actual_acc_width != actual_mul_width) && (param(dsp, \A_SIGNED).as_bool() != param(postAdd, \A_SIGNED).as_bool())) // reject; - sigP = port(addAB, \Y); + sigP = port(postAdd, \Y); } endcode @@ -190,7 +173,7 @@ code ffP sigP clock endcode match muxA - if addAB + if postAdd select muxA->type.in($mux) select nusers(port(muxA, \Y)) == 2 index port(muxA, \A) === sigP @@ -199,7 +182,7 @@ match muxA endmatch match muxB - if addAB + if postAdd select muxB->type.in($mux) select nusers(port(muxB, \Y)) == 2 index port(muxB, \B) === sigP @@ -217,7 +200,7 @@ code sigC muxAB sigC = port(muxAB, \A); } if (muxAB) { - // Ensure that adder is not used + // Ensure that postAdder is not used SigSpec opmodeZ = port(dsp, \OPMODE).extract(4,3); if (!opmodeZ.is_fully_zero()) reject; From 16316aa05d548c79fa1580defe71097efdeb78b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Sep 2019 16:24:59 -0700 Subject: [PATCH 159/356] Rename muxAB to postAddMux --- passes/pmgen/xilinx_dsp.cc | 22 ++++++++--------- passes/pmgen/xilinx_dsp.pmg | 47 +++++++++++-------------------------- 2 files changed, 25 insertions(+), 44 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 7f51d29f6..17e05c39c 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -35,15 +35,15 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) #if 1 log("\n"); - log("ffA: %s\n", log_id(st.ffA, "--")); - log("ffB: %s\n", log_id(st.ffB, "--")); - log("dsp: %s\n", log_id(st.dsp, "--")); - log("ffM: %s\n", log_id(st.ffM, "--")); - log("postAdd: %s\n", log_id(st.postAdd, "--")); - log("muxAB: %s\n", log_id(st.muxAB, "--")); - log("ffP: %s\n", log_id(st.ffP, "--")); + log("ffA: %s\n", log_id(st.ffA, "--")); + log("ffB: %s\n", log_id(st.ffB, "--")); + log("dsp: %s\n", log_id(st.dsp, "--")); + log("ffM: %s\n", log_id(st.ffM, "--")); + log("postAdd: %s\n", log_id(st.postAdd, "--")); + log("postAddMux: %s\n", log_id(st.postAddMux, "--")); + log("ffP: %s\n", log_id(st.ffP, "--")); //log("muxP: %s\n", log_id(st.muxP, "--")); - log("sigPused: %s\n", log_signal(st.sigPused)); + log("sigPused: %s\n", log_signal(st.sigPused)); #endif log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); @@ -59,9 +59,9 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log(" adder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); SigSpec &opmode = cell->connections_.at("\\OPMODE"); - if (st.ffP && st.muxAB) { - opmode[4] = st.muxAB->getPort("\\S"); - pm.autoremove(st.muxAB); + if (st.ffP && st.postAddMux) { + opmode[4] = st.postAddMux->getPort("\\S"); + pm.autoremove(st.postAddMux); } else if (st.ffP && C == P) { C = SigSpec(); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 0aafc9e40..8c8f431a4 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -3,8 +3,8 @@ pattern xilinx_dsp state clock state > sigAset sigBset state sigC sigM sigMused sigP sigPused -state postAdd muxAB -state postAddAB +state postAdd postAddMux +state postAddAB postAddMuxAB match dsp select dsp->type.in(\DSP48E1) @@ -105,10 +105,9 @@ match postAdd // Ensure that Z mux is not already used if port(dsp, \OPMODE).extract(4,3).is_fully_zero() - select postAdd->type.in($postAdd) + select postAdd->type.in($add) select param(postAdd, \A_SIGNED).as_bool() && param(postAdd, \B_SIGNED).as_bool() choice AB {\A, \B} - define AB_WIDTH (AB == \A ? \A_WIDTH : \B_WIDTH) select nusers(port(postAdd, AB)) == 2 filter GetSize(port(postAdd, AB)) <= GetSize(sigP) filter port(postAdd, AB) == sigP.extract(0, GetSize(port(postAdd, AB))) @@ -172,39 +171,21 @@ code ffP sigP clock } endcode -match muxA +match postAddMux if postAdd - select muxA->type.in($mux) - select nusers(port(muxA, \Y)) == 2 - index port(muxA, \A) === sigP - index port(muxA, \Y) === sigC + if ffP + select postAddMux->type.in($mux) + select nusers(port(postAddMux, \Y)) == 2 + choice AB {\A, \B} + index port(postAddMux, AB) === sigP + index port(postAddMux, \Y) === sigC + set postAddMuxAB AB optional endmatch -match muxB - if postAdd - select muxB->type.in($mux) - select nusers(port(muxB, \Y)) == 2 - index port(muxB, \B) === sigP - index port(muxB, \Y) === sigC - optional -endmatch - -code sigC muxAB - if (muxA) { - muxAB = muxA; - sigC = port(muxAB, \B); - } - if (muxB) { - muxAB = muxB; - sigC = port(muxAB, \A); - } - if (muxAB) { - // Ensure that postAdder is not used - SigSpec opmodeZ = port(dsp, \OPMODE).extract(4,3); - if (!opmodeZ.is_fully_zero()) - reject; - } +code sigC + if (postAddMux) + sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A); endcode code From 80aec0f006b91b0163c8be94f2450223e6e97a52 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 3 Sep 2019 16:37:59 -0700 Subject: [PATCH 160/356] st.ffP from if to assert --- passes/pmgen/xilinx_dsp.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 17e05c39c..95105275b 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -59,7 +59,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log(" adder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); SigSpec &opmode = cell->connections_.at("\\OPMODE"); - if (st.ffP && st.postAddMux) { + if (st.postAddMux) { + log_assert(st.ffP); opmode[4] = st.postAddMux->getPort("\\S"); pm.autoremove(st.postAddMux); } From e67e4a5ed66df59f5f924e6bb3891f87fc93f070 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Sep 2019 10:52:51 -0700 Subject: [PATCH 161/356] Support CEM --- passes/pmgen/xilinx_dsp.cc | 10 ++++++---- passes/pmgen/xilinx_dsp.pmg | 32 +++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 95105275b..4d2152f61 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -39,6 +39,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("ffB: %s\n", log_id(st.ffB, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); log("ffM: %s\n", log_id(st.ffM, "--")); + log("ffMmux: %s\n", log_id(st.ffMmux, "--")); log("postAdd: %s\n", log_id(st.postAdd, "--")); log("postAddMux: %s\n", log_id(st.postAddMux, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); @@ -111,11 +112,12 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) SigSpec Q = st.ffM->getPort("\\Q"); P.replace(pm.sigmap(D), Q); cell->setParam("\\MREG", State::S1); - if (st.ffM->type == "$dff") + if (st.ffMmux) { + cell->setPort("\\CEM", st.ffMmux->getPort("\\S")); + pm.autoremove(st.ffMmux); + } + else cell->setPort("\\CEM", State::S1); - //else if (st.ffP->type == "$dffe") - // cell->setPort("\\CEM", st.ffM->getPort("\\EN")); - else log_abort(); pm.autoremove(st.ffM); } if (st.ffP) { diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 8c8f431a4..9b01c22ee 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -2,9 +2,8 @@ pattern xilinx_dsp state clock state > sigAset sigBset -state sigC sigM sigMused sigP sigPused -state postAdd postAddMux -state postAddAB postAddMuxAB +state sigC sigM sigP sigPused +state ffMmuxAB postAddAB postAddMuxAB match dsp select dsp->type.in(\DSP48E1) @@ -70,22 +69,40 @@ code clock } endcode +match ffMmux + select ffMmux->type.in($mux) + select nusers(port(ffMmux, \Y)) == 2 + filter GetSize(port(ffMmux, \Y)) <= GetSize(sigM) + choice AB {\A, \B} + filter port(ffMmux, AB) == sigM.extract(0, GetSize(port(ffMmux, \Y))) + filter nusers(sigM.extract_end(GetSize(port(ffMmux, AB)))) <= 1 + set ffMmuxAB AB + optional +endmatch + +code sigM + if (ffMmux) + sigM = port(ffMmux, \Y); +endcode + match ffM if param(dsp, \MREG).as_int() == 0 select ffM->type.in($dff) // DSP48E1 does not support clock inversion select param(ffM, \CLK_POLARITY).as_bool() select nusers(port(ffM, \D)) == 2 - //index port(ffM, \D) === sigM.extract(0, GetSize(port(ffM, \D))) // TODO: Why doesn't this work!?! filter GetSize(port(ffM, \D)) <= GetSize(sigM) filter port(ffM, \D) == sigM.extract(0, GetSize(port(ffM, \D))) filter nusers(sigM.extract_end(GetSize(port(ffM, \D)))) <= 1 + // Check ffMmux (when present) is a $dff enable mux + filter !ffMmux || port(ffM, \Q) == port(ffMmux, ffMmuxAB == \A ? \B : \A) optional endmatch code clock sigM sigP if (ffM) { sigM = port(ffM, \Q); + for (auto b : sigM) if (b.wire->get_bool_attribute(\keep)) reject; @@ -97,6 +114,9 @@ code clock sigM sigP clock = c; } + // Cannot have ffMmux enable mux without ffM + else if (ffMmux) + reject; sigP = sigM; endcode @@ -108,7 +128,9 @@ match postAdd select postAdd->type.in($add) select param(postAdd, \A_SIGNED).as_bool() && param(postAdd, \B_SIGNED).as_bool() choice AB {\A, \B} - select nusers(port(postAdd, AB)) == 2 + select nusers(port(postAdd, AB)) <= 3 + filter ffMmux || nusers(port(postAdd, AB)) == 2 + filter !ffMmux || nusers(port(postAdd, AB)) == 3 filter GetSize(port(postAdd, AB)) <= GetSize(sigP) filter port(postAdd, AB) == sigP.extract(0, GetSize(port(postAdd, AB))) filter nusers(sigP.extract_end(GetSize(port(postAdd, AB)))) <= 1 From 93d798272d027f15aa930766bc3f9553f448f5cf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Sep 2019 16:59:57 -0700 Subject: [PATCH 162/356] Compute sigP properly --- passes/pmgen/xilinx_dsp.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 9b01c22ee..c45e92d6f 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -189,7 +189,7 @@ code ffP sigP clock clock = c; - sigP = port(ffP, \Q); + sigP.replace(port(ffP, \D), port(ffP, \Q)); } endcode From 42548d979018c4bc3b71d4faa0900b18d2d290ec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Sep 2019 17:06:17 -0700 Subject: [PATCH 163/356] Get rid of sigPused --- passes/pmgen/xilinx_dsp.cc | 2 -- passes/pmgen/xilinx_dsp.pmg | 27 +++++++++++++-------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 4d2152f61..0d1937844 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -43,8 +43,6 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("postAdd: %s\n", log_id(st.postAdd, "--")); log("postAddMux: %s\n", log_id(st.postAddMux, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); - //log("muxP: %s\n", log_id(st.muxP, "--")); - log("sigPused: %s\n", log_signal(st.sigPused)); #endif log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index c45e92d6f..375b5a492 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -19,8 +19,16 @@ code sigAset sigBset endcode code sigM - sigM = port(dsp, \P); - //if (GetSize(sigH) <= 10) + SigSpec P = port(dsp, \P); + // Only care about those bits that are used + int i; + for (i = 0; i < GetSize(P); i++) { + if (nusers(P[i]) <= 1) + break; + sigM.append(P[i]); + } + log_assert(nusers(P.extract_end(i)) <= 1); + //if (GetSize(sigM) <= 10) // reject; endcode @@ -156,23 +164,14 @@ code sigC sigP } endcode -// Extract the bits of P that actually have a consumer -// (as opposed to being a dummy) -code sigPused - for (int i = 0; i < GetSize(sigP); i++) - if (sigP[i].wire && nusers(sigP[i]) > 1) - sigPused.append(sigP[i]); -endcode - match ffP if param(dsp, \PREG).as_int() == 0 - if !sigPused.empty() - if nusers(sigPused) == 2 select ffP->type.in($dff) // DSP48E1 does not support clock inversion select param(ffP, \CLK_POLARITY).as_bool() - filter param(ffP, \WIDTH).as_int() >= GetSize(sigPused) - filter includes(port(ffP, \D).to_sigbit_set(), sigPused.to_sigbit_set()) + filter GetSize(port(ffP, \D)) >= GetSize(sigP) + slice offset GetSize(port(ffP, \D)) + filter offset+GetSize(sigP) <= GetSize(port(ffP, \D)) && port(ffP, \D).extract(offset, GetSize(sigP)) == sigP optional endmatch From 91ef4457b08e15da6b8af9522da002b76feefd06 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Sep 2019 17:18:49 -0700 Subject: [PATCH 164/356] Get rid of sigAset --- passes/pmgen/xilinx_dsp.pmg | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 375b5a492..598276063 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,18 +1,21 @@ pattern xilinx_dsp state clock -state > sigAset sigBset -state sigC sigM sigP sigPused +state > sigBset +state sigA sigC sigM sigP sigPused state ffMmuxAB postAddAB postAddMuxAB match dsp select dsp->type.in(\DSP48E1) endmatch -code sigAset sigBset - SigSpec A = port(dsp, \A); - A.remove_const(); - sigAset = A.to_sigbit_set(); +code sigA sigBset + sigA = port(dsp, \A); + int i; + for (i = GetSize(sigA)-1; i > 0; i--) + if (sigA[i] != sigA[i-1]) + break; + sigA.remove(i, GetSize(sigA)-i); SigSpec B = port(dsp, \B); B.remove_const(); sigBset = B.to_sigbit_set(); @@ -34,21 +37,22 @@ endcode match ffA if param(dsp, \AREG).as_int() == 0 - if !sigAset.empty() select ffA->type.in($dff) // DSP48E1 does not support clock inversion select param(ffA, \CLK_POLARITY).as_bool() - filter includes(port(ffA, \Q).to_sigbit_set(), sigAset) + filter GetSize(port(ffA, \Q)) >= GetSize(sigA) + slice offset GetSize(port(ffA, \Q)) + filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) && port(ffA, \Q).extract(offset, GetSize(sigA)) == sigA optional endmatch code clock if (ffA) { - clock = port(ffA, \CLK).as_bit(); - for (auto b : port(ffA, \Q)) if (b.wire->get_bool_attribute(\keep)) reject; + + clock = port(ffA, \CLK).as_bit(); } endcode From 09c26c55bb4357f0b7204d8a78806aa7ad12068f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Sep 2019 17:22:02 -0700 Subject: [PATCH 165/356] Get rid of sigBset too --- passes/pmgen/xilinx_dsp.cc | 4 ---- passes/pmgen/xilinx_dsp.pmg | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 0d1937844..c742ef84d 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -23,10 +23,6 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -template inline bool includes(const T &lhs, const T &rhs) { - return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); -} -#include #include "passes/pmgen/xilinx_dsp_pm.h" void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 598276063..d37792b29 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,24 +1,25 @@ pattern xilinx_dsp state clock -state > sigBset -state sigA sigC sigM sigP sigPused +state sigA sigB sigC sigM sigP sigPused state ffMmuxAB postAddAB postAddMuxAB match dsp select dsp->type.in(\DSP48E1) endmatch -code sigA sigBset +code sigA sigB sigA = port(dsp, \A); int i; for (i = GetSize(sigA)-1; i > 0; i--) if (sigA[i] != sigA[i-1]) break; sigA.remove(i, GetSize(sigA)-i); - SigSpec B = port(dsp, \B); - B.remove_const(); - sigBset = B.to_sigbit_set(); + sigB = port(dsp, \B); + for (i = GetSize(sigB)-1; i > 0; i--) + if (sigB[i] != sigB[i-1]) + break; + sigB.remove(i, GetSize(sigB)-i); endcode code sigM @@ -58,11 +59,12 @@ endcode match ffB if param(dsp, \BREG).as_int() == 0 - if !sigBset.empty() select ffB->type.in($dff) // DSP48E1 does not support clock inversion select param(ffB, \CLK_POLARITY).as_bool() - filter includes(port(ffB, \Q).to_sigbit_set(), sigBset) + filter GetSize(port(ffB, \Q)) >= GetSize(sigB) + slice offset GetSize(port(ffB, \Q)) + filter offset+GetSize(sigB) <= GetSize(port(ffB, \Q)) && port(ffB, \Q).extract(offset, GetSize(sigB)) == sigB optional endmatch From aa462da39513505a66840dca49a5f4499531d952 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 10:07:26 -0700 Subject: [PATCH 166/356] Support CEA --- passes/pmgen/xilinx_dsp.cc | 17 +++++++++++------ passes/pmgen/xilinx_dsp.pmg | 26 +++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index c742ef84d..2f36a5bde 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -32,6 +32,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) #if 1 log("\n"); log("ffA: %s\n", log_id(st.ffA, "--")); + log("ffAmux: %s\n", log_id(st.ffAmux, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); log("ffM: %s\n", log_id(st.ffM, "--")); @@ -78,15 +79,19 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffA) { SigSpec A = cell->getPort("\\A"); SigSpec D = st.ffA->getPort("\\D"); - SigSpec Q = st.ffA->getPort("\\Q"); + SigSpec Q = pm.sigmap(st.ffA->getPort("\\Q")); A.replace(Q, D); - cell->setPort("\\A", A); + cell->setParam("\\AREG", 1); - if (st.ffA->type == "$dff") + if (st.ffAmux) { + SigSpec Y = st.ffAmux->getPort("\\Y"); + SigSpec AB = st.ffAmux->getPort(st.ffAmuxAB == "\\A" ? "\\B" : "\\A"); + A.replace(Y, AB); + cell->setPort("\\CEA2", st.ffAmux->getPort("\\S")); + } + else cell->setPort("\\CEA2", State::S1); - //else if (st.ffA->type == "$dffe") - // cell->setPort("\\CEA2", st.ffA->getPort("\\EN")); - else log_abort(); + cell->setPort("\\A", A); } if (st.ffB) { SigSpec B = cell->getPort("\\B"); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index d37792b29..339ac646c 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,8 +1,8 @@ pattern xilinx_dsp state clock -state sigA sigB sigC sigM sigP sigPused -state ffMmuxAB postAddAB postAddMuxAB +state sigA sigffAmux sigB sigC sigM sigP sigPused +state ffAmuxAB ffMmuxAB postAddAB postAddMuxAB match dsp select dsp->type.in(\DSP48E1) @@ -14,11 +14,17 @@ code sigA sigB for (i = GetSize(sigA)-1; i > 0; i--) if (sigA[i] != sigA[i-1]) break; + // Do not remove non-const sign bit + if (sigA[i].wire) + ++i; sigA.remove(i, GetSize(sigA)-i); sigB = port(dsp, \B); for (i = GetSize(sigB)-1; i > 0; i--) if (sigB[i] != sigB[i-1]) break; + // Do not remove non-const sign bit + if (sigB[i].wire) + ++i; sigB.remove(i, GetSize(sigB)-i); endcode @@ -43,20 +49,34 @@ match ffA select param(ffA, \CLK_POLARITY).as_bool() filter GetSize(port(ffA, \Q)) >= GetSize(sigA) slice offset GetSize(port(ffA, \Q)) + filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) && nusers(port(ffA, \Q).extract(offset, GetSize(sigA))) <= 3 filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) && port(ffA, \Q).extract(offset, GetSize(sigA)) == sigA optional endmatch -code clock +code sigA sigffAmux clock if (ffA) { for (auto b : port(ffA, \Q)) if (b.wire->get_bool_attribute(\keep)) reject; clock = port(ffA, \CLK).as_bit(); + + if (nusers(sigA) == 3) + sigffAmux = sigA; + sigA.replace(port(ffA, \Q), port(ffA, \D)); } endcode +match ffAmux + if sigffAmux != SigSpec() + select ffAmux->type.in($mux) + choice AB {\A, \B} + index port(ffAmux, \Y) === sigA + index port(ffAmux, AB) === sigffAmux + set ffAmuxAB AB +endmatch + match ffB if param(dsp, \BREG).as_int() == 0 select ffB->type.in($dff) From 0166e02e781080f346b37dcb3ba6f9fa947ca22d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 10:07:56 -0700 Subject: [PATCH 167/356] Cleanup --- passes/pmgen/xilinx_dsp.pmg | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 339ac646c..ed5bd3aae 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,14 +1,14 @@ pattern xilinx_dsp state clock -state sigA sigffAmux sigB sigC sigM sigP sigPused +state sigA sigffAmux sigB sigC sigM sigP state ffAmuxAB ffMmuxAB postAddAB postAddMuxAB match dsp select dsp->type.in(\DSP48E1) endmatch -code sigA sigB +code sigA sigffAmux sigB sigM sigA = port(dsp, \A); int i; for (i = GetSize(sigA)-1; i > 0; i--) @@ -26,12 +26,9 @@ code sigA sigB if (sigB[i].wire) ++i; sigB.remove(i, GetSize(sigB)-i); -endcode -code sigM SigSpec P = port(dsp, \P); // Only care about those bits that are used - int i; for (i = 0; i < GetSize(P); i++) { if (nusers(P[i]) <= 1) break; From 05282afc2503d1dba1da561c7fbf86ac6cf97466 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 10:46:33 -0700 Subject: [PATCH 168/356] Add support for CEB, remove check on nusers --- passes/pmgen/xilinx_dsp.cc | 21 +++++++++++++-------- passes/pmgen/xilinx_dsp.pmg | 28 ++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 2f36a5bde..5ae34a1f7 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -34,6 +34,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("ffA: %s\n", log_id(st.ffA, "--")); log("ffAmux: %s\n", log_id(st.ffAmux, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); + log("ffBmux: %s\n", log_id(st.ffBmux, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); log("ffM: %s\n", log_id(st.ffM, "--")); log("ffMmux: %s\n", log_id(st.ffMmux, "--")); @@ -81,8 +82,6 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) SigSpec D = st.ffA->getPort("\\D"); SigSpec Q = pm.sigmap(st.ffA->getPort("\\Q")); A.replace(Q, D); - - cell->setParam("\\AREG", 1); if (st.ffAmux) { SigSpec Y = st.ffAmux->getPort("\\Y"); SigSpec AB = st.ffAmux->getPort(st.ffAmuxAB == "\\A" ? "\\B" : "\\A"); @@ -92,19 +91,25 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) else cell->setPort("\\CEA2", State::S1); cell->setPort("\\A", A); + + cell->setParam("\\AREG", 1); } if (st.ffB) { SigSpec B = cell->getPort("\\B"); SigSpec D = st.ffB->getPort("\\D"); SigSpec Q = st.ffB->getPort("\\Q"); B.replace(Q, D); - cell->setPort("\\B", B); - cell->setParam("\\BREG", 1); - if (st.ffB->type == "$dff") + if (st.ffBmux) { + SigSpec Y = st.ffBmux->getPort("\\Y"); + SigSpec AB = st.ffBmux->getPort(st.ffBmuxAB == "\\A" ? "\\B" : "\\A"); + B.replace(Y, AB); + cell->setPort("\\CEB2", st.ffBmux->getPort("\\S")); + } + else cell->setPort("\\CEB2", State::S1); - //else if (st.ffB->type == "$dffe") - // cell->setPort("\\CEB2", st.ffB->getPort("\\EN")); - else log_abort(); + cell->setPort("\\B", B); + + cell->setParam("\\BREG", 1); } if (st.ffM) { SigSpec D = st.ffM->getPort("\\D"); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index ed5bd3aae..2681cdbca 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,14 +1,14 @@ pattern xilinx_dsp state clock -state sigA sigffAmux sigB sigC sigM sigP -state ffAmuxAB ffMmuxAB postAddAB postAddMuxAB +state sigA sigffAmux sigB sigffBmux sigC sigM sigP +state ffAmuxAB ffBmuxAB ffMmuxAB postAddAB postAddMuxAB match dsp select dsp->type.in(\DSP48E1) endmatch -code sigA sigffAmux sigB sigM +code sigA sigffAmux sigB sigffBmux sigM sigA = port(dsp, \A); int i; for (i = GetSize(sigA)-1; i > 0; i--) @@ -46,7 +46,6 @@ match ffA select param(ffA, \CLK_POLARITY).as_bool() filter GetSize(port(ffA, \Q)) >= GetSize(sigA) slice offset GetSize(port(ffA, \Q)) - filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) && nusers(port(ffA, \Q).extract(offset, GetSize(sigA))) <= 3 filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) && port(ffA, \Q).extract(offset, GetSize(sigA)) == sigA optional endmatch @@ -59,19 +58,19 @@ code sigA sigffAmux clock clock = port(ffA, \CLK).as_bit(); - if (nusers(sigA) == 3) - sigffAmux = sigA; + sigffAmux = sigA; sigA.replace(port(ffA, \Q), port(ffA, \D)); } endcode match ffAmux - if sigffAmux != SigSpec() + if ffA select ffAmux->type.in($mux) choice AB {\A, \B} index port(ffAmux, \Y) === sigA index port(ffAmux, AB) === sigffAmux set ffAmuxAB AB + semioptional endmatch match ffB @@ -85,7 +84,7 @@ match ffB optional endmatch -code clock +code sigB sigffBmux clock if (ffB) { for (auto b : port(ffB, \Q)) if (b.wire->get_bool_attribute(\keep)) @@ -97,9 +96,22 @@ code clock reject; clock = c; + + sigffBmux = sigB; + sigB.replace(port(ffB, \Q), port(ffB, \D)); } endcode +match ffBmux + if ffB + select ffBmux->type.in($mux) + choice AB {\A, \B} + index port(ffBmux, \Y) === sigB + index port(ffBmux, AB) === sigffBmux + set ffBmuxAB AB + semioptional +endmatch + match ffMmux select ffMmux->type.in($mux) select nusers(port(ffMmux, \Y)) == 2 From 447a31e75d7bd77c0108eb0c76b9749340b10db4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 11:00:27 -0700 Subject: [PATCH 169/356] Add support for CEP --- passes/pmgen/xilinx_dsp.cc | 33 ++++++++++++++++----------------- passes/pmgen/xilinx_dsp.pmg | 22 ++++++++++++++++++++-- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 5ae34a1f7..a497d0a48 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -41,6 +41,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("postAdd: %s\n", log_id(st.postAdd, "--")); log("postAddMux: %s\n", log_id(st.postAddMux, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); + log("ffPmux: %s\n", log_id(st.ffPmux, "--")); #endif log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); @@ -112,34 +113,32 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) cell->setParam("\\BREG", 1); } if (st.ffM) { - SigSpec D = st.ffM->getPort("\\D"); - SigSpec Q = st.ffM->getPort("\\Q"); - P.replace(pm.sigmap(D), Q); - cell->setParam("\\MREG", State::S1); if (st.ffMmux) { cell->setPort("\\CEM", st.ffMmux->getPort("\\S")); pm.autoremove(st.ffMmux); } else cell->setPort("\\CEM", State::S1); + SigSpec D = st.ffM->getPort("\\D"); + SigSpec Q = st.ffM->getPort("\\Q"); + P.replace(/*pm.sigmap*/(D), Q); + + cell->setParam("\\MREG", State::S1); pm.autoremove(st.ffM); } if (st.ffP) { - SigSpec D; - //if (st.muxP) - // D = st.muxP->getPort("\\B"); - //else - D = st.ffP->getPort("\\D"); - SigSpec Q = st.ffP->getPort("\\Q"); - P.replace(pm.sigmap(D), Q); - cell->setParam("\\PREG", State::S1); - if (st.ffP->type == "$dff") + if (st.ffPmux) { + cell->setPort("\\CEP", st.ffPmux->getPort("\\S")); + st.ffPmux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); + } + else cell->setPort("\\CEP", State::S1); - //else if (st.ffP->type == "$dffe") - // cell->setPort("\\CEP", st.ffP->getPort("\\EN")); - else log_abort(); - + SigSpec D = st.ffP->getPort("\\D"); + SigSpec Q = st.ffP->getPort("\\Q"); + P.replace(/*pm.sigmap*/(D), Q); st.ffP->connections_.at("\\Q").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); + + cell->setParam("\\PREG", State::S1); } log(" clock: %s (%s)", log_signal(st.clock), "posedge"); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 2681cdbca..a2a6f2ef0 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -2,7 +2,7 @@ pattern xilinx_dsp state clock state sigA sigffAmux sigB sigffBmux sigC sigM sigP -state ffAmuxAB ffBmuxAB ffMmuxAB postAddAB postAddMuxAB +state ffAmuxAB ffBmuxAB ffMmuxAB ffPmuxAB postAddAB postAddMuxAB match dsp select dsp->type.in(\DSP48E1) @@ -120,7 +120,7 @@ match ffMmux filter port(ffMmux, AB) == sigM.extract(0, GetSize(port(ffMmux, \Y))) filter nusers(sigM.extract_end(GetSize(port(ffMmux, AB)))) <= 1 set ffMmuxAB AB - optional + semioptional endmatch code sigM @@ -199,6 +199,22 @@ code sigC sigP } endcode +match ffPmux + select ffPmux->type.in($mux) + select nusers(port(ffPmux, \Y)) == 2 + filter GetSize(port(ffPmux, \Y)) <= GetSize(sigP) + choice AB {\A, \B} + filter port(ffPmux, AB) == sigP.extract(0, GetSize(port(ffPmux, \Y))) + filter nusers(sigP.extract_end(GetSize(port(ffPmux, AB)))) <= 1 + set ffPmuxAB AB + semioptional +endmatch + +code sigP + if (ffPmux) + sigP = port(ffPmux, \Y); +endcode + match ffP if param(dsp, \PREG).as_int() == 0 select ffP->type.in($dff) @@ -207,6 +223,8 @@ match ffP filter GetSize(port(ffP, \D)) >= GetSize(sigP) slice offset GetSize(port(ffP, \D)) filter offset+GetSize(sigP) <= GetSize(port(ffP, \D)) && port(ffP, \D).extract(offset, GetSize(sigP)) == sigP + // Check ffPmux (when present) is a $dff enable mux + filter !ffPmux || port(ffP, \Q) == port(ffPmux, ffPmuxAB == \A ? \B : \A) optional endmatch From fe5a1324c953cee51774228723e73a2ecac9a45b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 11:46:38 -0700 Subject: [PATCH 170/356] Do not make ff[MP]mux semioptional, use sigmap --- passes/pmgen/xilinx_dsp.cc | 7 +++++-- passes/pmgen/xilinx_dsp.pmg | 9 ++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index a497d0a48..6e82ffac3 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -121,7 +121,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) cell->setPort("\\CEM", State::S1); SigSpec D = st.ffM->getPort("\\D"); SigSpec Q = st.ffM->getPort("\\Q"); - P.replace(/*pm.sigmap*/(D), Q); + P.replace(pm.sigmap(D), Q); cell->setParam("\\MREG", State::S1); pm.autoremove(st.ffM); @@ -135,7 +135,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) cell->setPort("\\CEP", State::S1); SigSpec D = st.ffP->getPort("\\D"); SigSpec Q = st.ffP->getPort("\\Q"); - P.replace(/*pm.sigmap*/(D), Q); + P.replace(pm.sigmap(D), Q); st.ffP->connections_.at("\\Q").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); cell->setParam("\\PREG", State::S1); @@ -149,6 +149,9 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffB) log(" ffB:%s", log_id(st.ffB)); + if (st.ffM) + log(" ffM:%s", log_id(st.ffM)); + if (st.ffP) log(" ffP:%s", log_id(st.ffP)); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index a2a6f2ef0..d7632da6f 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -120,7 +120,7 @@ match ffMmux filter port(ffMmux, AB) == sigM.extract(0, GetSize(port(ffMmux, \Y))) filter nusers(sigM.extract_end(GetSize(port(ffMmux, AB)))) <= 1 set ffMmuxAB AB - semioptional + optional endmatch code sigM @@ -207,12 +207,12 @@ match ffPmux filter port(ffPmux, AB) == sigP.extract(0, GetSize(port(ffPmux, \Y))) filter nusers(sigP.extract_end(GetSize(port(ffPmux, AB)))) <= 1 set ffPmuxAB AB - semioptional + optional endmatch code sigP if (ffPmux) - sigP = port(ffPmux, \Y); + sigP.replace(port(ffPmux, ffPmuxAB), port(ffPmux, \Y)); endcode match ffP @@ -243,6 +243,9 @@ code ffP sigP clock sigP.replace(port(ffP, \D), port(ffP, \Q)); } + // Cannot have ffPmux enable mux without ffP + else if (ffPmux) + reject; endcode match postAddMux From 7bd55f379ca3bf8f79c290e9851d14b20c1f5c28 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 11:55:14 -0700 Subject: [PATCH 171/356] Use filter instead of index; support wide enable muxes --- passes/pmgen/xilinx_dsp.pmg | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index d7632da6f..cee1906d6 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -66,9 +66,11 @@ endcode match ffAmux if ffA select ffAmux->type.in($mux) + filter GetSize(port(ffAmux, \Y)) >= GetSize(sigA) + slice offset GetSize(port(ffAmux, \Y)) + filter offset+GetSize(sigA) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, \Y).extract(offset, GetSize(sigA)) == sigA choice AB {\A, \B} - index port(ffAmux, \Y) === sigA - index port(ffAmux, AB) === sigffAmux + filter offset+GetSize(sigffAmux) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, AB).extract(offset, GetSize(sigffAmux)) == sigffAmux set ffAmuxAB AB semioptional endmatch @@ -105,9 +107,11 @@ endcode match ffBmux if ffB select ffBmux->type.in($mux) + filter GetSize(port(ffBmux, \Y)) >= GetSize(sigB) + slice offset GetSize(port(ffBmux, \Y)) + filter offset+GetSize(sigB) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, \Y).extract(offset, GetSize(sigB)) == sigB choice AB {\A, \B} - index port(ffBmux, \Y) === sigB - index port(ffBmux, AB) === sigffBmux + filter offset+GetSize(sigffBmux) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, AB).extract(offset, GetSize(sigffBmux)) == sigffBmux set ffBmuxAB AB semioptional endmatch From a32b14a55f888664981dc6b1184b00f34f5f4201 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 12:38:47 -0700 Subject: [PATCH 172/356] Do not check signedness of post-adder (assume taken care of by DSP) --- passes/pmgen/xilinx_dsp.cc | 2 -- passes/pmgen/xilinx_dsp.pmg | 1 - 2 files changed, 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 6e82ffac3..9291c2dfb 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -52,8 +52,6 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) SigSpec P = st.sigP; if (st.postAdd) { - log_assert(st.postAdd->getParam("\\A_SIGNED").as_bool()); - log_assert(st.postAdd->getParam("\\B_SIGNED").as_bool()); log(" adder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); SigSpec &opmode = cell->connections_.at("\\OPMODE"); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index cee1906d6..fa490146c 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -173,7 +173,6 @@ match postAdd if port(dsp, \OPMODE).extract(4,3).is_fully_zero() select postAdd->type.in($add) - select param(postAdd, \A_SIGNED).as_bool() && param(postAdd, \B_SIGNED).as_bool() choice AB {\A, \B} select nusers(port(postAdd, AB)) <= 3 filter ffMmux || nusers(port(postAdd, AB)) == 2 From 888ae1d05e322666821262218a87b3f5577b66d0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 17:58:19 -0700 Subject: [PATCH 173/356] Fix broken ice40_dsp --- passes/pmgen/ice40_dsp.cc | 38 ++++----- passes/pmgen/ice40_dsp.pmg | 160 +++++++++++++++---------------------- 2 files changed, 85 insertions(+), 113 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 31e11c742..8f5191be7 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -28,6 +28,7 @@ PRIVATE_NAMESPACE_BEGIN void create_ice40_dsp(ice40_dsp_pm &pm) { auto &st = pm.st_ice40_dsp; + Cell* ffO = st.ffO ? st.ffO : st.ffO_lo; #if 1 log("\n"); @@ -37,8 +38,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); log("addAB: %s\n", log_id(st.addAB, "--")); log("muxAB: %s\n", log_id(st.muxAB, "--")); - log("ffO_lo: %s\n", log_id(st.ffO_lo, "--")); - log("ffO_hi: %s\n", log_id(st.ffO_hi, "--")); + log("ffO: %s\n", log_id(ffO, "--")); #endif log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); @@ -118,10 +118,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (st.ffFJKG) log(" ffFJKG:%s", log_id(st.ffFJKG)); - if (st.ffO_lo) - log(" ffO_lo:%s", log_id(st.ffO_lo)); - if (st.ffO_hi) - log(" ffO_hi:%s", log_id(st.ffO_hi)); + if (ffO) + log(" ffO:%s", log_id(ffO)); log("\n"); } @@ -167,9 +165,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm) bool accum = false; if (st.addAB) { if (st.addA) - accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\B") == st.sigO); + accum = (ffO && st.addAB->getPort("\\B") == st.sigO); else if (st.addB) - accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\A") == st.sigO); + accum = (ffO && st.addAB->getPort("\\A") == st.sigO); else log_abort(); if (accum) log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); @@ -207,12 +205,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffFJKG ? State::S1 : State::S0); cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0); - cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffO_hi ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2)); cell->setParam("\\TOPADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2)); - cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffO_lo ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2)); cell->setParam("\\BOTADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2)); @@ -221,20 +217,26 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\A_SIGNED", st.mul->getParam("\\A_SIGNED").as_bool()); cell->setParam("\\B_SIGNED", st.mul->getParam("\\B_SIGNED").as_bool()); + if (ffO) { + if (st.ffO) + cell->setParam("\\TOPOUTPUT_SELECT", Const(1, 2)); + else + cell->setParam("\\TOPOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2)); + + ffO->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); + cell->setParam("\\BOTOUTPUT_SELECT", Const(1, 2)); + } + else { + cell->setParam("\\TOPOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2)); + cell->setParam("\\BOTOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2)); + } + if (cell != st.mul) pm.autoremove(st.mul); else pm.blacklist(st.mul); pm.autoremove(st.ffFJKG); pm.autoremove(st.addAB); - if (st.ffO_lo) { - SigSpec O = st.sigO.extract(0,std::min(16,st.ffO_lo->getParam("\\WIDTH").as_int())); - st.ffO_lo->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); - } - if (st.ffO_hi) { - SigSpec O = st.sigO.extract_end(16); - st.ffO_hi->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); - } } struct Ice40DspPass : public Pass { diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 8221cdb69..4baea8aef 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,7 +1,7 @@ pattern ice40_dsp state clock -state clock_pol +state clock_pol cd_signed state > sigAset sigBset state sigA sigB sigCD sigH sigO sigOused state addAB muxAB @@ -21,13 +21,22 @@ code sigAset sigBset endcode code sigH + SigSpec O; if (mul->type == $mul) - sigH = mul->getPort(\Y); + O = mul->getPort(\Y); else if (mul->type == \SB_MAC16) - sigH = mul->getPort(\O); + O = mul->getPort(\O); else log_abort(); - if (GetSize(sigH) <= 10) + if (GetSize(O) <= 10) reject; + // Only care about those bits that are used + int i; + for (i = 0; i < GetSize(O); i++) { + if (nusers(O[i]) <= 1) + break; + sigH.append(O[i]); + } + log_assert(nusers(O.extract_end(i)) <= 1); endcode match ffA @@ -136,17 +145,16 @@ match addB optional endmatch -code addAB sigCD sigO - bool CD_SIGNED = false; +code addAB sigCD sigO cd_signed if (addA) { addAB = addA; sigCD = port(addAB, \B); - CD_SIGNED = param(addAB, \B_SIGNED).as_bool(); + cd_signed = param(addAB, \B_SIGNED).as_bool(); } - if (addB) { + else if (addB) { addAB = addB; sigCD = port(addAB, \A); - CD_SIGNED = param(addAB, \A_SIGNED).as_bool(); + cd_signed = param(addAB, \A_SIGNED).as_bool(); } if (addAB) { if (mul->type == \SB_MAC16) { @@ -167,7 +175,6 @@ code addAB sigCD sigO reject; sigO = port(addAB, \Y); - sigCD.extend_u0(32, CD_SIGNED); } endcode @@ -186,105 +193,63 @@ match muxB optional endmatch -code muxAB +code muxAB sigO if (muxA) muxAB = muxA; else if (muxB) muxAB = muxB; + if (muxAB) + sigO = port(muxAB, \Y); endcode -// Extract the bits of P that actually have a consumer -// (as opposed to being a dummy) -code sigOused - for (int i = 0; i < GetSize(sigO); i++) - if (!sigO[i].wire || nusers(sigO[i]) == 1) - sigOused.append(State::Sx); - else - sigOused.append(sigO[i]); -endcode +match ffO + // Ensure that register is not already used + if mul->type != \SB_MAC16 || (mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) + // Ensure that OLOADTOP/OLOADBOT is unused or zero + if mul->type != \SB_MAC16 || (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero()) + if nusers(sigO) == 2 + select ffO->type.in($dff) + filter GetSize(port(ffO, \D)) >= GetSize(sigO) + slice offset GetSize(port(ffO, \D)) + filter offset+GetSize(sigO) <= GetSize(port(ffO, \D)) && port(ffO, \D).extract(offset, GetSize(sigO)) == sigO + optional +endmatch match ffO_lo - if nusers(sigOused.extract(0,std::min(16,GetSize(sigOused)))) == 2 + if !ffO && GetSize(sigO) > 16 + // Ensure that register is not already used + if mul->type != \SB_MAC16 || (mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) + // Ensure that OLOADTOP/OLOADBOT is unused or zero + if mul->type != \SB_MAC16 || (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero()) + if nusers(sigO.extract(0, 16)) == 2 select ffO_lo->type.in($dff) + filter GetSize(port(ffO_lo, \D)) >= 16 + slice offset GetSize(port(ffO_lo, \D)) + filter offset+GetSize(sigO) <= GetSize(port(ffO_lo, \D)) && port(ffO_lo, \D).extract(offset, 16) == sigO.extract(0, 16) optional endmatch -code - if (ffO_lo) { - SigSpec O = sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int())); - O.remove_const(); - auto ffO_loSet = port(ffO_lo, \D).to_sigbit_set(); - auto Oset = O.to_sigbit_set(); - if (!std::includes(ffO_loSet.begin(), ffO_loSet.end(), Oset.begin(), Oset.end())) +code clock clock_pol sigO sigCD cd_signed + Cell* ff = nullptr; + if (ffO) + ff = ffO; + else if (ffO_lo) + ff = ffO_lo; + if (ff) { + for (auto b : port(ff, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + + SigBit c = port(ff, \CLK).as_bit(); + bool cp = param(ff, \CLK_POLARITY).as_bool(); + + if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; - } -endcode -match ffO_hi - if GetSize(sigOused) > 16 - if nusers(sigOused.extract_end(16)) == 2 - select ffO_hi->type.in($dff) - optional -endmatch + clock = c; + clock_pol = cp; -code - if (ffO_hi) { - SigSpec O = sigOused.extract_end(16); - O.remove_const(); - auto ffO_hiSet = port(ffO_hi, \D).to_sigbit_set(); - auto Oset = O.to_sigbit_set(); - if (!std::includes(ffO_hiSet.begin(), ffO_hiSet.end(), Oset.begin(), Oset.end())) - reject; - } -endcode - -code clock clock_pol sigO sigCD - if (ffO_lo || ffO_hi) { - if (mul->type == \SB_MAC16) { - // Ensure that register is not already used - if (param(mul, \TOPOUTPUT_SELECT).as_int() == 1 || - param(mul, \BOTOUTPUT_SELECT).as_int() == 1) - reject; - - // Ensure that OLOADTOP/OLOADBOT is unused or zero - if ((mul->hasPort(\OLOADTOP) && !port(mul, \OLOADTOP).is_fully_zero()) - || (mul->hasPort(\OLOADBOT) && !port(mul, \OLOADBOT).is_fully_zero())) - reject; - } - - if (ffO_lo) { - for (auto b : port(ffO_lo, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffO_lo, \CLK).as_bit(); - bool cp = param(ffO_lo, \CLK_POLARITY).as_bool(); - - if (clock != SigBit() && (c != clock || cp != clock_pol)) - reject; - - clock = c; - clock_pol = cp; - - sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q)); - } - - if (ffO_hi) { - for (auto b : port(ffO_hi, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffO_hi, \CLK).as_bit(); - bool cp = param(ffO_hi, \CLK_POLARITY).as_bool(); - - if (clock != SigBit() && (c != clock || cp != clock_pol)) - reject; - - clock = c; - clock_pol = cp; - - sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q)); - } + sigO.replace(port(ff, \D), port(ff, \Q)); // Loading value into output register is not // supported unless using accumulator @@ -296,8 +261,13 @@ code clock clock_pol sigO sigCD else if (muxB) sigCD = port(muxAB, \A); else log_abort(); - sigCD.extend_u0(32, addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool()); + + cd_signed = addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool(); } } + sigCD.extend_u0(32, cd_signed); +endcode + +code accept; endcode From 5a2fc6fcb5141573cbfcebdec4354fc11056a8f4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 18:06:59 -0700 Subject: [PATCH 174/356] Refactor ice40_dsp --- passes/pmgen/ice40_dsp.cc | 2 ++ passes/pmgen/ice40_dsp.pmg | 54 +++++++++++++++++++------------------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 8f5191be7..f62f627bb 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -74,9 +74,11 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Input Interface SigSpec A = st.sigA; + A.extend_u0(16, st.mul->getParam("\\A_SIGNED").as_bool()); log_assert(GetSize(A) == 16); SigSpec B = st.sigB; + B.extend_u0(16, st.mul->getParam("\\B_SIGNED").as_bool()); log_assert(GetSize(B) == 16); SigSpec CD = st.sigCD; diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 4baea8aef..1219e0d24 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -2,8 +2,7 @@ pattern ice40_dsp state clock state clock_pol cd_signed -state > sigAset sigBset -state sigA sigB sigCD sigH sigO sigOused +state sigA sigB sigCD sigH sigO state addAB muxAB match mul @@ -11,16 +10,7 @@ match mul select GetSize(mul->getPort(\A)) + GetSize(mul->getPort(\B)) > 10 endmatch -code sigAset sigBset - SigSpec A = port(mul, \A); - A.remove_const(); - sigAset = A.to_sigbit_set(); - SigSpec B = port(mul, \B); - B.remove_const(); - sigBset = B.to_sigbit_set(); -endcode - -code sigH +code sigA sigB sigH SigSpec O; if (mul->type == $mul) O = mul->getPort(\Y); @@ -29,8 +19,26 @@ code sigH else log_abort(); if (GetSize(O) <= 10) reject; - // Only care about those bits that are used + + sigA = port(mul, \A); int i; + for (i = GetSize(sigA)-1; i > 0; i--) + if (sigA[i] != sigA[i-1]) + break; + // Do not remove non-const sign bit + if (sigA[i].wire) + ++i; + sigA.remove(i, GetSize(sigA)-i); + sigB = port(mul, \B); + for (i = GetSize(sigB)-1; i > 0; i--) + if (sigB[i] != sigB[i-1]) + break; + // Do not remove non-const sign bit + if (sigB[i].wire) + ++i; + sigB.remove(i, GetSize(sigB)-i); + + // Only care about those bits that are used for (i = 0; i < GetSize(O); i++) { if (nusers(O[i]) <= 1) break; @@ -41,19 +49,15 @@ endcode match ffA if mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool() - if !sigAset.empty() select ffA->type.in($dff) + filter GetSize(port(ffA, \Q)) >= GetSize(sigA) + slice offset GetSize(port(ffA, \Q)) + filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) && port(ffA, \Q).extract(offset, GetSize(sigA)) == sigA optional endmatch code sigA clock clock_pol - sigA = port(mul, \A); - if (ffA) { - auto ffAset = port(ffA, \Q).to_sigbit_set(); - if (!std::includes(ffAset.begin(), ffAset.end(), sigAset.begin(), sigAset.end())) - reject; - for (auto b : port(ffA, \Q)) if (b.wire->get_bool_attribute(\keep)) reject; @@ -67,19 +71,15 @@ endcode match ffB if mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool() - if !sigBset.empty() select ffB->type.in($dff) + filter GetSize(port(ffB, \Q)) >= GetSize(sigB) + slice offset GetSize(port(ffB, \Q)) + filter offset+GetSize(sigB) <= GetSize(port(ffB, \Q)) && port(ffB, \Q).extract(offset, GetSize(sigB)) == sigB optional endmatch code sigB clock clock_pol - sigB = port(mul, \B); - if (ffB) { - auto ffBset = port(ffB, \Q).to_sigbit_set(); - if (!std::includes(ffBset.begin(), ffBset.end(), sigBset.begin(), sigBset.end())) - reject; - for (auto b : port(ffB, \Q)) if (b.wire->get_bool_attribute(\keep)) reject; From 53ca536d674ade382da16adddfb02db7e970acef Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 21:28:28 -0700 Subject: [PATCH 175/356] ffAmuxAB -> ffAenpol --- passes/pmgen/xilinx_dsp.cc | 5 +++-- passes/pmgen/xilinx_dsp.pmg | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 9291c2dfb..16a098fd0 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -83,9 +83,10 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) A.replace(Q, D); if (st.ffAmux) { SigSpec Y = st.ffAmux->getPort("\\Y"); - SigSpec AB = st.ffAmux->getPort(st.ffAmuxAB == "\\A" ? "\\B" : "\\A"); + SigSpec AB = st.ffAmux->getPort(st.ffAenpol ? "\\A" : "\\B"); A.replace(Y, AB); - cell->setPort("\\CEA2", st.ffAmux->getPort("\\S")); + SigSpec S = st.ffAmux->getPort("\\S"); + cell->setPort("\\CEA2", st.ffAenpol ? S : pm.module->Not(NEW_ID, S)); } else cell->setPort("\\CEA2", State::S1); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index fa490146c..579935869 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -2,7 +2,8 @@ pattern xilinx_dsp state clock state sigA sigffAmux sigB sigffBmux sigC sigM sigP -state ffAmuxAB ffBmuxAB ffMmuxAB ffPmuxAB postAddAB postAddMuxAB +state ffBmuxAB ffMmuxAB ffPmuxAB postAddAB postAddMuxAB +state ffAenpol match dsp select dsp->type.in(\DSP48E1) @@ -69,9 +70,10 @@ match ffAmux filter GetSize(port(ffAmux, \Y)) >= GetSize(sigA) slice offset GetSize(port(ffAmux, \Y)) filter offset+GetSize(sigA) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, \Y).extract(offset, GetSize(sigA)) == sigA - choice AB {\A, \B} - filter offset+GetSize(sigffAmux) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, AB).extract(offset, GetSize(sigffAmux)) == sigffAmux - set ffAmuxAB AB + choice BA {\B, \A} + filter offset+GetSize(sigffAmux) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, BA).extract(offset, GetSize(sigffAmux)) == sigffAmux + define pol (BA == \B) + set ffAenpol pol semioptional endmatch From 174edbcb96f780592cde1952db6ee7e58e8e2f56 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 21:38:35 -0700 Subject: [PATCH 176/356] Sensitive to CEB CEM CEP polarity --- passes/pmgen/xilinx_dsp.cc | 13 ++++++++----- passes/pmgen/xilinx_dsp.pmg | 35 +++++++++++++++++++---------------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 16a098fd0..38b1a12be 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -84,8 +84,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffAmux) { SigSpec Y = st.ffAmux->getPort("\\Y"); SigSpec AB = st.ffAmux->getPort(st.ffAenpol ? "\\A" : "\\B"); - A.replace(Y, AB); SigSpec S = st.ffAmux->getPort("\\S"); + A.replace(Y, AB); cell->setPort("\\CEA2", st.ffAenpol ? S : pm.module->Not(NEW_ID, S)); } else @@ -101,9 +101,10 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) B.replace(Q, D); if (st.ffBmux) { SigSpec Y = st.ffBmux->getPort("\\Y"); - SigSpec AB = st.ffBmux->getPort(st.ffBmuxAB == "\\A" ? "\\B" : "\\A"); + SigSpec AB = st.ffBmux->getPort(st.ffBenpol ? "\\A" : "\\B"); + SigSpec S = st.ffBmux->getPort("\\S"); B.replace(Y, AB); - cell->setPort("\\CEB2", st.ffBmux->getPort("\\S")); + cell->setPort("\\CEB2", st.ffBenpol ? S : pm.module->Not(NEW_ID, S)); } else cell->setPort("\\CEB2", State::S1); @@ -113,7 +114,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) } if (st.ffM) { if (st.ffMmux) { - cell->setPort("\\CEM", st.ffMmux->getPort("\\S")); + SigSpec S = st.ffMmux->getPort("\\S"); + cell->setPort("\\CEM", st.ffMenpol ? S : pm.module->Not(NEW_ID, S)); pm.autoremove(st.ffMmux); } else @@ -127,7 +129,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) } if (st.ffP) { if (st.ffPmux) { - cell->setPort("\\CEP", st.ffPmux->getPort("\\S")); + SigSpec S = st.ffPmux->getPort("\\S"); + cell->setPort("\\CEP", st.ffPenpol ? S : pm.module->Not(NEW_ID, S)); st.ffPmux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); } else diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 579935869..a86501d29 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -2,8 +2,8 @@ pattern xilinx_dsp state clock state sigA sigffAmux sigB sigffBmux sigC sigM sigP -state ffBmuxAB ffMmuxAB ffPmuxAB postAddAB postAddMuxAB -state ffAenpol +state postAddAB postAddMuxAB +state ffAenpol ffBenpol ffMenpol ffPenpol match dsp select dsp->type.in(\DSP48E1) @@ -112,9 +112,10 @@ match ffBmux filter GetSize(port(ffBmux, \Y)) >= GetSize(sigB) slice offset GetSize(port(ffBmux, \Y)) filter offset+GetSize(sigB) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, \Y).extract(offset, GetSize(sigB)) == sigB - choice AB {\A, \B} - filter offset+GetSize(sigffBmux) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, AB).extract(offset, GetSize(sigffBmux)) == sigffBmux - set ffBmuxAB AB + choice BA {\B, \A} + filter offset+GetSize(sigffBmux) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, BA).extract(offset, GetSize(sigffBmux)) == sigffBmux + define pol (BA == \B) + set ffBenpol pol semioptional endmatch @@ -122,10 +123,11 @@ match ffMmux select ffMmux->type.in($mux) select nusers(port(ffMmux, \Y)) == 2 filter GetSize(port(ffMmux, \Y)) <= GetSize(sigM) - choice AB {\A, \B} - filter port(ffMmux, AB) == sigM.extract(0, GetSize(port(ffMmux, \Y))) - filter nusers(sigM.extract_end(GetSize(port(ffMmux, AB)))) <= 1 - set ffMmuxAB AB + choice BA {\B, \A} + filter port(ffMmux, BA) == sigM.extract(0, GetSize(port(ffMmux, \Y))) + filter nusers(sigM.extract_end(GetSize(port(ffMmux, BA)))) <= 1 + define pol (BA == \B) + set ffMenpol pol optional endmatch @@ -144,7 +146,7 @@ match ffM filter port(ffM, \D) == sigM.extract(0, GetSize(port(ffM, \D))) filter nusers(sigM.extract_end(GetSize(port(ffM, \D)))) <= 1 // Check ffMmux (when present) is a $dff enable mux - filter !ffMmux || port(ffM, \Q) == port(ffMmux, ffMmuxAB == \A ? \B : \A) + filter !ffMmux || port(ffM, \Q) == port(ffMmux, ffMenpol ? \A : \B) optional endmatch @@ -208,16 +210,17 @@ match ffPmux select ffPmux->type.in($mux) select nusers(port(ffPmux, \Y)) == 2 filter GetSize(port(ffPmux, \Y)) <= GetSize(sigP) - choice AB {\A, \B} - filter port(ffPmux, AB) == sigP.extract(0, GetSize(port(ffPmux, \Y))) - filter nusers(sigP.extract_end(GetSize(port(ffPmux, AB)))) <= 1 - set ffPmuxAB AB + choice BA {\B, \A} + filter port(ffPmux, BA) == sigP.extract(0, GetSize(port(ffPmux, \Y))) + filter nusers(sigP.extract_end(GetSize(port(ffPmux, BA)))) <= 1 + define pol (BA == \B) + set ffPenpol pol optional endmatch code sigP if (ffPmux) - sigP.replace(port(ffPmux, ffPmuxAB), port(ffPmux, \Y)); + sigP.replace(port(ffPmux, ffPenpol ? \A : \B), port(ffPmux, \Y)); endcode match ffP @@ -229,7 +232,7 @@ match ffP slice offset GetSize(port(ffP, \D)) filter offset+GetSize(sigP) <= GetSize(port(ffP, \D)) && port(ffP, \D).extract(offset, GetSize(sigP)) == sigP // Check ffPmux (when present) is a $dff enable mux - filter !ffPmux || port(ffP, \Q) == port(ffPmux, ffPmuxAB == \A ? \B : \A) + filter !ffPmux || port(ffP, \Q) == port(ffPmux, ffPenpol ? \A : \B) optional endmatch From dc10559f31410e2395e1321d6ca6126024c7cea3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 5 Sep 2019 21:39:52 -0700 Subject: [PATCH 177/356] Cleanup --- passes/pmgen/ice40_dsp.cc | 17 ++++++++--------- passes/pmgen/ice40_dsp.pmg | 34 +++++++++++++++++----------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index f62f627bb..7858b8972 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -28,7 +28,6 @@ PRIVATE_NAMESPACE_BEGIN void create_ice40_dsp(ice40_dsp_pm &pm) { auto &st = pm.st_ice40_dsp; - Cell* ffO = st.ffO ? st.ffO : st.ffO_lo; #if 1 log("\n"); @@ -38,7 +37,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); log("addAB: %s\n", log_id(st.addAB, "--")); log("muxAB: %s\n", log_id(st.muxAB, "--")); - log("ffO: %s\n", log_id(ffO, "--")); + log("ffO: %s\n", log_id(st.ffO, "--")); #endif log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); @@ -120,8 +119,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (st.ffFJKG) log(" ffFJKG:%s", log_id(st.ffFJKG)); - if (ffO) - log(" ffO:%s", log_id(ffO)); + if (st.ffO) + log(" ffO:%s", log_id(st.ffO)); log("\n"); } @@ -167,9 +166,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm) bool accum = false; if (st.addAB) { if (st.addA) - accum = (ffO && st.addAB->getPort("\\B") == st.sigO); + accum = (st.ffO && st.addAB->getPort("\\B") == st.sigO); else if (st.addB) - accum = (ffO && st.addAB->getPort("\\A") == st.sigO); + accum = (st.ffO && st.addAB->getPort("\\A") == st.sigO); else log_abort(); if (accum) log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); @@ -219,13 +218,13 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\A_SIGNED", st.mul->getParam("\\A_SIGNED").as_bool()); cell->setParam("\\B_SIGNED", st.mul->getParam("\\B_SIGNED").as_bool()); - if (ffO) { - if (st.ffO) + if (st.ffO) { + if (st.ffO_hilo) cell->setParam("\\TOPOUTPUT_SELECT", Const(1, 2)); else cell->setParam("\\TOPOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2)); - ffO->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); + st.ffO->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); cell->setParam("\\BOTOUTPUT_SELECT", Const(1, 2)); } else { diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 1219e0d24..95e8da379 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -3,7 +3,7 @@ pattern ice40_dsp state clock state clock_pol cd_signed state sigA sigB sigCD sigH sigO -state addAB muxAB +state addAB muxAB ffO match mul select mul->type.in($mul, \SB_MAC16) @@ -202,21 +202,21 @@ code muxAB sigO sigO = port(muxAB, \Y); endcode -match ffO +match ffO_hilo // Ensure that register is not already used if mul->type != \SB_MAC16 || (mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) // Ensure that OLOADTOP/OLOADBOT is unused or zero if mul->type != \SB_MAC16 || (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero()) if nusers(sigO) == 2 - select ffO->type.in($dff) - filter GetSize(port(ffO, \D)) >= GetSize(sigO) - slice offset GetSize(port(ffO, \D)) - filter offset+GetSize(sigO) <= GetSize(port(ffO, \D)) && port(ffO, \D).extract(offset, GetSize(sigO)) == sigO + select ffO_hilo->type.in($dff) + filter GetSize(port(ffO_hilo, \D)) >= GetSize(sigO) + slice offset GetSize(port(ffO_hilo, \D)) + filter offset+GetSize(sigO) <= GetSize(port(ffO_hilo, \D)) && port(ffO_hilo, \D).extract(offset, GetSize(sigO)) == sigO optional endmatch match ffO_lo - if !ffO && GetSize(sigO) > 16 + if !ffO_hilo && GetSize(sigO) > 16 // Ensure that register is not already used if mul->type != \SB_MAC16 || (mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) // Ensure that OLOADTOP/OLOADBOT is unused or zero @@ -229,19 +229,19 @@ match ffO_lo optional endmatch -code clock clock_pol sigO sigCD cd_signed - Cell* ff = nullptr; - if (ffO) - ff = ffO; +code ffO clock clock_pol sigO sigCD cd_signed + ffO = nullptr; + if (ffO_hilo) + ffO = ffO_hilo; else if (ffO_lo) - ff = ffO_lo; - if (ff) { - for (auto b : port(ff, \Q)) + ffO = ffO_lo; + if (ffO) { + for (auto b : port(ffO, \Q)) if (b.wire->get_bool_attribute(\keep)) reject; - SigBit c = port(ff, \CLK).as_bit(); - bool cp = param(ff, \CLK_POLARITY).as_bool(); + SigBit c = port(ffO, \CLK).as_bit(); + bool cp = param(ffO, \CLK_POLARITY).as_bool(); if (clock != SigBit() && (c != clock || cp != clock_pol)) reject; @@ -249,7 +249,7 @@ code clock clock_pol sigO sigCD cd_signed clock = c; clock_pol = cp; - sigO.replace(port(ff, \D), port(ff, \Q)); + sigO.replace(port(ffO, \D), port(ffO, \Q)); // Loading value into output register is not // supported unless using accumulator From 4fe24b20f9c42e81bf0539c4b3bde9c4a471c5ea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 09:47:32 -0700 Subject: [PATCH 178/356] More nusers() checks for A and B enable muxes --- passes/pmgen/xilinx_dsp.pmg | 41 ++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index a86501d29..15343e21e 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,7 +1,7 @@ pattern xilinx_dsp state clock -state sigA sigffAmux sigB sigffBmux sigC sigM sigP +state sigA sigffAmuxY sigB sigffBmuxY sigC sigM sigP state postAddAB postAddMuxAB state ffAenpol ffBenpol ffMenpol ffPenpol @@ -9,7 +9,7 @@ match dsp select dsp->type.in(\DSP48E1) endmatch -code sigA sigffAmux sigB sigffBmux sigM +code sigA sigffAmuxY sigB sigffBmuxY sigM sigA = port(dsp, \A); int i; for (i = GetSize(sigA)-1; i > 0; i--) @@ -38,6 +38,9 @@ code sigA sigffAmux sigB sigffBmux sigM log_assert(nusers(P.extract_end(i)) <= 1); //if (GetSize(sigM) <= 10) // reject; + + sigffAmuxY = SigSpec(); + sigffBmuxY = SigSpec(); endcode match ffA @@ -51,7 +54,7 @@ match ffA optional endmatch -code sigA sigffAmux clock +code sigA sigffAmuxY clock if (ffA) { for (auto b : port(ffA, \Q)) if (b.wire->get_bool_attribute(\keep)) @@ -59,19 +62,25 @@ code sigA sigffAmux clock clock = port(ffA, \CLK).as_bit(); - sigffAmux = sigA; - sigA.replace(port(ffA, \Q), port(ffA, \D)); + SigSpec A = sigA; + A.replace(port(ffA, \Q), port(ffA, \D)); + // Only search for ffAmux if ffA.Q has at + // least 3 users (ffA, dsp, ffAmux) and + // its ffA.D only has two (ffA, ffAmux) + if (nusers(sigA) >= 3 && nusers(A) == 2) + sigffAmuxY = sigA; + sigA = std::move(A); } endcode match ffAmux - if ffA + if !sigffAmuxY.empty() select ffAmux->type.in($mux) filter GetSize(port(ffAmux, \Y)) >= GetSize(sigA) slice offset GetSize(port(ffAmux, \Y)) filter offset+GetSize(sigA) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, \Y).extract(offset, GetSize(sigA)) == sigA choice BA {\B, \A} - filter offset+GetSize(sigffAmux) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, BA).extract(offset, GetSize(sigffAmux)) == sigffAmux + filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, BA).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY define pol (BA == \B) set ffAenpol pol semioptional @@ -88,32 +97,36 @@ match ffB optional endmatch -code sigB sigffBmux clock +code sigB sigffBmuxY clock if (ffB) { for (auto b : port(ffB, \Q)) if (b.wire->get_bool_attribute(\keep)) reject; SigBit c = port(ffB, \CLK).as_bit(); - if (clock != SigBit() && c != clock) reject; - clock = c; - sigffBmux = sigB; - sigB.replace(port(ffB, \Q), port(ffB, \D)); + SigSpec B = sigB; + B.replace(port(ffB, \Q), port(ffB, \D)); + // Only search for ffBmux if ffB.Q has at + // least 3 users (ffB, dsp, ffBmux) and + // its ffB.D only has two (ffB, ffBmux) + if (nusers(sigB) >= 3 && nusers(B) == 2) + sigffBmuxY = sigB; + sigB = std::move(B); } endcode match ffBmux - if ffB + if !sigffBmuxY.empty() select ffBmux->type.in($mux) filter GetSize(port(ffBmux, \Y)) >= GetSize(sigB) slice offset GetSize(port(ffBmux, \Y)) filter offset+GetSize(sigB) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, \Y).extract(offset, GetSize(sigB)) == sigB choice BA {\B, \A} - filter offset+GetSize(sigffBmux) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, BA).extract(offset, GetSize(sigffBmux)) == sigffBmux + filter offset+GetSize(sigffBmuxY) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, BA).extract(offset, GetSize(sigffBmuxY)) == sigffBmuxY define pol (BA == \B) set ffBenpol pol semioptional From 91f68c4de2c1c9823e5c6a6257ded09144dfcbd6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 09:59:35 -0700 Subject: [PATCH 179/356] Check nusers for M and P enable muxes --- passes/pmgen/xilinx_dsp.pmg | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 15343e21e..8f83a2a50 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -134,10 +134,17 @@ endmatch match ffMmux select ffMmux->type.in($mux) + choice BA {\B, \A} + // new-value net must have exactly two users: dsp and ffM + select nusers(port(ffMmux, BA)) == 2 + define AB (BA == \B ? \A : \B) + // keep-last-value net must have at least three users: ffMmux, ffM, downstream sink(s) + select nusers(port(ffMmux, AB)) >= 3 + // ffMmux output must have two users: ffMmux and ffM.D select nusers(port(ffMmux, \Y)) == 2 filter GetSize(port(ffMmux, \Y)) <= GetSize(sigM) - choice BA {\B, \A} filter port(ffMmux, BA) == sigM.extract(0, GetSize(port(ffMmux, \Y))) + // Remaining bits on sigM must not have any other users filter nusers(sigM.extract_end(GetSize(port(ffMmux, BA)))) <= 1 define pol (BA == \B) set ffMenpol pol @@ -157,6 +164,7 @@ match ffM select nusers(port(ffM, \D)) == 2 filter GetSize(port(ffM, \D)) <= GetSize(sigM) filter port(ffM, \D) == sigM.extract(0, GetSize(port(ffM, \D))) + // Remaining bits on sigM must not have any other users filter nusers(sigM.extract_end(GetSize(port(ffM, \D)))) <= 1 // Check ffMmux (when present) is a $dff enable mux filter !ffMmux || port(ffM, \Q) == port(ffMmux, ffMenpol ? \A : \B) @@ -221,10 +229,17 @@ endcode match ffPmux select ffPmux->type.in($mux) + choice BA {\B, \A} + // new-value net must have exactly two users: dsp and ffP + select nusers(port(ffPmux, BA)) == 2 + define AB (BA == \B ? \A : \B) + // keep-last-value net must have at least three users: ffPmux, ffP, downstream sink(s) + select nusers(port(ffPmux, AB)) >= 3 + // ffPmux output must have two users: ffPmux and ffP.D select nusers(port(ffPmux, \Y)) == 2 filter GetSize(port(ffPmux, \Y)) <= GetSize(sigP) - choice BA {\B, \A} filter port(ffPmux, BA) == sigP.extract(0, GetSize(port(ffPmux, \Y))) + // Remaining bits on sigP must not have any other users filter nusers(sigP.extract_end(GetSize(port(ffPmux, BA)))) <= 1 define pol (BA == \B) set ffPenpol pol From cdc1e1f5c226d3597896555749ecfa3568a66c50 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 10:35:06 -0700 Subject: [PATCH 180/356] Check adder is <= 48 bits before packing --- passes/pmgen/xilinx_dsp.pmg | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 8f83a2a50..bb3bf90bd 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -83,7 +83,7 @@ match ffAmux filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, BA).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY define pol (BA == \B) set ffAenpol pol - semioptional + optional endmatch match ffB @@ -129,7 +129,7 @@ match ffBmux filter offset+GetSize(sigffBmuxY) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, BA).extract(offset, GetSize(sigffBmuxY)) == sigffBmuxY define pol (BA == \B) set ffBenpol pol - semioptional + optional endmatch match ffMmux @@ -180,10 +180,8 @@ code clock sigM sigP reject; SigBit c = port(ffM, \CLK).as_bit(); - if (clock != SigBit() && c != clock) reject; - clock = c; } // Cannot have ffMmux enable mux without ffM @@ -198,6 +196,8 @@ match postAdd if port(dsp, \OPMODE).extract(4,3).is_fully_zero() select postAdd->type.in($add) + select GetSize(port(postAdd, \Y)) <= 48 + select nusers(port(postAdd, \Y)) == 2 choice AB {\A, \B} select nusers(port(postAdd, AB)) <= 3 filter ffMmux || nusers(port(postAdd, AB)) == 2 @@ -256,6 +256,7 @@ match ffP select ffP->type.in($dff) // DSP48E1 does not support clock inversion select param(ffP, \CLK_POLARITY).as_bool() + select nusers(port(ffP, \D)) == 2 filter GetSize(port(ffP, \D)) >= GetSize(sigP) slice offset GetSize(port(ffP, \D)) filter offset+GetSize(sigP) <= GetSize(port(ffP, \D)) && port(ffP, \D).extract(offset, GetSize(sigP)) == sigP From 39a5d046ea5fe1021520d285723ef0b02dca4d17 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 11:38:19 -0700 Subject: [PATCH 181/356] Fix nusers condition in ffP --- passes/pmgen/xilinx_dsp.pmg | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index bb3bf90bd..adf30b45a 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -228,6 +228,8 @@ code sigC sigP endcode match ffPmux + if param(dsp, \PREG).as_int() == 0 + if nusers(sigP) == 2 select ffPmux->type.in($mux) choice BA {\B, \A} // new-value net must have exactly two users: dsp and ffP @@ -253,13 +255,14 @@ endcode match ffP if param(dsp, \PREG).as_int() == 0 + if nusers(sigP) == 2 select ffP->type.in($dff) // DSP48E1 does not support clock inversion select param(ffP, \CLK_POLARITY).as_bool() - select nusers(port(ffP, \D)) == 2 filter GetSize(port(ffP, \D)) >= GetSize(sigP) slice offset GetSize(port(ffP, \D)) - filter offset+GetSize(sigP) <= GetSize(port(ffP, \D)) && port(ffP, \D).extract(offset, GetSize(sigP)) == sigP + filter offset+GetSize(sigP) <= GetSize(port(ffP, \D)) + filter port(ffP, \D).extract(offset, GetSize(sigP)) == sigP // Check ffPmux (when present) is a $dff enable mux filter !ffPmux || port(ffP, \Q) == port(ffPmux, ffPenpol ? \A : \B) optional From fbf1b749460dea32eb52c39a9553fc8fdfdd914e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 11:39:20 -0700 Subject: [PATCH 182/356] Simplify filter expressions --- passes/pmgen/xilinx_dsp.pmg | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index adf30b45a..a9e2ebf86 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -50,7 +50,8 @@ match ffA select param(ffA, \CLK_POLARITY).as_bool() filter GetSize(port(ffA, \Q)) >= GetSize(sigA) slice offset GetSize(port(ffA, \Q)) - filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) && port(ffA, \Q).extract(offset, GetSize(sigA)) == sigA + filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) + filter port(ffA, \Q).extract(offset, GetSize(sigA)) == sigA optional endmatch @@ -78,9 +79,11 @@ match ffAmux select ffAmux->type.in($mux) filter GetSize(port(ffAmux, \Y)) >= GetSize(sigA) slice offset GetSize(port(ffAmux, \Y)) - filter offset+GetSize(sigA) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, \Y).extract(offset, GetSize(sigA)) == sigA + filter offset+GetSize(sigA) <= GetSize(port(ffAmux, \Y)) + filter port(ffAmux, \Y).extract(offset, GetSize(sigA)) == sigA choice BA {\B, \A} - filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffAmux, \Y)) && port(ffAmux, BA).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY + filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffAmux, \Y)) + filter port(ffAmux, BA).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY define pol (BA == \B) set ffAenpol pol optional @@ -93,7 +96,8 @@ match ffB select param(ffB, \CLK_POLARITY).as_bool() filter GetSize(port(ffB, \Q)) >= GetSize(sigB) slice offset GetSize(port(ffB, \Q)) - filter offset+GetSize(sigB) <= GetSize(port(ffB, \Q)) && port(ffB, \Q).extract(offset, GetSize(sigB)) == sigB + filter offset+GetSize(sigB) <= GetSize(port(ffB, \Q)) + filter port(ffB, \Q).extract(offset, GetSize(sigB)) == sigB optional endmatch @@ -124,9 +128,11 @@ match ffBmux select ffBmux->type.in($mux) filter GetSize(port(ffBmux, \Y)) >= GetSize(sigB) slice offset GetSize(port(ffBmux, \Y)) - filter offset+GetSize(sigB) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, \Y).extract(offset, GetSize(sigB)) == sigB + filter offset+GetSize(sigB) <= GetSize(port(ffBmux, \Y)) + filter port(ffBmux, \Y).extract(offset, GetSize(sigB)) == sigB choice BA {\B, \A} - filter offset+GetSize(sigffBmuxY) <= GetSize(port(ffBmux, \Y)) && port(ffBmux, BA).extract(offset, GetSize(sigffBmuxY)) == sigffBmuxY + filter offset+GetSize(sigffBmuxY) <= GetSize(port(ffBmux, \Y)) + filter port(ffBmux, BA).extract(offset, GetSize(sigffBmuxY)) == sigffBmuxY define pol (BA == \B) set ffBenpol pol optional From a945f6c7ef43258504f8c9c5a9c2d2e03fbfe0fe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 11:58:56 -0700 Subject: [PATCH 183/356] Fix ffPmux to cope with offset --- passes/pmgen/xilinx_dsp.pmg | 48 +++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index a9e2ebf86..58ffcfedf 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -4,6 +4,7 @@ state clock state sigA sigffAmuxY sigB sigffBmuxY sigC sigM sigP state postAddAB postAddMuxAB state ffAenpol ffBenpol ffMenpol ffPenpol +state ffPoffset match dsp select dsp->type.in(\DSP48E1) @@ -139,6 +140,8 @@ match ffBmux endmatch match ffMmux + if param(dsp, \MREG).as_int() == 0 + if nusers(sigM) == 2 select ffMmux->type.in($mux) choice BA {\B, \A} // new-value net must have exactly two users: dsp and ffM @@ -164,6 +167,7 @@ endcode match ffM if param(dsp, \MREG).as_int() == 0 + if nusers(sigM) == 2 select ffM->type.in($dff) // DSP48E1 does not support clock inversion select param(ffM, \CLK_POLARITY).as_bool() @@ -235,31 +239,47 @@ endcode match ffPmux if param(dsp, \PREG).as_int() == 0 + // new-value net must have exactly two users: dsp and ffP if nusers(sigP) == 2 select ffPmux->type.in($mux) - choice BA {\B, \A} - // new-value net must have exactly two users: dsp and ffP - select nusers(port(ffPmux, BA)) == 2 - define AB (BA == \B ? \A : \B) - // keep-last-value net must have at least three users: ffPmux, ffP, downstream sink(s) - select nusers(port(ffPmux, AB)) >= 3 // ffPmux output must have two users: ffPmux and ffP.D select nusers(port(ffPmux, \Y)) == 2 - filter GetSize(port(ffPmux, \Y)) <= GetSize(sigP) - filter port(ffPmux, BA) == sigP.extract(0, GetSize(port(ffPmux, \Y))) - // Remaining bits on sigP must not have any other users - filter nusers(sigP.extract_end(GetSize(port(ffPmux, BA)))) <= 1 + filter GetSize(port(ffPmux, \Y)) >= GetSize(sigP) + + choice BA {\B, \A} + slice offset GetSize(port(ffPmux, \Y)) + filter offset+GetSize(sigP) <= GetSize(port(ffPmux, \Y)) + filter port(ffPmux, BA).extract(offset, GetSize(sigP)) == sigP + + define AB (BA == \B ? \A : \B) + // keep-last-value net must have at least three users: ffPmux, ffP, downstream sink(s) + filter nusers(port(ffPmux, AB)) >= 3 define pol (BA == \B) set ffPenpol pol + set ffPoffset offset optional endmatch code sigP if (ffPmux) - sigP.replace(port(ffPmux, ffPenpol ? \A : \B), port(ffPmux, \Y)); + sigP.replace(port(ffPmux, ffPenpol ? \B : \A), port(ffPmux, \Y)); endcode +match ffP_enable + if ffPmux + if nusers(sigP) == 2 + select ffP_enable->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ffP_enable, \CLK_POLARITY).as_bool() + index port(ffP_enable, \D) === port(ffPmux, \Y) + index port(ffP_enable, \Q) === port(ffPmux, ffPenpol ? \A : \B) + filter GetSize(port(ffP_enable, \D)) >= GetSize(sigP) + filter ffPoffset+GetSize(sigP) <= GetSize(port(ffP_enable, \D)) + filter port(ffP_enable, \D).extract(ffPoffset, GetSize(sigP)) == sigP +endmatch + match ffP + if !ffP_enable if param(dsp, \PREG).as_int() == 0 if nusers(sigP) == 2 select ffP->type.in($dff) @@ -269,12 +289,14 @@ match ffP slice offset GetSize(port(ffP, \D)) filter offset+GetSize(sigP) <= GetSize(port(ffP, \D)) filter port(ffP, \D).extract(offset, GetSize(sigP)) == sigP - // Check ffPmux (when present) is a $dff enable mux - filter !ffPmux || port(ffP, \Q) == port(ffPmux, ffPenpol ? \A : \B) optional endmatch code ffP sigP clock + if (ffP_enable) { + log_assert(!ffP); + ffP = ffP_enable; + } if (ffP) { for (auto b : port(ffP, \Q)) if (b.wire->get_bool_attribute(\keep)) From 776d76994102af4ee9ade69392f31c0a2f4f61ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 12:07:35 -0700 Subject: [PATCH 184/356] Use more index patterns --- passes/pmgen/xilinx_dsp.pmg | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 58ffcfedf..5cea69b16 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -78,6 +78,7 @@ endcode match ffAmux if !sigffAmuxY.empty() select ffAmux->type.in($mux) + index port(ffAmux, \Y) === port(ffA, \D) filter GetSize(port(ffAmux, \Y)) >= GetSize(sigA) slice offset GetSize(port(ffAmux, \Y)) filter offset+GetSize(sigA) <= GetSize(port(ffAmux, \Y)) @@ -127,6 +128,7 @@ endcode match ffBmux if !sigffBmuxY.empty() select ffBmux->type.in($mux) + index port(ffBmux, \Y) === port(ffB, \D) filter GetSize(port(ffBmux, \Y)) >= GetSize(sigB) slice offset GetSize(port(ffBmux, \Y)) filter offset+GetSize(sigB) <= GetSize(port(ffBmux, \Y)) @@ -165,23 +167,32 @@ code sigM sigM = port(ffMmux, \Y); endcode +match ffM_enable + if ffMmux + if nusers(sigM) == 2 + select ffM_enable->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ffM_enable, \CLK_POLARITY).as_bool() + index port(ffM_enable, \D) === sigM + index port(ffM_enable, \Q) === port(ffMmux, ffMenpol ? \A : \B) +endmatch + match ffM + if !ffM_enable if param(dsp, \MREG).as_int() == 0 if nusers(sigM) == 2 select ffM->type.in($dff) // DSP48E1 does not support clock inversion select param(ffM, \CLK_POLARITY).as_bool() - select nusers(port(ffM, \D)) == 2 - filter GetSize(port(ffM, \D)) <= GetSize(sigM) - filter port(ffM, \D) == sigM.extract(0, GetSize(port(ffM, \D))) - // Remaining bits on sigM must not have any other users - filter nusers(sigM.extract_end(GetSize(port(ffM, \D)))) <= 1 - // Check ffMmux (when present) is a $dff enable mux - filter !ffMmux || port(ffM, \Q) == port(ffMmux, ffMenpol ? \A : \B) + index port(ffM, \D) === sigM optional endmatch -code clock sigM sigP +code ffM clock sigM sigP + if (ffM_enable) { + log_assert(!ffM); + ffM = ffM_enable; + } if (ffM) { sigM = port(ffM, \Q); @@ -194,10 +205,6 @@ code clock sigM sigP reject; clock = c; } - // Cannot have ffMmux enable mux without ffM - else if (ffMmux) - reject; - sigP = sigM; endcode @@ -311,9 +318,6 @@ code ffP sigP clock sigP.replace(port(ffP, \D), port(ffP, \Q)); } - // Cannot have ffPmux enable mux without ffP - else if (ffPmux) - reject; endcode match postAddMux From da8fe83f7ac6305d6cc884823a561828b13e7931 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 12:16:40 -0700 Subject: [PATCH 185/356] Tidy up ice40_dsp some more --- passes/pmgen/ice40_dsp.cc | 6 +++--- passes/pmgen/ice40_dsp.pmg | 21 ++++++++++----------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 7858b8972..68fc29f31 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -219,10 +219,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\B_SIGNED", st.mul->getParam("\\B_SIGNED").as_bool()); if (st.ffO) { - if (st.ffO_hilo) - cell->setParam("\\TOPOUTPUT_SELECT", Const(1, 2)); - else + if (st.ffO_lo) cell->setParam("\\TOPOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2)); + else + cell->setParam("\\TOPOUTPUT_SELECT", Const(1, 2)); st.ffO->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); cell->setParam("\\BOTOUTPUT_SELECT", Const(1, 2)); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 95e8da379..fbf498109 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -3,7 +3,7 @@ pattern ice40_dsp state clock state clock_pol cd_signed state sigA sigB sigCD sigH sigO -state addAB muxAB ffO +state addAB muxAB match mul select mul->type.in($mul, \SB_MAC16) @@ -202,21 +202,21 @@ code muxAB sigO sigO = port(muxAB, \Y); endcode -match ffO_hilo +match ffO // Ensure that register is not already used if mul->type != \SB_MAC16 || (mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) // Ensure that OLOADTOP/OLOADBOT is unused or zero if mul->type != \SB_MAC16 || (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero()) if nusers(sigO) == 2 - select ffO_hilo->type.in($dff) - filter GetSize(port(ffO_hilo, \D)) >= GetSize(sigO) - slice offset GetSize(port(ffO_hilo, \D)) - filter offset+GetSize(sigO) <= GetSize(port(ffO_hilo, \D)) && port(ffO_hilo, \D).extract(offset, GetSize(sigO)) == sigO + select ffO->type.in($dff) + filter GetSize(port(ffO, \D)) >= GetSize(sigO) + slice offset GetSize(port(ffO, \D)) + filter offset+GetSize(sigO) <= GetSize(port(ffO, \D)) && port(ffO, \D).extract(offset, GetSize(sigO)) == sigO optional endmatch match ffO_lo - if !ffO_hilo && GetSize(sigO) > 16 + if !ffO && GetSize(sigO) > 16 // Ensure that register is not already used if mul->type != \SB_MAC16 || (mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) // Ensure that OLOADTOP/OLOADBOT is unused or zero @@ -230,11 +230,10 @@ match ffO_lo endmatch code ffO clock clock_pol sigO sigCD cd_signed - ffO = nullptr; - if (ffO_hilo) - ffO = ffO_hilo; - else if (ffO_lo) + if (ffO_lo) { + log_assert(!ffO); ffO = ffO_lo; + } if (ffO) { for (auto b : port(ffO, \Q)) if (b.wire->get_bool_attribute(\keep)) From ef77162ce4bff9987312a0881483c7befaed2dc5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 13:28:15 -0700 Subject: [PATCH 186/356] Document (* gentb_skip *) attr for test_autotb --- passes/tests/test_autotb.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc index 7f11e54f3..2b6a86c25 100644 --- a/passes/tests/test_autotb.cc +++ b/passes/tests/test_autotb.cc @@ -345,6 +345,9 @@ struct TestAutotbBackend : public Backend { log("value after initialization. This can e.g. be used to force a reset signal\n"); log("low in order to explore more inner states in a state machine.\n"); log("\n"); + log("The attribute 'gentb_skip' can be attached to modules to suppress testbench\n"); + log("generation.\n"); + log("\n"); log(" -n \n"); log(" number of iterations the test bench should run (default = 1000)\n"); log("\n"); From e926f2973e5c6bf8e00cd67fc44200ceb47e215e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 14:06:57 -0700 Subject: [PATCH 187/356] Add support for pre-adder and AD register --- passes/pmgen/xilinx_dsp.cc | 31 ++++++++++- passes/pmgen/xilinx_dsp.pmg | 101 ++++++++++++++++++++++++++++++++++-- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 38b1a12be..9587ed28a 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -31,6 +31,9 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) #if 1 log("\n"); + log("preAdd: %s\n", log_id(st.preAdd, "--")); + log("ffAD: %s\n", log_id(st.ffAD, "--")); + log("ffADmux: %s\n", log_id(st.ffADmux, "--")); log("ffA: %s\n", log_id(st.ffA, "--")); log("ffAmux: %s\n", log_id(st.ffAmux, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); @@ -51,8 +54,34 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) SigSpec C = st.sigC; SigSpec P = st.sigP; + if (st.preAdd) { + log(" preadder %s (%s)\n", log_id(st.preAdd), log_id(st.preAdd->type)); + bool A_SIGNED = st.preAdd->getParam("\\A_SIGNED").as_bool(); + bool D_SIGNED = st.preAdd->getParam("\\B_SIGNED").as_bool(); + if (st.sigA == st.preAdd->getPort("\\B")) + std::swap(A_SIGNED, D_SIGNED); + st.sigA.extend_u0(30, A_SIGNED); + st.sigD.extend_u0(25, D_SIGNED); + cell->setPort("\\A", st.sigA); + cell->setPort("\\D", st.sigD); + cell->connections_.at("\\INMODE") = Const::from_string("00100"); + + if (st.ffAD) { + if (st.ffADmux) { + SigSpec S = st.ffADmux->getPort("\\S"); + cell->setPort("\\CEAD", st.ffADenpol ? S : pm.module->Not(NEW_ID, S)); + } + else + cell->setPort("\\CEAD", State::S1); + cell->setParam("\\ADREG", 1); + } + + cell->setParam("\\USE_DPORT", Const("TRUE")); + + pm.autoremove(st.preAdd); + } if (st.postAdd) { - log(" adder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); + log(" postadder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); SigSpec &opmode = cell->connections_.at("\\OPMODE"); if (st.postAddMux) { diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 5cea69b16..83963804b 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,16 +1,16 @@ pattern xilinx_dsp state clock -state sigA sigffAmuxY sigB sigffBmuxY sigC sigM sigP +state sigA sigffAmuxY sigB sigffBmuxY sigC sigD sigM sigP state postAddAB postAddMuxAB -state ffAenpol ffBenpol ffMenpol ffPenpol +state ffAenpol ffADenpol ffBenpol ffMenpol ffPenpol state ffPoffset match dsp select dsp->type.in(\DSP48E1) endmatch -code sigA sigffAmuxY sigB sigffBmuxY sigM +code sigA sigffAmuxY sigB sigffBmuxY sigD sigM sigA = port(dsp, \A); int i; for (i = GetSize(sigA)-1; i > 0; i--) @@ -29,6 +29,8 @@ code sigA sigffAmuxY sigB sigffBmuxY sigM ++i; sigB.remove(i, GetSize(sigB)-i); + sigD = dsp->connections_.at(\D, SigSpec()); + SigSpec P = port(dsp, \P); // Only care about those bits that are used for (i = 0; i < GetSize(P); i++) { @@ -44,7 +46,85 @@ code sigA sigffAmuxY sigB sigffBmuxY sigM sigffBmuxY = SigSpec(); endcode +match ffAD + if param(dsp, \ADREG).as_int() == 0 + select ffAD->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ffAD, \CLK_POLARITY).as_bool() + filter GetSize(port(ffAD, \Q)) >= GetSize(sigA) + slice offset GetSize(port(ffAD, \Q)) + filter offset+GetSize(sigA) <= GetSize(port(ffAD, \Q)) + filter port(ffAD, \Q).extract(offset, GetSize(sigA)) == sigA + optional +endmatch + +code sigA sigffAmuxY clock + if (ffAD) { + for (auto b : port(ffAD, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + + clock = port(ffAD, \CLK).as_bit(); + + SigSpec A = sigA; + A.replace(port(ffAD, \Q), port(ffAD, \D)); + // Only search for ffAmux if ffA.Q has at + // least 3 users (ffA, dsp, ffAmux) and + // its ffA.D only has two (ffA, ffAmux) + if (nusers(sigA) >= 3 && nusers(A) == 2) + sigffAmuxY = sigA; + sigA = std::move(A); + } +endcode + +match ffADmux + if !sigffAmuxY.empty() + select ffADmux->type.in($mux) + index port(ffADmux, \Y) === port(ffAD, \D) + filter GetSize(port(ffADmux, \Y)) >= GetSize(sigA) + slice offset GetSize(port(ffADmux, \Y)) + filter offset+GetSize(sigA) <= GetSize(port(ffADmux, \Y)) + filter port(ffADmux, \Y).extract(offset, GetSize(sigA)) == sigA + choice BA {\B, \A} + filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffADmux, \Y)) + filter port(ffADmux, BA).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY + define pol (BA == \B) + set ffADenpol pol + optional +endmatch + +match preAdd + if sigD.empty() || sigD.is_fully_zero() + // Ensure that preAdder not already used + if dsp->parameters.at(\USE_DPORT, Const("FALSE")).decode_string() == "FALSE" + if dsp->connections_.at(\INMODE, Const(0, 5)).is_fully_zero() + + select preAdd->type.in($add) + // Output has to be 25 bits or less + select GetSize(port(preAdd, \Y)) <= 25 + select nusers(port(preAdd, \Y)) == 2 + choice AB {\A, \B} + // A port has to be 30 bits or less + select GetSize(port(preAdd, AB)) <= 30 + define BA (AB == \A ? \B : \A) + // D port has to be 25 bits or less + select GetSize(port(preAdd, BA)) <= 25 + index port(preAdd, \Y) === sigA + + optional +endmatch + +code sigA sigD + if (preAdd) { + sigA = port(preAdd, \A); + sigD = port(preAdd, \B); + if (GetSize(sigA) < GetSize(sigD)) + std::swap(sigA, sigD); + } +endcode + match ffA + if !preAdd if param(dsp, \AREG).as_int() == 0 select ffA->type.in($dff) // DSP48E1 does not support clock inversion @@ -73,6 +153,9 @@ code sigA sigffAmuxY clock sigffAmuxY = sigA; sigA = std::move(A); } + else if (!preAdd) { + sigffAmuxY = SigSpec(); + } endcode match ffAmux @@ -91,6 +174,18 @@ match ffAmux optional endmatch +code ffA ffAmux ffAenpol ffAD ffADmux + // Move AD register to A if no pre-adder + if (!ffA && !preAdd && ffAD) { + ffA = ffAD; + ffAmux = ffADmux; + ffAenpol = ffADenpol; + + ffAD = nullptr; + ffADmux = nullptr; + } +endcode + match ffB if param(dsp, \BREG).as_int() == 0 select ffB->type.in($dff) From 2c32056990b9742839841f4cf3fa31d742cef472 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 14:10:12 -0700 Subject: [PATCH 188/356] Logging for ffAD --- passes/pmgen/xilinx_dsp.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 9587ed28a..65a4d5a11 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -177,6 +177,9 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffA) log(" ffA:%s", log_id(st.ffA)); + if (st.ffAD) + log(" ffAD:%s", log_id(st.ffAD)); + if (st.ffB) log(" ffB:%s", log_id(st.ffB)); From 8246062acfd3b294c59ce72a9dcc6513dc0d08bd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 14:36:10 -0700 Subject: [PATCH 189/356] Fix enable polarity --- passes/pmgen/xilinx_dsp.cc | 4 ++-- passes/pmgen/xilinx_dsp.pmg | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 65a4d5a11..d8213e02f 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -112,7 +112,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) A.replace(Q, D); if (st.ffAmux) { SigSpec Y = st.ffAmux->getPort("\\Y"); - SigSpec AB = st.ffAmux->getPort(st.ffAenpol ? "\\A" : "\\B"); + SigSpec AB = st.ffAmux->getPort(st.ffAenpol ? "\\B" : "\\A"); SigSpec S = st.ffAmux->getPort("\\S"); A.replace(Y, AB); cell->setPort("\\CEA2", st.ffAenpol ? S : pm.module->Not(NEW_ID, S)); @@ -130,7 +130,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) B.replace(Q, D); if (st.ffBmux) { SigSpec Y = st.ffBmux->getPort("\\Y"); - SigSpec AB = st.ffBmux->getPort(st.ffBenpol ? "\\A" : "\\B"); + SigSpec AB = st.ffBmux->getPort(st.ffBenpol ? "\\B" : "\\A"); SigSpec S = st.ffBmux->getPort("\\S"); B.replace(Y, AB); cell->setPort("\\CEB2", st.ffBenpol ? S : pm.module->Not(NEW_ID, S)); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 83963804b..f8bd26e8b 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -85,10 +85,10 @@ match ffADmux slice offset GetSize(port(ffADmux, \Y)) filter offset+GetSize(sigA) <= GetSize(port(ffADmux, \Y)) filter port(ffADmux, \Y).extract(offset, GetSize(sigA)) == sigA - choice BA {\B, \A} + choice AB {\A, \B} filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffADmux, \Y)) - filter port(ffADmux, BA).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY - define pol (BA == \B) + filter port(ffADmux, AB).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY + define pol (AB == \A) set ffADenpol pol optional endmatch @@ -166,10 +166,10 @@ match ffAmux slice offset GetSize(port(ffAmux, \Y)) filter offset+GetSize(sigA) <= GetSize(port(ffAmux, \Y)) filter port(ffAmux, \Y).extract(offset, GetSize(sigA)) == sigA - choice BA {\B, \A} + choice AB {\A, \B} filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffAmux, \Y)) - filter port(ffAmux, BA).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY - define pol (BA == \B) + filter port(ffAmux, AB).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY + define pol (AB == \A) set ffAenpol pol optional endmatch @@ -228,10 +228,10 @@ match ffBmux slice offset GetSize(port(ffBmux, \Y)) filter offset+GetSize(sigB) <= GetSize(port(ffBmux, \Y)) filter port(ffBmux, \Y).extract(offset, GetSize(sigB)) == sigB - choice BA {\B, \A} + choice AB {\A, \B} filter offset+GetSize(sigffBmuxY) <= GetSize(port(ffBmux, \Y)) - filter port(ffBmux, BA).extract(offset, GetSize(sigffBmuxY)) == sigffBmuxY - define pol (BA == \B) + filter port(ffBmux, AB).extract(offset, GetSize(sigffBmuxY)) == sigffBmuxY + define pol (AB == \A) set ffBenpol pol optional endmatch @@ -252,7 +252,7 @@ match ffMmux filter port(ffMmux, BA) == sigM.extract(0, GetSize(port(ffMmux, \Y))) // Remaining bits on sigM must not have any other users filter nusers(sigM.extract_end(GetSize(port(ffMmux, BA)))) <= 1 - define pol (BA == \B) + define pol (AB == \A) set ffMenpol pol optional endmatch @@ -348,15 +348,15 @@ match ffPmux select nusers(port(ffPmux, \Y)) == 2 filter GetSize(port(ffPmux, \Y)) >= GetSize(sigP) - choice BA {\B, \A} slice offset GetSize(port(ffPmux, \Y)) filter offset+GetSize(sigP) <= GetSize(port(ffPmux, \Y)) + choice BA {\B, \A} filter port(ffPmux, BA).extract(offset, GetSize(sigP)) == sigP define AB (BA == \B ? \A : \B) // keep-last-value net must have at least three users: ffPmux, ffP, downstream sink(s) filter nusers(port(ffPmux, AB)) >= 3 - define pol (BA == \B) + define pol (AB == \A) set ffPenpol pol set ffPoffset offset optional From 0d1d8b4d24d3cce071e7c7e3c6284ba2cb874bd0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 14:57:36 -0700 Subject: [PATCH 190/356] Fix macc and mul tests --- passes/pmgen/xilinx_dsp.pmg | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index f8bd26e8b..d91072868 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -300,6 +300,10 @@ code ffM clock sigM sigP reject; clock = c; } + // No enable mux possible without flop + else if (ffMmux) + reject; + sigP = sigM; endcode @@ -341,8 +345,11 @@ endcode match ffPmux if param(dsp, \PREG).as_int() == 0 - // new-value net must have exactly two users: dsp and ffP - if nusers(sigP) == 2 + // If ffMmux, new-value net must have exactly three users: ffMmux, ffM and ffPmux + if !ffMmux || nusers(sigP) == 3 + // Otherwise new-value net must have exactly two users: dsp and ffPmux + if ffMmux || nusers(sigP) == 2 + select ffPmux->type.in($mux) // ffPmux output must have two users: ffPmux and ffP.D select nusers(port(ffPmux, \Y)) == 2 @@ -383,7 +390,11 @@ endmatch match ffP if !ffP_enable if param(dsp, \PREG).as_int() == 0 - if nusers(sigP) == 2 + // If ffMmux, input net must have exactly three users: ffMmux, ffM and ffP + if !ffMmux || nusers(sigP) == 3 + // Otherwise input net must have exactly two users: dsp and ffP + if ffMmux || nusers(sigP) == 2 + select ffP->type.in($dff) // DSP48E1 does not support clock inversion select param(ffP, \CLK_POLARITY).as_bool() @@ -413,6 +424,9 @@ code ffP sigP clock sigP.replace(port(ffP, \D), port(ffP, \Q)); } + // No enable mux possible without flop + else if (ffPmux) + reject; endcode match postAddMux From ef56f8596fdd9753e93dbd654493497be8902691 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 15:11:41 -0700 Subject: [PATCH 191/356] Fine tune nusers when postAdd --- passes/pmgen/xilinx_dsp.pmg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index d91072868..7d943b16f 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -345,10 +345,10 @@ endcode match ffPmux if param(dsp, \PREG).as_int() == 0 - // If ffMmux, new-value net must have exactly three users: ffMmux, ffM and ffPmux - if !ffMmux || nusers(sigP) == 3 + // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux + if !ffMmux || postAdd || nusers(sigP) == 3 // Otherwise new-value net must have exactly two users: dsp and ffPmux - if ffMmux || nusers(sigP) == 2 + if (ffMmux && !postAdd) || nusers(sigP) == 2 select ffPmux->type.in($mux) // ffPmux output must have two users: ffPmux and ffP.D From 74eac766995237dec86d51778811cf186c68d851 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 15:32:26 -0700 Subject: [PATCH 192/356] Add support for DREG --- passes/pmgen/xilinx_dsp.cc | 13 ++++++++ passes/pmgen/xilinx_dsp.pmg | 59 +++++++++++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index d8213e02f..547073aa6 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -38,6 +38,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("ffAmux: %s\n", log_id(st.ffAmux, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); log("ffBmux: %s\n", log_id(st.ffBmux, "--")); + log("ffD: %s\n", log_id(st.ffD, "--")); + log("ffDmux: %s\n", log_id(st.ffDmux, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); log("ffM: %s\n", log_id(st.ffM, "--")); log("ffMmux: %s\n", log_id(st.ffMmux, "--")); @@ -141,6 +143,17 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) cell->setParam("\\BREG", 1); } + if (st.ffD) { + if (st.ffDmux) { + SigSpec S = st.ffDmux->getPort("\\S"); + cell->setPort("\\CED", st.ffBenpol ? S : pm.module->Not(NEW_ID, S)); + } + else + cell->setPort("\\CED", State::S1); + cell->setPort("\\D", st.sigD); + + cell->setParam("\\DREG", 1); + } if (st.ffM) { if (st.ffMmux) { SigSpec S = st.ffMmux->getPort("\\S"); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 7d943b16f..6cc42e2e1 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,9 +1,9 @@ pattern xilinx_dsp state clock -state sigA sigffAmuxY sigB sigffBmuxY sigC sigD sigM sigP +state sigA sigffAmuxY sigB sigffBmuxY sigC sigD sigffDmuxY sigM sigP state postAddAB postAddMuxAB -state ffAenpol ffADenpol ffBenpol ffMenpol ffPenpol +state ffAenpol ffADenpol ffBenpol ffDenpol ffMenpol ffPenpol state ffPoffset match dsp @@ -236,6 +236,61 @@ match ffBmux optional endmatch +match ffD + if param(dsp, \DREG).as_int() == 0 + select ffD->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ffD, \CLK_POLARITY).as_bool() + filter GetSize(port(ffD, \Q)) >= GetSize(sigD) + slice offset GetSize(port(ffD, \Q)) + filter offset+GetSize(sigD) <= GetSize(port(ffD, \Q)) + filter port(ffD, \Q).extract(offset, GetSize(sigD)) == sigD + optional +endmatch + +code sigD sigffDmuxY clock + if (ffD) { + for (auto b : port(ffD, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + + SigBit c = port(ffD, \CLK).as_bit(); + if (clock != SigBit() && c != clock) + reject; + clock = c; + + SigSpec D = sigD; + D.replace(port(ffD, \Q), port(ffD, \D)); + // Only search for ffBmux if ffB.Q has at + // least 3 users (ffB, dsp, ffBmux) and + // its ffB.D only has two (ffB, ffBmux) + if (nusers(sigD) >= 3 && nusers(D) == 2) + sigffDmuxY = sigD; + sigD = std::move(D); + } +endcode + +match ffDmux + if !sigffDmuxY.empty() + select ffDmux->type.in($mux) + index port(ffDmux, \Y) === port(ffD, \D) + filter GetSize(port(ffDmux, \Y)) >= GetSize(sigD) + slice offset GetSize(port(ffDmux, \Y)) + filter offset+GetSize(sigD) <= GetSize(port(ffDmux, \Y)) + filter port(ffDmux, \Y).extract(offset, GetSize(sigB)) == sigD + choice AB {\A, \B} + filter offset+GetSize(sigffDmuxY) <= GetSize(port(ffDmux, \Y)) + filter port(ffDmux, AB).extract(offset, GetSize(sigffDmuxY)) == sigffDmuxY + define pol (AB == \A) + set ffDenpol pol + optional +endmatch + +code sigD + if (ffDmux) + sigD.replace(port(ffDmux, \Y), port(ffDmux, ffDenpol ? \B : \A)); +endcode + match ffMmux if param(dsp, \MREG).as_int() == 0 if nusers(sigM) == 2 From 5344bfe637e0c8d527f94f615e4ed8704c358cf8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 15:46:15 -0700 Subject: [PATCH 193/356] Perform D replacement properly --- passes/pmgen/xilinx_dsp.cc | 13 +++++++++++-- passes/pmgen/xilinx_dsp.pmg | 5 ----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 547073aa6..ba8a1de05 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -144,13 +144,22 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) cell->setParam("\\BREG", 1); } if (st.ffD) { + SigSpec D_ = cell->getPort("\\D"); + SigSpec D = st.ffB->getPort("\\D"); + SigSpec Q = st.ffB->getPort("\\Q"); + D_.replace(Q, D); + if (st.ffDmux) { + SigSpec Y = st.ffDmux->getPort("\\Y"); + SigSpec AB = st.ffDmux->getPort(st.ffDenpol ? "\\B" : "\\A"); SigSpec S = st.ffDmux->getPort("\\S"); - cell->setPort("\\CED", st.ffBenpol ? S : pm.module->Not(NEW_ID, S)); + D_.replace(Y, AB); + + cell->setPort("\\CED", st.ffDenpol ? S : pm.module->Not(NEW_ID, S)); } else cell->setPort("\\CED", State::S1); - cell->setPort("\\D", st.sigD); + cell->setPort("\\D", D_); cell->setParam("\\DREG", 1); } diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 6cc42e2e1..9e4738c88 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -286,11 +286,6 @@ match ffDmux optional endmatch -code sigD - if (ffDmux) - sigD.replace(port(ffDmux, \Y), port(ffDmux, ffDenpol ? \B : \A)); -endcode - match ffMmux if param(dsp, \MREG).as_int() == 0 if nusers(sigM) == 2 From b69512a5b90a854a96b6e25bf4ccc567a7f89ad2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 15:51:21 -0700 Subject: [PATCH 194/356] Fix ffP just like ffPmux --- passes/pmgen/xilinx_dsp.pmg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 9e4738c88..7be841ff3 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -440,10 +440,10 @@ endmatch match ffP if !ffP_enable if param(dsp, \PREG).as_int() == 0 - // If ffMmux, input net must have exactly three users: ffMmux, ffM and ffP - if !ffMmux || nusers(sigP) == 3 - // Otherwise input net must have exactly two users: dsp and ffP - if ffMmux || nusers(sigP) == 2 + // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux + if !ffMmux || postAdd || nusers(sigP) == 3 + // Otherwise new-value net must have exactly two users: dsp and ffPmux + if (ffMmux && !postAdd) || nusers(sigP) == 2 select ffP->type.in($dff) // DSP48E1 does not support clock inversion From 6a9205280f4c574db3a779e2f057e8649fe35356 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 18:40:11 -0700 Subject: [PATCH 195/356] Use unextend lambda --- passes/pmgen/xilinx_dsp.pmg | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 7be841ff3..3aab807bd 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,5 +1,6 @@ pattern xilinx_dsp +state > unextend state clock state sigA sigffAmuxY sigB sigffBmuxY sigC sigD sigffDmuxY sigM sigP state postAddAB postAddMuxAB @@ -10,29 +11,26 @@ match dsp select dsp->type.in(\DSP48E1) endmatch -code sigA sigffAmuxY sigB sigffBmuxY sigD sigM - sigA = port(dsp, \A); - int i; - for (i = GetSize(sigA)-1; i > 0; i--) - if (sigA[i] != sigA[i-1]) - break; - // Do not remove non-const sign bit - if (sigA[i].wire) - ++i; - sigA.remove(i, GetSize(sigA)-i); - sigB = port(dsp, \B); - for (i = GetSize(sigB)-1; i > 0; i--) - if (sigB[i] != sigB[i-1]) - break; - // Do not remove non-const sign bit - if (sigB[i].wire) - ++i; - sigB.remove(i, GetSize(sigB)-i); +code unextend sigA sigffAmuxY sigB sigffBmuxY sigC sigD sigffDmuxY sigM + unextend = [](const SigSpec &sig, bool keep_sign) { + int i; + for (i = GetSize(sig)-1; i > 0; i--) + if (sig[i] != sig[i-1]) + break; + // Do not remove non-const sign bit + if (!keep_sign && sig[i].wire) + ++i; + return sig.extract(0, i); + }; + sigA = unextend(port(dsp, \A), false); + sigB = unextend(port(dsp, \B), false); + sigC = dsp->connections_.at(\C, SigSpec()); sigD = dsp->connections_.at(\D, SigSpec()); SigSpec P = port(dsp, \P); // Only care about those bits that are used + int i; for (i = 0; i < GetSize(P); i++) { if (nusers(P[i]) <= 1) break; @@ -44,6 +42,7 @@ code sigA sigffAmuxY sigB sigffBmuxY sigD sigM sigffAmuxY = SigSpec(); sigffBmuxY = SigSpec(); + sigffDmuxY = SigSpec(); endcode match ffAD From 74a5c802f70c181520ce762376e9673a5f6f6465 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 21:01:36 -0700 Subject: [PATCH 196/356] Pack CREG --- passes/pmgen/xilinx_dsp.cc | 53 +++++++++++++++++----- passes/pmgen/xilinx_dsp.pmg | 89 +++++++++++++++++++++++++++++-------- 2 files changed, 111 insertions(+), 31 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index ba8a1de05..10308de57 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -38,6 +38,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("ffAmux: %s\n", log_id(st.ffAmux, "--")); log("ffB: %s\n", log_id(st.ffB, "--")); log("ffBmux: %s\n", log_id(st.ffBmux, "--")); + log("ffC: %s\n", log_id(st.ffC, "--")); + log("ffCmux: %s\n", log_id(st.ffCmux, "--")); log("ffD: %s\n", log_id(st.ffD, "--")); log("ffDmux: %s\n", log_id(st.ffDmux, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); @@ -53,7 +55,6 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) Cell *cell = st.dsp; bit_to_driver.insert(std::make_pair(cell->getPort("\\P")[17], cell)); - SigSpec C = st.sigC; SigSpec P = st.sigP; if (st.preAdd) { @@ -91,15 +92,21 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) opmode[4] = st.postAddMux->getPort("\\S"); pm.autoremove(st.postAddMux); } - else if (st.ffP && C == P) { - C = SigSpec(); + else if (st.ffP && st.sigC == P) opmode[4] = State::S0; - } else opmode[4] = State::S1; opmode[6] = State::S0; opmode[5] = State::S1; + if (opmode[4] != State::S0) { + if (st.postAddMuxAB == "\\A") + st.sigC.extend_u0(48, st.postAdd->getParam("\\B_SIGNED").as_bool()); + else + st.sigC.extend_u0(48, st.postAdd->getParam("\\A_SIGNED").as_bool()); + cell->setPort("\\C", st.sigC); + } + pm.autoremove(st.postAdd); } @@ -143,10 +150,30 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) cell->setParam("\\BREG", 1); } + if (st.ffC) { + SigSpec C = cell->getPort("\\C"); + SigSpec D = st.ffC->getPort("\\D"); + SigSpec Q = st.ffC->getPort("\\Q"); + C.replace(Q, D); + + if (st.ffCmux) { + SigSpec Y = st.ffCmux->getPort("\\Y"); + SigSpec AB = st.ffCmux->getPort(st.ffCenpol ? "\\B" : "\\A"); + SigSpec S = st.ffCmux->getPort("\\S"); + C.replace(Y, AB); + + cell->setPort("\\CEC", st.ffCenpol ? S : pm.module->Not(NEW_ID, S)); + } + else + cell->setPort("\\CEC", State::S1); + cell->setPort("\\C", C); + + cell->setParam("\\CREG", 1); + } if (st.ffD) { SigSpec D_ = cell->getPort("\\D"); - SigSpec D = st.ffB->getPort("\\D"); - SigSpec Q = st.ffB->getPort("\\Q"); + SigSpec D = st.ffD->getPort("\\D"); + SigSpec Q = st.ffD->getPort("\\Q"); D_.replace(Q, D); if (st.ffDmux) { @@ -205,6 +232,12 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffB) log(" ffB:%s", log_id(st.ffB)); + if (st.ffC) + log(" ffC:%s", log_id(st.ffC)); + + if (st.ffD) + log(" ffD:%s", log_id(st.ffD)); + if (st.ffM) log(" ffM:%s", log_id(st.ffM)); @@ -214,12 +247,6 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("\n"); } - if (!C.empty()) { - if (GetSize(C) < 48) - C.extend_u0(48, true); - cell->setPort("\\C", C); - } - if (GetSize(P) < 48) P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); cell->setPort("\\P", P); @@ -265,6 +292,8 @@ struct XilinxDspPass : public Pass { for (auto cell : module->cells()) { if (cell->type != "\\DSP48E1") continue; + if (cell->parameters.at("\\CREG", State::S1).as_bool()) + continue; SigSpec &opmode = cell->connections_.at("\\OPMODE"); if (opmode.extract(4,3) != Const::from_string("011")) continue; diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 3aab807bd..6b981bc13 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,29 +1,29 @@ pattern xilinx_dsp -state > unextend +state > unextend state clock -state sigA sigffAmuxY sigB sigffBmuxY sigC sigD sigffDmuxY sigM sigP +state sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM sigP state postAddAB postAddMuxAB -state ffAenpol ffADenpol ffBenpol ffDenpol ffMenpol ffPenpol +state ffAenpol ffADenpol ffBenpol ffCenpol ffDenpol ffMenpol ffPenpol state ffPoffset match dsp select dsp->type.in(\DSP48E1) endmatch -code unextend sigA sigffAmuxY sigB sigffBmuxY sigC sigD sigffDmuxY sigM - unextend = [](const SigSpec &sig, bool keep_sign) { +code unextend sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM + unextend = [](const SigSpec &sig) { int i; for (i = GetSize(sig)-1; i > 0; i--) if (sig[i] != sig[i-1]) break; // Do not remove non-const sign bit - if (!keep_sign && sig[i].wire) + if (sig[i].wire) ++i; return sig.extract(0, i); }; - sigA = unextend(port(dsp, \A), false); - sigB = unextend(port(dsp, \B), false); + sigA = unextend(port(dsp, \A)); + sigB = unextend(port(dsp, \B)); sigC = dsp->connections_.at(\C, SigSpec()); sigD = dsp->connections_.at(\D, SigSpec()); @@ -42,6 +42,7 @@ code unextend sigA sigffAmuxY sigB sigffBmuxY sigC sigD sigffDmuxY sigM sigffAmuxY = SigSpec(); sigffBmuxY = SigSpec(); + sigffCmuxY = SigSpec(); sigffDmuxY = SigSpec(); endcode @@ -260,9 +261,9 @@ code sigD sigffDmuxY clock SigSpec D = sigD; D.replace(port(ffD, \Q), port(ffD, \D)); - // Only search for ffBmux if ffB.Q has at - // least 3 users (ffB, dsp, ffBmux) and - // its ffB.D only has two (ffB, ffBmux) + // Only search for ffDmux if ffD.Q has at + // least 3 users (ffD, dsp, ffDmux) and + // its ffD.D only has two (ffD, ffDmux) if (nusers(sigD) >= 3 && nusers(D) == 2) sigffDmuxY = sigD; sigD = std::move(D); @@ -276,7 +277,7 @@ match ffDmux filter GetSize(port(ffDmux, \Y)) >= GetSize(sigD) slice offset GetSize(port(ffDmux, \Y)) filter offset+GetSize(sigD) <= GetSize(port(ffDmux, \Y)) - filter port(ffDmux, \Y).extract(offset, GetSize(sigB)) == sigD + filter port(ffDmux, \Y).extract(offset, GetSize(sigD)) == sigD choice AB {\A, \B} filter offset+GetSize(sigffDmuxY) <= GetSize(port(ffDmux, \Y)) filter port(ffDmux, AB).extract(offset, GetSize(sigffDmuxY)) == sigffDmuxY @@ -290,17 +291,17 @@ match ffMmux if nusers(sigM) == 2 select ffMmux->type.in($mux) choice BA {\B, \A} - // new-value net must have exactly two users: dsp and ffM + // new-value net must have exactly two users: dsp and ffMmux select nusers(port(ffMmux, BA)) == 2 define AB (BA == \B ? \A : \B) // keep-last-value net must have at least three users: ffMmux, ffM, downstream sink(s) select nusers(port(ffMmux, AB)) >= 3 // ffMmux output must have two users: ffMmux and ffM.D select nusers(port(ffMmux, \Y)) == 2 - filter GetSize(port(ffMmux, \Y)) <= GetSize(sigM) - filter port(ffMmux, BA) == sigM.extract(0, GetSize(port(ffMmux, \Y))) + filter GetSize(unextend(port(ffMmux, BA))) <= GetSize(sigM) + filter unextend(port(ffMmux, BA)) == sigM.extract(0, GetSize(unextend(port(ffMmux, BA)))) // Remaining bits on sigM must not have any other users - filter nusers(sigM.extract_end(GetSize(port(ffMmux, BA)))) <= 1 + filter nusers(sigM.extract_end(GetSize(unextend(port(ffMmux, BA))))) <= 1 define pol (AB == \A) set ffMenpol pol optional @@ -367,9 +368,9 @@ match postAdd select nusers(port(postAdd, AB)) <= 3 filter ffMmux || nusers(port(postAdd, AB)) == 2 filter !ffMmux || nusers(port(postAdd, AB)) == 3 - filter GetSize(port(postAdd, AB)) <= GetSize(sigP) - filter port(postAdd, AB) == sigP.extract(0, GetSize(port(postAdd, AB))) - filter nusers(sigP.extract_end(GetSize(port(postAdd, AB)))) <= 1 + filter GetSize(unextend(port(postAdd, AB))) <= GetSize(sigP) + filter unextend(port(postAdd, AB)) == sigP.extract(0, GetSize(unextend(port(postAdd, AB)))) + filter nusers(sigP.extract_end(GetSize(unextend(port(postAdd, AB))))) <= 1 set postAddAB AB optional endmatch @@ -495,6 +496,56 @@ code sigC sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A); endcode +match ffC + if param(dsp, \CREG).as_int() == 0 + select ffC->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ffC, \CLK_POLARITY).as_bool() + filter GetSize(port(ffC, \Q)) >= GetSize(sigD) + slice offset GetSize(port(ffC, \Q)) + filter offset+GetSize(sigC) <= GetSize(port(ffC, \Q)) + filter port(ffC, \Q).extract(offset, GetSize(sigC)) == sigC + optional +endmatch + +code sigC sigffCmuxY clock + if (ffC) { + for (auto b : port(ffC, \Q)) + if (b.wire->get_bool_attribute(\keep)) + reject; + + SigBit c = port(ffC, \CLK).as_bit(); + if (clock != SigBit() && c != clock) + reject; + clock = c; + + SigSpec C = sigC; + C.replace(port(ffC, \Q), port(ffC, \D)); + // Only search for ffCmux if ffC.Q has at + // least 3 users (ffC, dsp, ffCmux) and + // its ffC.D only has two (ffC, ffCmux) + if (nusers(sigC) >= 3 && nusers(C) == 2) + sigffCmuxY = sigC; + sigC = std::move(C); + } +endcode + +match ffCmux + if !sigffCmuxY.empty() + select ffCmux->type.in($mux) + index port(ffCmux, \Y) === port(ffC, \D) + filter GetSize(port(ffCmux, \Y)) >= GetSize(sigC) + slice offset GetSize(port(ffCmux, \Y)) + filter offset+GetSize(sigC) <= GetSize(port(ffCmux, \Y)) + filter port(ffCmux, \Y).extract(offset, GetSize(sigC)) == sigC + choice AB {\A, \B} + filter offset+GetSize(sigffCmuxY) <= GetSize(port(ffCmux, \Y)) + filter port(ffCmux, AB).extract(offset, GetSize(sigffCmuxY)) == sigffCmuxY + define pol (AB == \A) + set ffCenpol pol + optional +endmatch + code accept; endcode From e68507a71603553426a338bcffb0eccb1653436f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 6 Sep 2019 23:19:03 -0700 Subject: [PATCH 197/356] Update macc test --- tests/xilinx/macc.v | 66 +++++++++++++++++++++++--------------------- tests/xilinx/macc.ys | 18 +++++------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/tests/xilinx/macc.v b/tests/xilinx/macc.v index bae63b5a4..0bb673316 100644 --- a/tests/xilinx/macc.v +++ b/tests/xilinx/macc.v @@ -1,37 +1,41 @@ // Signed 40-bit streaming accumulator with 16-bit inputs // File: HDL_Coding_Techniques/multipliers/multipliers4.v // -module macc # (parameter SIZEIN = /*16*/7, SIZEOUT = 40) - (input clk, ce, sload, - input signed [SIZEIN-1:0] a, b, - output signed [SIZEOUT-1:0] accum_out); - // Declare registers for intermediate values - reg signed [SIZEIN-1:0] a_reg, b_reg; - reg sload_reg; - reg signed [2*SIZEIN:0] mult_reg; - reg signed [SIZEOUT-1:0] adder_out, old_result; - always @(adder_out or sload_reg) begin - //if (sload_reg) - //old_result <= 0; - //else - // 'sload' is now active (=low) and opens the accumulation loop. - // The accumulator takes the next multiplier output in - // the same cycle. - old_result <= adder_out; - a_reg <= a; - b_reg <= b; - end +// Source: +// https://www.xilinx.com/support/documentation/sw_manuals/xilinx2014_2/ug901-vivado-synthesis.pdf p.90 +// +module macc # (parameter SIZEIN = 16, SIZEOUT = 40) ( + input clk, ce, sload, + input signed [SIZEIN-1:0] a, b, + output signed [SIZEOUT-1:0] accum_out +); +// Declare registers for intermediate values +reg signed [SIZEIN-1:0] a_reg, b_reg; +reg sload_reg; +reg signed [2*SIZEIN-1:0] mult_reg; +reg signed [SIZEOUT-1:0] adder_out, old_result; +always @* /*(adder_out or sload_reg)*/ begin // Modification necessary to fix sim/synth mismatch + if (sload_reg) + old_result <= 0; + else + // 'sload' is now active (=low) and opens the accumulation loop. + // The accumulator takes the next multiplier output in + // the same cycle. + old_result <= adder_out; +end - always @(posedge clk) - //if (ce) - begin - mult_reg <= a_reg * b_reg; - sload_reg <= sload; - // Store accumulation result into a register - adder_out <= old_result + mult_reg; - end +always @(posedge clk) + if (ce) + begin + a_reg <= a; + b_reg <= b; + mult_reg <= a_reg * b_reg; + sload_reg <= sload; + // Store accumulation result into a register + adder_out <= old_result + mult_reg; + end - // Output accumulation result - assign accum_out = adder_out; + // Output accumulation result + assign accum_out = adder_out; -endmodule // macc +endmodule diff --git a/tests/xilinx/macc.ys b/tests/xilinx/macc.ys index 62b69f4d2..de408162c 100644 --- a/tests/xilinx/macc.ys +++ b/tests/xilinx/macc.ys @@ -1,17 +1,13 @@ read_verilog macc.v proc -hierarchy -top macc -equiv_opt -run :restore -map +/xilinx/cells_sim.v synth_xilinx # equivalency check - -#equiv_miter -trigger miter equiv -#sat -verify -prove-asserts -tempinduct -show-inputs -show-outputs miter - -#equiv_opt -assert -run :prove -map +/xilinx/cells_sim.v synth_xilinx # equivalency check -#miter -equiv -flatten -make_assert -make_outputs gold gate miter -#sat -set-init-zero -verify -prove-asserts -seq 10 -show-inputs -show-outputs miter - +hierarchy -auto-top +#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx ### TODO +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -seq 10 -show-inputs -show-outputs miter design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd macc # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG +select -assert-count 1 t:FDRE select -assert-count 1 t:DSP48E1 -select -assert-none t:BUFG t:DSP48E1 %% t:* %D +select -assert-none t:BUFG t:FDRE t:DSP48E1 %% t:* %D From 04bc287271354d3a1770ae7a9f8f1de9341b9253 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 15:51:14 -0700 Subject: [PATCH 198/356] Refactor using subpattern in_dffe --- passes/pmgen/xilinx_dsp.pmg | 404 ++++++++++++++---------------------- 1 file changed, 155 insertions(+), 249 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 6b981bc13..e611bfb3b 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -7,11 +7,21 @@ state postAddAB postAddMuxAB state ffAenpol ffADenpol ffBenpol ffCenpol ffDenpol ffMenpol ffPenpol state ffPoffset +state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux + +// subpattern +state dffQ +state dffenpol_ +udata dffD +udata dffclock +udata dff dffmux +udata dffenpol + match dsp select dsp->type.in(\DSP48E1) endmatch -code unextend sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM +code unextend sigA sigB sigC sigD sigM unextend = [](const SigSpec &sig) { int i; for (i = GetSize(sig)-1; i > 0; i--) @@ -39,60 +49,24 @@ code unextend sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY si log_assert(nusers(P.extract_end(i)) <= 1); //if (GetSize(sigM) <= 10) // reject; - - sigffAmuxY = SigSpec(); - sigffBmuxY = SigSpec(); - sigffCmuxY = SigSpec(); - sigffDmuxY = SigSpec(); endcode -match ffAD - if param(dsp, \ADREG).as_int() == 0 - select ffAD->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffAD, \CLK_POLARITY).as_bool() - filter GetSize(port(ffAD, \Q)) >= GetSize(sigA) - slice offset GetSize(port(ffAD, \Q)) - filter offset+GetSize(sigA) <= GetSize(port(ffAD, \Q)) - filter port(ffAD, \Q).extract(offset, GetSize(sigA)) == sigA - optional -endmatch - -code sigA sigffAmuxY clock - if (ffAD) { - for (auto b : port(ffAD, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - clock = port(ffAD, \CLK).as_bit(); - - SigSpec A = sigA; - A.replace(port(ffAD, \Q), port(ffAD, \D)); - // Only search for ffAmux if ffA.Q has at - // least 3 users (ffA, dsp, ffAmux) and - // its ffA.D only has two (ffA, ffAmux) - if (nusers(sigA) >= 3 && nusers(A) == 2) - sigffAmuxY = sigA; - sigA = std::move(A); +code dffQ ffAD ffADmux ffADenpol sigA clock + if (param(dsp, \ADREG).as_int() == 0) { + dffQ = sigA; + subpattern(in_dffe); + if (dff) { + ffAD = dff; + clock = dffclock; + if (dffmux) { + ffADmux = dffmux; + ffADenpol = dffenpol; + } + sigA = dffD; + } } endcode -match ffADmux - if !sigffAmuxY.empty() - select ffADmux->type.in($mux) - index port(ffADmux, \Y) === port(ffAD, \D) - filter GetSize(port(ffADmux, \Y)) >= GetSize(sigA) - slice offset GetSize(port(ffADmux, \Y)) - filter offset+GetSize(sigA) <= GetSize(port(ffADmux, \Y)) - filter port(ffADmux, \Y).extract(offset, GetSize(sigA)) == sigA - choice AB {\A, \B} - filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffADmux, \Y)) - filter port(ffADmux, AB).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY - define pol (AB == \A) - set ffADenpol pol - optional -endmatch - match preAdd if sigD.empty() || sigD.is_fully_zero() // Ensure that preAdder not already used @@ -123,169 +97,66 @@ code sigA sigD } endcode -match ffA - if !preAdd - if param(dsp, \AREG).as_int() == 0 - select ffA->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffA, \CLK_POLARITY).as_bool() - filter GetSize(port(ffA, \Q)) >= GetSize(sigA) - slice offset GetSize(port(ffA, \Q)) - filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) - filter port(ffA, \Q).extract(offset, GetSize(sigA)) == sigA - optional -endmatch - -code sigA sigffAmuxY clock - if (ffA) { - for (auto b : port(ffA, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - clock = port(ffA, \CLK).as_bit(); - - SigSpec A = sigA; - A.replace(port(ffA, \Q), port(ffA, \D)); - // Only search for ffAmux if ffA.Q has at - // least 3 users (ffA, dsp, ffAmux) and - // its ffA.D only has two (ffA, ffAmux) - if (nusers(sigA) >= 3 && nusers(A) == 2) - sigffAmuxY = sigA; - sigA = std::move(A); +code dffQ ffA ffAmux ffAenpol sigA clock ffAD ffADmux ffADenpol + // Only search for ffA if there was a pre-adder + // (otherwise ffA would have been matched as ffAD) + if (preAdd) { + if (param(dsp, \AREG).as_int() == 0) { + dffQ = sigA; + subpattern(in_dffe); + if (dff) { + ffA = dff; + clock = dffclock; + if (dffmux) { + ffAmux = dffmux; + ffAenpol = dffenpol; + } + sigA = dffD; + } + } } - else if (!preAdd) { - sigffAmuxY = SigSpec(); - } -endcode - -match ffAmux - if !sigffAmuxY.empty() - select ffAmux->type.in($mux) - index port(ffAmux, \Y) === port(ffA, \D) - filter GetSize(port(ffAmux, \Y)) >= GetSize(sigA) - slice offset GetSize(port(ffAmux, \Y)) - filter offset+GetSize(sigA) <= GetSize(port(ffAmux, \Y)) - filter port(ffAmux, \Y).extract(offset, GetSize(sigA)) == sigA - choice AB {\A, \B} - filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffAmux, \Y)) - filter port(ffAmux, AB).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY - define pol (AB == \A) - set ffAenpol pol - optional -endmatch - -code ffA ffAmux ffAenpol ffAD ffADmux - // Move AD register to A if no pre-adder - if (!ffA && !preAdd && ffAD) { - ffA = ffAD; - ffAmux = ffADmux; + // And if there wasn't a pre-adder, + // move AD register to A + else if (ffAD) { + log_assert(!ffA && !ffAmux); + std::swap(ffA, ffAD); + std::swap(ffAmux, ffADmux); ffAenpol = ffADenpol; - - ffAD = nullptr; - ffADmux = nullptr; } endcode -match ffB - if param(dsp, \BREG).as_int() == 0 - select ffB->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffB, \CLK_POLARITY).as_bool() - filter GetSize(port(ffB, \Q)) >= GetSize(sigB) - slice offset GetSize(port(ffB, \Q)) - filter offset+GetSize(sigB) <= GetSize(port(ffB, \Q)) - filter port(ffB, \Q).extract(offset, GetSize(sigB)) == sigB - optional -endmatch - -code sigB sigffBmuxY clock - if (ffB) { - for (auto b : port(ffB, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffB, \CLK).as_bit(); - if (clock != SigBit() && c != clock) - reject; - clock = c; - - SigSpec B = sigB; - B.replace(port(ffB, \Q), port(ffB, \D)); - // Only search for ffBmux if ffB.Q has at - // least 3 users (ffB, dsp, ffBmux) and - // its ffB.D only has two (ffB, ffBmux) - if (nusers(sigB) >= 3 && nusers(B) == 2) - sigffBmuxY = sigB; - sigB = std::move(B); +code dffQ ffB ffBmux ffBenpol sigB clock + if (param(dsp, \BREG).as_int() == 0) { + dffQ = sigB; + subpattern(in_dffe); + if (dff) { + ffB = dff; + clock = dffclock; + if (dffmux) { + ffBmux = dffmux; + ffBenpol = dffenpol; + } + sigB = dffD; + } } endcode -match ffBmux - if !sigffBmuxY.empty() - select ffBmux->type.in($mux) - index port(ffBmux, \Y) === port(ffB, \D) - filter GetSize(port(ffBmux, \Y)) >= GetSize(sigB) - slice offset GetSize(port(ffBmux, \Y)) - filter offset+GetSize(sigB) <= GetSize(port(ffBmux, \Y)) - filter port(ffBmux, \Y).extract(offset, GetSize(sigB)) == sigB - choice AB {\A, \B} - filter offset+GetSize(sigffBmuxY) <= GetSize(port(ffBmux, \Y)) - filter port(ffBmux, AB).extract(offset, GetSize(sigffBmuxY)) == sigffBmuxY - define pol (AB == \A) - set ffBenpol pol - optional -endmatch - -match ffD - if param(dsp, \DREG).as_int() == 0 - select ffD->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffD, \CLK_POLARITY).as_bool() - filter GetSize(port(ffD, \Q)) >= GetSize(sigD) - slice offset GetSize(port(ffD, \Q)) - filter offset+GetSize(sigD) <= GetSize(port(ffD, \Q)) - filter port(ffD, \Q).extract(offset, GetSize(sigD)) == sigD - optional -endmatch - -code sigD sigffDmuxY clock - if (ffD) { - for (auto b : port(ffD, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffD, \CLK).as_bit(); - if (clock != SigBit() && c != clock) - reject; - clock = c; - - SigSpec D = sigD; - D.replace(port(ffD, \Q), port(ffD, \D)); - // Only search for ffDmux if ffD.Q has at - // least 3 users (ffD, dsp, ffDmux) and - // its ffD.D only has two (ffD, ffDmux) - if (nusers(sigD) >= 3 && nusers(D) == 2) - sigffDmuxY = sigD; - sigD = std::move(D); +code dffQ ffD ffDmux ffDenpol sigD clock + if (param(dsp, \DREG).as_int() == 0) { + dffQ = sigD; + subpattern(in_dffe); + if (dff) { + ffD = dff; + clock = dffclock; + if (dffmux) { + ffDmux = dffmux; + ffDenpol = dffenpol; + } + sigD = dffD; + } } endcode -match ffDmux - if !sigffDmuxY.empty() - select ffDmux->type.in($mux) - index port(ffDmux, \Y) === port(ffD, \D) - filter GetSize(port(ffDmux, \Y)) >= GetSize(sigD) - slice offset GetSize(port(ffDmux, \Y)) - filter offset+GetSize(sigD) <= GetSize(port(ffDmux, \Y)) - filter port(ffDmux, \Y).extract(offset, GetSize(sigD)) == sigD - choice AB {\A, \B} - filter offset+GetSize(sigffDmuxY) <= GetSize(port(ffDmux, \Y)) - filter port(ffDmux, AB).extract(offset, GetSize(sigffDmuxY)) == sigffDmuxY - define pol (AB == \A) - set ffDenpol pol - optional -endmatch - match ffMmux if param(dsp, \MREG).as_int() == 0 if nusers(sigM) == 2 @@ -496,56 +367,91 @@ code sigC sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A); endcode -match ffC - if param(dsp, \CREG).as_int() == 0 - select ffC->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffC, \CLK_POLARITY).as_bool() - filter GetSize(port(ffC, \Q)) >= GetSize(sigD) - slice offset GetSize(port(ffC, \Q)) - filter offset+GetSize(sigC) <= GetSize(port(ffC, \Q)) - filter port(ffC, \Q).extract(offset, GetSize(sigC)) == sigC - optional -endmatch - -code sigC sigffCmuxY clock - if (ffC) { - for (auto b : port(ffC, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffC, \CLK).as_bit(); - if (clock != SigBit() && c != clock) - reject; - clock = c; - - SigSpec C = sigC; - C.replace(port(ffC, \Q), port(ffC, \D)); - // Only search for ffCmux if ffC.Q has at - // least 3 users (ffC, dsp, ffCmux) and - // its ffC.D only has two (ffC, ffCmux) - if (nusers(sigC) >= 3 && nusers(C) == 2) - sigffCmuxY = sigC; - sigC = std::move(C); +code dffQ ffC ffCmux ffCenpol sigC clock + if (param(dsp, \CREG).as_int() == 0) { + dffQ = sigC; + subpattern(in_dffe); + if (dff) { + ffC = dff; + clock = dffclock; + if (dffmux) { + ffCmux = dffmux; + ffCenpol = dffenpol; + } + sigC = dffD; + } } endcode -match ffCmux - if !sigffCmuxY.empty() - select ffCmux->type.in($mux) - index port(ffCmux, \Y) === port(ffC, \D) - filter GetSize(port(ffCmux, \Y)) >= GetSize(sigC) - slice offset GetSize(port(ffCmux, \Y)) - filter offset+GetSize(sigC) <= GetSize(port(ffCmux, \Y)) - filter port(ffCmux, \Y).extract(offset, GetSize(sigC)) == sigC - choice AB {\A, \B} - filter offset+GetSize(sigffCmuxY) <= GetSize(port(ffCmux, \Y)) - filter port(ffCmux, AB).extract(offset, GetSize(sigffCmuxY)) == sigffCmuxY - define pol (AB == \A) - set ffCenpol pol - optional -endmatch - code accept; endcode + +subpattern in_dffe +arg dffQ clock dffenpol_ + +code + dff = nullptr; + dffmux = nullptr; +endcode + +match ff + select ff->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ff, \CLK_POLARITY).as_bool() + filter GetSize(port(ff, \Q)) >= GetSize(dffQ) + slice offset GetSize(port(ff, \Q)) + filter offset+GetSize(dffQ) <= GetSize(port(ff, \Q)) + filter port(ff, \Q).extract(offset, GetSize(dffQ)) == dffQ + semioptional +endmatch + +code dffQ + if (ff) { + for (auto b : dffQ) + if (b.wire->get_bool_attribute(\keep)) + reject; + + if (clock != SigBit()) { + if (port(ff, \CLK) != clock) + reject; + } + else + dffclock = port(ff, \CLK); + + dff = ff; + dffD = dffQ; + dffD.replace(port(ff, \Q), port(ff, \D)); + // Only search for ffmux if ff.Q has at + // least 3 users (ff, dsp, ffmux) and + // its ff.D only has two (ff, ffmux) + if (!(nusers(dffQ) >= 3 && nusers(dffD) == 2)) + dffQ = SigSpec(); + } + else + dffQ = SigSpec(); +endcode + +match ffmux + if !dffQ.empty() + select ffmux->type.in($mux) + index port(ffmux, \Y) === port(ff, \D) + filter GetSize(port(ffmux, \Y)) >= GetSize(dffD) + slice offset GetSize(port(ffmux, \Y)) + filter offset+GetSize(dffD) <= GetSize(port(ffmux, \Y)) + filter port(ffmux, \Y).extract(offset, GetSize(dffD)) == dffD + choice AB {\A, \B} + filter offset+GetSize(dffQ) <= GetSize(port(ffmux, \Y)) + filter port(ffmux, AB).extract(offset, GetSize(dffQ)) == dffQ + define pol (AB == \A) + set dffenpol_ pol + semioptional +endmatch + +code + if (ffmux) { + dffmux = ffmux; + dffenpol = dffenpol_; + dffD = port(ffmux, dffenpol ? \B : \A); + } +endcode From 5f8f0e13833ef052adb4d2d3deb8e965734127fd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 15:59:10 -0700 Subject: [PATCH 199/356] Tidy up --- passes/pmgen/xilinx_dsp.pmg | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index e611bfb3b..afbd6ef81 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -390,11 +390,6 @@ endcode subpattern in_dffe arg dffQ clock dffenpol_ -code - dff = nullptr; - dffmux = nullptr; -endcode - match ff select ff->type.in($dff) // DSP48E1 does not support clock inversion @@ -428,8 +423,10 @@ code dffQ if (!(nusers(dffQ) >= 3 && nusers(dffD) == 2)) dffQ = SigSpec(); } - else + else { + dff = nullptr; dffQ = SigSpec(); + } endcode match ffmux @@ -454,4 +451,6 @@ code dffenpol = dffenpol_; dffD = port(ffmux, dffenpol ? \B : \A); } + else + dffmux = nullptr; endcode From 1df9c5d277aa70d4dc1088d0030a756f342bb8fb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 16:07:40 -0700 Subject: [PATCH 200/356] Oops --- passes/pmgen/xilinx_dsp.pmg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index afbd6ef81..f01eeb245 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -411,8 +411,7 @@ code dffQ if (port(ff, \CLK) != clock) reject; } - else - dffclock = port(ff, \CLK); + dffclock = port(ff, \CLK); dff = ff; dffD = dffQ; From 6348f9512c5dd9de9529a5e6cac58ad46a742309 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 16:45:38 -0700 Subject: [PATCH 201/356] Rename --- passes/pmgen/xilinx_dsp.pmg | 54 ++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index f01eeb245..3185c4641 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -10,8 +10,8 @@ state ffPoffset state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux // subpattern -state dffQ -state dffenpol_ +state argQ +state ffenpol udata dffD udata dffclock udata dff dffmux @@ -51,9 +51,9 @@ code unextend sigA sigB sigC sigD sigM // reject; endcode -code dffQ ffAD ffADmux ffADenpol sigA clock +code argQ ffAD ffADmux ffADenpol sigA clock if (param(dsp, \ADREG).as_int() == 0) { - dffQ = sigA; + argQ = sigA; subpattern(in_dffe); if (dff) { ffAD = dff; @@ -97,12 +97,12 @@ code sigA sigD } endcode -code dffQ ffA ffAmux ffAenpol sigA clock ffAD ffADmux ffADenpol +code argQ ffA ffAmux ffAenpol sigA clock ffAD ffADmux ffADenpol // Only search for ffA if there was a pre-adder // (otherwise ffA would have been matched as ffAD) if (preAdd) { if (param(dsp, \AREG).as_int() == 0) { - dffQ = sigA; + argQ = sigA; subpattern(in_dffe); if (dff) { ffA = dff; @@ -125,9 +125,9 @@ code dffQ ffA ffAmux ffAenpol sigA clock ffAD ffADmux ffADenpol } endcode -code dffQ ffB ffBmux ffBenpol sigB clock +code argQ ffB ffBmux ffBenpol sigB clock if (param(dsp, \BREG).as_int() == 0) { - dffQ = sigB; + argQ = sigB; subpattern(in_dffe); if (dff) { ffB = dff; @@ -141,9 +141,9 @@ code dffQ ffB ffBmux ffBenpol sigB clock } endcode -code dffQ ffD ffDmux ffDenpol sigD clock +code argQ ffD ffDmux ffDenpol sigD clock if (param(dsp, \DREG).as_int() == 0) { - dffQ = sigD; + argQ = sigD; subpattern(in_dffe); if (dff) { ffD = dff; @@ -367,9 +367,9 @@ code sigC sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A); endcode -code dffQ ffC ffCmux ffCenpol sigC clock +code argQ ffC ffCmux ffCenpol sigC clock if (param(dsp, \CREG).as_int() == 0) { - dffQ = sigC; + argQ = sigC; subpattern(in_dffe); if (dff) { ffC = dff; @@ -388,22 +388,22 @@ code endcode subpattern in_dffe -arg dffQ clock dffenpol_ +arg argQ clock ffenpol match ff select ff->type.in($dff) // DSP48E1 does not support clock inversion select param(ff, \CLK_POLARITY).as_bool() - filter GetSize(port(ff, \Q)) >= GetSize(dffQ) + filter GetSize(port(ff, \Q)) >= GetSize(argQ) slice offset GetSize(port(ff, \Q)) - filter offset+GetSize(dffQ) <= GetSize(port(ff, \Q)) - filter port(ff, \Q).extract(offset, GetSize(dffQ)) == dffQ + filter offset+GetSize(argQ) <= GetSize(port(ff, \Q)) + filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ semioptional endmatch -code dffQ +code argQ if (ff) { - for (auto b : dffQ) + for (auto b : argQ) if (b.wire->get_bool_attribute(\keep)) reject; @@ -414,22 +414,22 @@ code dffQ dffclock = port(ff, \CLK); dff = ff; - dffD = dffQ; + dffD = argQ; dffD.replace(port(ff, \Q), port(ff, \D)); // Only search for ffmux if ff.Q has at // least 3 users (ff, dsp, ffmux) and // its ff.D only has two (ff, ffmux) - if (!(nusers(dffQ) >= 3 && nusers(dffD) == 2)) - dffQ = SigSpec(); + if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) + argQ = SigSpec(); } else { dff = nullptr; - dffQ = SigSpec(); + argQ = SigSpec(); } endcode match ffmux - if !dffQ.empty() + if !argQ.empty() select ffmux->type.in($mux) index port(ffmux, \Y) === port(ff, \D) filter GetSize(port(ffmux, \Y)) >= GetSize(dffD) @@ -437,17 +437,17 @@ match ffmux filter offset+GetSize(dffD) <= GetSize(port(ffmux, \Y)) filter port(ffmux, \Y).extract(offset, GetSize(dffD)) == dffD choice AB {\A, \B} - filter offset+GetSize(dffQ) <= GetSize(port(ffmux, \Y)) - filter port(ffmux, AB).extract(offset, GetSize(dffQ)) == dffQ + filter offset+GetSize(argQ) <= GetSize(port(ffmux, \Y)) + filter port(ffmux, AB).extract(offset, GetSize(argQ)) == argQ define pol (AB == \A) - set dffenpol_ pol + set ffenpol pol semioptional endmatch code if (ffmux) { dffmux = ffmux; - dffenpol = dffenpol_; + dffenpol = ffenpol; dffD = port(ffmux, dffenpol ? \B : \A); } else From a7e60322878913886278d537365baf939182a1d9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 20:56:29 -0700 Subject: [PATCH 202/356] Set USE_MULT and USE_SIMD --- techlibs/xilinx/dsp_map.v | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v index fdd55afe3..cc37f0085 100644 --- a/techlibs/xilinx/dsp_map.v +++ b/techlibs/xilinx/dsp_map.v @@ -23,7 +23,9 @@ module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); .INMODEREG(0), .MREG(0), .OPMODEREG(0), - .PREG(0) + .PREG(0), + .USE_MULT("MULTIPLY"), + .USE_SIMD("ONE48") ) _TECHMAP_REPLACE_ ( //Data path .A({{5{A[24]}}, A}), From 2c044304453ed0f2533af30cfbb347bf0fe6354d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 20:57:03 -0700 Subject: [PATCH 203/356] Only trim sigM if USE_MULT; only look for ffM then too --- passes/pmgen/xilinx_dsp.pmg | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 3185c4641..07432dfc7 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -39,16 +39,18 @@ code unextend sigA sigB sigC sigD sigM sigD = dsp->connections_.at(\D, SigSpec()); SigSpec P = port(dsp, \P); - // Only care about those bits that are used - int i; - for (i = 0; i < GetSize(P); i++) { - if (nusers(P[i]) <= 1) - break; - sigM.append(P[i]); + if (dsp->parameters.at(\USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") { + // Only care about those bits that are used + int i; + for (i = 0; i < GetSize(P); i++) { + if (nusers(P[i]) <= 1) + break; + sigM.append(P[i]); + } + log_assert(nusers(P.extract_end(i)) <= 1); } - log_assert(nusers(P.extract_end(i)) <= 1); - //if (GetSize(sigM) <= 10) - // reject; + else + sigM = P; endcode code argQ ffAD ffADmux ffADenpol sigA clock @@ -159,6 +161,7 @@ endcode match ffMmux if param(dsp, \MREG).as_int() == 0 + if dsp->parameters.at(\USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY" if nusers(sigM) == 2 select ffMmux->type.in($mux) choice BA {\B, \A} @@ -194,6 +197,7 @@ match ffM_enable endmatch match ffM + if dsp->parameters.at(\USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY" if !ffM_enable if param(dsp, \MREG).as_int() == 0 if nusers(sigM) == 2 From 5a6552e56bf278a4cb5249303680e10f3e1a79b1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 20:57:20 -0700 Subject: [PATCH 204/356] Add initial USE_SIMD=FOUR12 support --- passes/pmgen/xilinx_dsp.cc | 157 +++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 10308de57..2ab0cfa71 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -25,6 +25,161 @@ PRIVATE_NAMESPACE_BEGIN #include "passes/pmgen/xilinx_dsp_pm.h" +void pack_xilinx_simd(Module *module, const std::vector &selected_cells) +{ + std::deque simd12, simd24; + + for (auto cell : selected_cells) { + if (!cell->type.in("$add")) + continue; + SigSpec Y = cell->getPort("\\Y"); + if (!Y.is_chunk()) + continue; + if (!Y.as_chunk().wire->get_strpool_attribute("\\use_dsp").count("simd")) + continue; + if (GetSize(Y) > 25) + continue; + SigSpec A = cell->getPort("\\A"); + SigSpec B = cell->getPort("\\B"); + if (GetSize(Y) <= 13) { + if (GetSize(A) > 12) + continue; + if (GetSize(B) > 12) + continue; + simd12.push_back(cell); + } + else { + if (GetSize(A) > 24) + continue; + if (GetSize(B) > 24) + continue; + simd24.push_back(cell); + } + } + + auto addDsp = [module] { + Cell *cell = module->addCell(NEW_ID, "\\DSP48E1"); + cell->setParam("\\ACASCREG", 0); + cell->setParam("\\ADREG", 0); + cell->setParam("\\A_INPUT", Const("DIRECT")); + cell->setParam("\\ALUMODEREG", 0); + cell->setParam("\\AREG", 0); + cell->setParam("\\BCASCREG", 0); + cell->setParam("\\B_INPUT", Const("DIRECT")); + cell->setParam("\\BREG", 0); + cell->setParam("\\CARRYINREG", 0); + cell->setParam("\\CARRYINSELREG", 0); + cell->setParam("\\CREG", 0); + cell->setParam("\\DREG", 0); + cell->setParam("\\INMODEREG", 0); + cell->setParam("\\MREG", 0); + cell->setParam("\\OPMODEREG", 0); + cell->setParam("\\PREG", 0); + cell->setParam("\\USE_MULT", Const("NONE")); + + cell->setPort("\\D", Const(0, 24)); + cell->setPort("\\INMODE", Const(0, 5)); + cell->setPort("\\ALUMODE", Const(0, 4)); + cell->setPort("\\OPMODE", Const(0, 7)); + cell->setPort("\\CARRYINSEL", Const(0, 3)); + cell->setPort("\\ACIN", Const(0, 30)); + cell->setPort("\\BCIN", Const(0, 18)); + cell->setPort("\\PCIN", Const(0, 48)); + cell->setPort("\\CARRYIN", Const(0, 1)); + return cell; + }; + + SigSpec AB; + SigSpec C; + SigSpec P; + SigSpec CARRYOUT; + auto f12 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) { + SigSpec A = lane->getPort("\\A"); + SigSpec B = lane->getPort("\\B"); + SigSpec Y = lane->getPort("\\Y"); + A.extend_u0(12, lane->getParam("\\A_SIGNED").as_bool()); + B.extend_u0(12, lane->getParam("\\B_SIGNED").as_bool()); + AB.append(A); + C.append(B); + if (GetSize(Y) < 13) + Y.append(module->addWire(NEW_ID, 13-GetSize(Y))); + else + log_assert(GetSize(Y) == 13); + P.append(Y.extract(0, 12)); + CARRYOUT.append(Y[12]); + }; + while (simd12.size() > 1) { + AB = SigSpec(); + C = SigSpec(); + P = SigSpec(); + CARRYOUT = SigSpec(); + + Cell *lane1 = simd12.front(); + simd12.pop_front(); + Cell *lane2 = simd12.front(); + simd12.pop_front(); + Cell *lane3 = nullptr; + Cell *lane4 = nullptr; + + if (!simd12.empty()) { + lane3 = simd12.front(); + simd12.pop_front(); + if (!simd12.empty()) { + lane4 = simd12.front(); + simd12.pop_front(); + } + } + + log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1)); + + Cell *cell = addDsp(); + cell->setParam("\\USE_SIMD", Const("FOUR12")); + // X = A:B + // Y = 0 + // Z = C + cell->setPort("\\OPMODE", Const::from_string("0110011")); + + log_assert(lane1); + log_assert(lane2); + f12(lane1); + f12(lane2); + if (lane3) { + f12(lane3); + if (lane4) + f12(lane4); + else { + AB.append(Const(0, 12)); + C.append(Const(0, 12)); + P.append(module->addWire(NEW_ID, 12)); + CARRYOUT.append(module->addWire(NEW_ID, 1)); + } + } + else { + AB.append(Const(0, 24)); + C.append(Const(0, 24)); + P.append(module->addWire(NEW_ID, 24)); + CARRYOUT.append(module->addWire(NEW_ID, 2)); + } + log_assert(GetSize(AB) == 48); + log_assert(GetSize(C) == 48); + log_assert(GetSize(P) == 48); + log_assert(GetSize(CARRYOUT) == 4); + cell->setPort("\\A", AB.extract(18, 30)); + cell->setPort("\\B", AB.extract(0, 18)); + cell->setPort("\\C", C); + cell->setPort("\\P", P); + cell->setPort("\\CARRYOUT", CARRYOUT); + + module->remove(lane1); + module->remove(lane2); + if (lane3) module->remove(lane3); + if (lane4) module->remove(lane4); + + module->design->select(module, cell); + } +} + + void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) { auto &st = pm.st_xilinx_dsp; @@ -281,6 +436,8 @@ struct XilinxDspPass : public Pass { extra_args(args, argidx, design); for (auto module : design->selected_modules()) { + pack_xilinx_simd(module, module->selected_cells()); + xilinx_dsp_pm pm(module, module->selected_cells()); dict bit_to_driver; auto f = [&bit_to_driver](xilinx_dsp_pm &pm){ pack_xilinx_dsp(bit_to_driver, pm); }; From 0bb6fd8448aee02b7006dd1067cc556a85c6c266 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 20:58:54 -0700 Subject: [PATCH 205/356] Refactor --- passes/pmgen/xilinx_dsp.cc | 66 +++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 2ab0cfa71..97cadd3c9 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -25,6 +25,38 @@ PRIVATE_NAMESPACE_BEGIN #include "passes/pmgen/xilinx_dsp_pm.h" +static Cell* addDsp(Module *module) { + Cell *cell = module->addCell(NEW_ID, "\\DSP48E1"); + cell->setParam("\\ACASCREG", 0); + cell->setParam("\\ADREG", 0); + cell->setParam("\\A_INPUT", Const("DIRECT")); + cell->setParam("\\ALUMODEREG", 0); + cell->setParam("\\AREG", 0); + cell->setParam("\\BCASCREG", 0); + cell->setParam("\\B_INPUT", Const("DIRECT")); + cell->setParam("\\BREG", 0); + cell->setParam("\\CARRYINREG", 0); + cell->setParam("\\CARRYINSELREG", 0); + cell->setParam("\\CREG", 0); + cell->setParam("\\DREG", 0); + cell->setParam("\\INMODEREG", 0); + cell->setParam("\\MREG", 0); + cell->setParam("\\OPMODEREG", 0); + cell->setParam("\\PREG", 0); + cell->setParam("\\USE_MULT", Const("NONE")); + + cell->setPort("\\D", Const(0, 24)); + cell->setPort("\\INMODE", Const(0, 5)); + cell->setPort("\\ALUMODE", Const(0, 4)); + cell->setPort("\\OPMODE", Const(0, 7)); + cell->setPort("\\CARRYINSEL", Const(0, 3)); + cell->setPort("\\ACIN", Const(0, 30)); + cell->setPort("\\BCIN", Const(0, 18)); + cell->setPort("\\PCIN", Const(0, 48)); + cell->setPort("\\CARRYIN", Const(0, 1)); + return cell; +} + void pack_xilinx_simd(Module *module, const std::vector &selected_cells) { std::deque simd12, simd24; @@ -57,38 +89,6 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) } } - auto addDsp = [module] { - Cell *cell = module->addCell(NEW_ID, "\\DSP48E1"); - cell->setParam("\\ACASCREG", 0); - cell->setParam("\\ADREG", 0); - cell->setParam("\\A_INPUT", Const("DIRECT")); - cell->setParam("\\ALUMODEREG", 0); - cell->setParam("\\AREG", 0); - cell->setParam("\\BCASCREG", 0); - cell->setParam("\\B_INPUT", Const("DIRECT")); - cell->setParam("\\BREG", 0); - cell->setParam("\\CARRYINREG", 0); - cell->setParam("\\CARRYINSELREG", 0); - cell->setParam("\\CREG", 0); - cell->setParam("\\DREG", 0); - cell->setParam("\\INMODEREG", 0); - cell->setParam("\\MREG", 0); - cell->setParam("\\OPMODEREG", 0); - cell->setParam("\\PREG", 0); - cell->setParam("\\USE_MULT", Const("NONE")); - - cell->setPort("\\D", Const(0, 24)); - cell->setPort("\\INMODE", Const(0, 5)); - cell->setPort("\\ALUMODE", Const(0, 4)); - cell->setPort("\\OPMODE", Const(0, 7)); - cell->setPort("\\CARRYINSEL", Const(0, 3)); - cell->setPort("\\ACIN", Const(0, 30)); - cell->setPort("\\BCIN", Const(0, 18)); - cell->setPort("\\PCIN", Const(0, 48)); - cell->setPort("\\CARRYIN", Const(0, 1)); - return cell; - }; - SigSpec AB; SigSpec C; SigSpec P; @@ -132,7 +132,7 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1)); - Cell *cell = addDsp(); + Cell *cell = addDsp(module); cell->setParam("\\USE_SIMD", Const("FOUR12")); // X = A:B // Y = 0 From 31e60353acfae3335793c9640ab3fb131040512d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 21:11:41 -0700 Subject: [PATCH 206/356] Support TWO24 --- passes/pmgen/xilinx_dsp.cc | 60 +++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 97cadd3c9..23f342a2b 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -80,13 +80,15 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) continue; simd12.push_back(cell); } - else { + else if (GetSize(Y) <= 25) { if (GetSize(A) > 24) continue; if (GetSize(B) > 24) continue; simd24.push_back(cell); } + else + log_abort(); } SigSpec AB; @@ -177,6 +179,62 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) module->design->select(module, cell); } + + auto f24 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) { + SigSpec A = lane->getPort("\\A"); + SigSpec B = lane->getPort("\\B"); + SigSpec Y = lane->getPort("\\Y"); + A.extend_u0(24, lane->getParam("\\A_SIGNED").as_bool()); + B.extend_u0(24, lane->getParam("\\B_SIGNED").as_bool()); + AB.append(A); + C.append(B); + if (GetSize(Y) < 25) + Y.append(module->addWire(NEW_ID, 25-GetSize(Y))); + else + log_assert(GetSize(Y) == 25); + P.append(Y.extract(0, 24)); + CARRYOUT.append(module->addWire(NEW_ID)); // TWO24 uses every other bit + CARRYOUT.append(Y[24]); + }; + while (simd24.size() > 1) { + AB = SigSpec(); + C = SigSpec(); + P = SigSpec(); + CARRYOUT = SigSpec(); + + Cell *lane1 = simd24.front(); + simd24.pop_front(); + Cell *lane2 = simd24.front(); + simd24.pop_front(); + + log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1)); + + Cell *cell = addDsp(module); + cell->setParam("\\USE_SIMD", Const("TWO24")); + // X = A:B + // Y = 0 + // Z = C + cell->setPort("\\OPMODE", Const::from_string("0110011")); + + log_assert(lane1); + log_assert(lane2); + f24(lane1); + f24(lane2); + log_assert(GetSize(AB) == 48); + log_assert(GetSize(C) == 48); + log_assert(GetSize(P) == 48); + log_assert(GetSize(CARRYOUT) == 4); + cell->setPort("\\A", AB.extract(18, 30)); + cell->setPort("\\B", AB.extract(0, 18)); + cell->setPort("\\C", C); + cell->setPort("\\P", P); + cell->setPort("\\CARRYOUT", CARRYOUT); + + module->remove(lane1); + module->remove(lane2); + + module->design->select(module, cell); + } } From 02cf9933b9e5c0bff360db13c3577c0a75cdb5b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 21:39:42 -0700 Subject: [PATCH 207/356] Support subtraction as well --- passes/pmgen/xilinx_dsp.cc | 217 +++++++++++++++++++------------------ 1 file changed, 114 insertions(+), 103 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 23f342a2b..7bac1b974 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -59,10 +59,11 @@ static Cell* addDsp(Module *module) { void pack_xilinx_simd(Module *module, const std::vector &selected_cells) { - std::deque simd12, simd24; + std::deque simd12_add, simd12_sub; + std::deque simd24_add, simd24_sub; for (auto cell : selected_cells) { - if (!cell->type.in("$add")) + if (!cell->type.in("$add", "$sub")) continue; SigSpec Y = cell->getPort("\\Y"); if (!Y.is_chunk()) @@ -78,24 +79,26 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) continue; if (GetSize(B) > 12) continue; - simd12.push_back(cell); + if (cell->type == "$add") + simd12_add.push_back(cell); + else if (cell->type == "$sub") + simd12_sub.push_back(cell); } else if (GetSize(Y) <= 25) { if (GetSize(A) > 24) continue; if (GetSize(B) > 24) continue; - simd24.push_back(cell); + if (cell->type == "$add") + simd24_add.push_back(cell); + else if (cell->type == "$sub") + simd24_sub.push_back(cell); } else log_abort(); } - SigSpec AB; - SigSpec C; - SigSpec P; - SigSpec CARRYOUT; - auto f12 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) { + auto f12 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) { SigSpec A = lane->getPort("\\A"); SigSpec B = lane->getPort("\\B"); SigSpec Y = lane->getPort("\\Y"); @@ -110,84 +113,86 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) P.append(Y.extract(0, 12)); CARRYOUT.append(Y[12]); }; - while (simd12.size() > 1) { - AB = SigSpec(); - C = SigSpec(); - P = SigSpec(); - CARRYOUT = SigSpec(); + auto g12 = [&f12,module](std::deque &simd12) { + while (simd12.size() > 1) { + SigSpec AB, C, P, CARRYOUT; - Cell *lane1 = simd12.front(); - simd12.pop_front(); - Cell *lane2 = simd12.front(); - simd12.pop_front(); - Cell *lane3 = nullptr; - Cell *lane4 = nullptr; - - if (!simd12.empty()) { - lane3 = simd12.front(); + Cell *lane1 = simd12.front(); simd12.pop_front(); + Cell *lane2 = simd12.front(); + simd12.pop_front(); + Cell *lane3 = nullptr; + Cell *lane4 = nullptr; + if (!simd12.empty()) { - lane4 = simd12.front(); + lane3 = simd12.front(); simd12.pop_front(); + if (!simd12.empty()) { + lane4 = simd12.front(); + simd12.pop_front(); + } } - } - log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1)); + log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1)); - Cell *cell = addDsp(module); - cell->setParam("\\USE_SIMD", Const("FOUR12")); - // X = A:B - // Y = 0 - // Z = C - cell->setPort("\\OPMODE", Const::from_string("0110011")); + Cell *cell = addDsp(module); + cell->setParam("\\USE_SIMD", Const("FOUR12")); + // X = A:B + // Y = 0 + // Z = C + cell->setPort("\\OPMODE", Const::from_string("0110011")); - log_assert(lane1); - log_assert(lane2); - f12(lane1); - f12(lane2); - if (lane3) { - f12(lane3); - if (lane4) - f12(lane4); + log_assert(lane1); + log_assert(lane2); + f12(AB, C, P, CARRYOUT, lane1); + f12(AB, C, P, CARRYOUT, lane2); + if (lane3) { + f12(AB, C, P, CARRYOUT, lane3); + if (lane4) + f12(AB, C, P, CARRYOUT, lane4); + else { + AB.append(Const(0, 12)); + C.append(Const(0, 12)); + P.append(module->addWire(NEW_ID, 12)); + CARRYOUT.append(module->addWire(NEW_ID, 1)); + } + } else { - AB.append(Const(0, 12)); - C.append(Const(0, 12)); - P.append(module->addWire(NEW_ID, 12)); - CARRYOUT.append(module->addWire(NEW_ID, 1)); + AB.append(Const(0, 24)); + C.append(Const(0, 24)); + P.append(module->addWire(NEW_ID, 24)); + CARRYOUT.append(module->addWire(NEW_ID, 2)); } + log_assert(GetSize(AB) == 48); + log_assert(GetSize(C) == 48); + log_assert(GetSize(P) == 48); + log_assert(GetSize(CARRYOUT) == 4); + cell->setPort("\\A", AB.extract(18, 30)); + cell->setPort("\\B", AB.extract(0, 18)); + cell->setPort("\\C", C); + cell->setPort("\\P", P); + cell->setPort("\\CARRYOUT", CARRYOUT); + if (lane1->type == "$sub") + cell->setPort("\\ALUMODE", Const::from_string("0011")); + + module->remove(lane1); + module->remove(lane2); + if (lane3) module->remove(lane3); + if (lane4) module->remove(lane4); + + module->design->select(module, cell); } - else { - AB.append(Const(0, 24)); - C.append(Const(0, 24)); - P.append(module->addWire(NEW_ID, 24)); - CARRYOUT.append(module->addWire(NEW_ID, 2)); - } - log_assert(GetSize(AB) == 48); - log_assert(GetSize(C) == 48); - log_assert(GetSize(P) == 48); - log_assert(GetSize(CARRYOUT) == 4); - cell->setPort("\\A", AB.extract(18, 30)); - cell->setPort("\\B", AB.extract(0, 18)); - cell->setPort("\\C", C); - cell->setPort("\\P", P); - cell->setPort("\\CARRYOUT", CARRYOUT); + }; + g12(simd12_add); + g12(simd12_sub); - module->remove(lane1); - module->remove(lane2); - if (lane3) module->remove(lane3); - if (lane4) module->remove(lane4); - - module->design->select(module, cell); - } - - auto f24 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) { + auto f24 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) { SigSpec A = lane->getPort("\\A"); SigSpec B = lane->getPort("\\B"); SigSpec Y = lane->getPort("\\Y"); A.extend_u0(24, lane->getParam("\\A_SIGNED").as_bool()); B.extend_u0(24, lane->getParam("\\B_SIGNED").as_bool()); - AB.append(A); - C.append(B); + AB.append(B); if (GetSize(Y) < 25) Y.append(module->addWire(NEW_ID, 25-GetSize(Y))); else @@ -196,45 +201,51 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) CARRYOUT.append(module->addWire(NEW_ID)); // TWO24 uses every other bit CARRYOUT.append(Y[24]); }; - while (simd24.size() > 1) { - AB = SigSpec(); - C = SigSpec(); - P = SigSpec(); - CARRYOUT = SigSpec(); + auto g24 = [&f24,module](std::deque &simd24) { + while (simd24.size() > 1) { + SigSpec AB; + SigSpec C; + SigSpec P; + SigSpec CARRYOUT; - Cell *lane1 = simd24.front(); - simd24.pop_front(); - Cell *lane2 = simd24.front(); - simd24.pop_front(); + Cell *lane1 = simd24.front(); + simd24.pop_front(); + Cell *lane2 = simd24.front(); + simd24.pop_front(); - log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1)); + log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1)); - Cell *cell = addDsp(module); - cell->setParam("\\USE_SIMD", Const("TWO24")); - // X = A:B - // Y = 0 - // Z = C - cell->setPort("\\OPMODE", Const::from_string("0110011")); + Cell *cell = addDsp(module); + cell->setParam("\\USE_SIMD", Const("TWO24")); + // X = A:B + // Y = 0 + // Z = C + cell->setPort("\\OPMODE", Const::from_string("0110011")); - log_assert(lane1); - log_assert(lane2); - f24(lane1); - f24(lane2); - log_assert(GetSize(AB) == 48); - log_assert(GetSize(C) == 48); - log_assert(GetSize(P) == 48); - log_assert(GetSize(CARRYOUT) == 4); - cell->setPort("\\A", AB.extract(18, 30)); - cell->setPort("\\B", AB.extract(0, 18)); - cell->setPort("\\C", C); - cell->setPort("\\P", P); - cell->setPort("\\CARRYOUT", CARRYOUT); + log_assert(lane1); + log_assert(lane2); + f24(AB, C, P, CARRYOUT, lane1); + f24(AB, C, P, CARRYOUT, lane2); + log_assert(GetSize(AB) == 48); + log_assert(GetSize(C) == 48); + log_assert(GetSize(P) == 48); + log_assert(GetSize(CARRYOUT) == 4); + cell->setPort("\\A", AB.extract(18, 30)); + cell->setPort("\\B", AB.extract(0, 18)); + cell->setPort("\\C", C); + cell->setPort("\\P", P); + cell->setPort("\\CARRYOUT", CARRYOUT); + if (lane1->type == "$sub") + cell->setPort("\\ALUMODE", Const::from_string("0011")); - module->remove(lane1); - module->remove(lane2); + module->remove(lane1); + module->remove(lane2); - module->design->select(module, cell); - } + module->design->select(module, cell); + } + }; + g24(simd24_add); + g24(simd24_sub); } From 1fc50a03fcaeebc0d1b12f397c2d31bcd27df715 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 21:40:06 -0700 Subject: [PATCH 208/356] Add SIMD test --- tests/xilinx/dsp_simd.ys | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/xilinx/dsp_simd.ys diff --git a/tests/xilinx/dsp_simd.ys b/tests/xilinx/dsp_simd.ys new file mode 100644 index 000000000..956952327 --- /dev/null +++ b/tests/xilinx/dsp_simd.ys @@ -0,0 +1,25 @@ +read_verilog < Date: Mon, 9 Sep 2019 22:06:23 -0700 Subject: [PATCH 209/356] Oops --- passes/pmgen/xilinx_dsp.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 7bac1b974..d48c646c0 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -192,6 +192,7 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) SigSpec Y = lane->getPort("\\Y"); A.extend_u0(24, lane->getParam("\\A_SIGNED").as_bool()); B.extend_u0(24, lane->getParam("\\B_SIGNED").as_bool()); + C.append(A); AB.append(B); if (GetSize(Y) < 25) Y.append(module->addWire(NEW_ID, 25-GetSize(Y))); From bfda921d0317bfb4cb6fc9de8a556c2258b709bc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 13:17:47 -0700 Subject: [PATCH 210/356] Remove "opt_expr -fine" call --- techlibs/xilinx/synth_xilinx.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 95b2c4040..e13491e2c 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -325,7 +325,6 @@ struct SynthXilinxPass : public ScriptPass if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); - run("opt_expr -fine", " (skip if '-nodsp')"); run("wreduce", " (skip if '-nodsp')"); run("xilinx_dsp", " (skip if '-nodsp')"); run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); From d3fb3081812f0fc34230aabe01b14f06a3240d56 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 13:18:10 -0700 Subject: [PATCH 211/356] Rename label to map_dsp --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index e13491e2c..af8ee2368 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -321,7 +321,7 @@ struct SynthXilinxPass : public ScriptPass run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); } - if (check_label("dsp")) { + if (check_label("map_dsp")) { if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); From 8514e7c32ebfb2ce35619063b1507416f01bd3b4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 14:09:21 -0700 Subject: [PATCH 212/356] Revert "Remove "opt_expr -fine" call" This reverts commit bfda921d0317bfb4cb6fc9de8a556c2258b709bc. --- techlibs/xilinx/synth_xilinx.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index af8ee2368..2cf0bd4f9 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -325,6 +325,7 @@ struct SynthXilinxPass : public ScriptPass if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); + run("opt_expr -fine", " (skip if '-nodsp')"); run("wreduce", " (skip if '-nodsp')"); run("xilinx_dsp", " (skip if '-nodsp')"); run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); From f3a55d3f06a21af06a267b3f9da8bd4df3d4aa82 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 14:11:56 -0700 Subject: [PATCH 213/356] Add comment for why opt_expr is necessary --- techlibs/xilinx/synth_xilinx.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 2cf0bd4f9..c99b77905 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -325,6 +325,8 @@ struct SynthXilinxPass : public ScriptPass if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); + // Necessary for optimising away $shl cells, as well as $add cells + // that have inputs with 1'b0 LSBs run("opt_expr -fine", " (skip if '-nodsp')"); run("wreduce", " (skip if '-nodsp')"); run("xilinx_dsp", " (skip if '-nodsp')"); From c460d10e60648c5126fe4a105ebf608b4f8d5e1a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 14:17:35 -0700 Subject: [PATCH 214/356] Remove wreduce call --- techlibs/xilinx/synth_xilinx.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c99b77905..9ad28a933 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -328,7 +328,6 @@ struct SynthXilinxPass : public ScriptPass // Necessary for optimising away $shl cells, as well as $add cells // that have inputs with 1'b0 LSBs run("opt_expr -fine", " (skip if '-nodsp')"); - run("wreduce", " (skip if '-nodsp')"); run("xilinx_dsp", " (skip if '-nodsp')"); run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); } From 76eedee08928f035f00f46304d1b49e9502401c1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 14:26:12 -0700 Subject: [PATCH 215/356] Really get rid of 'opt_expr -fine' by being explicit --- techlibs/common/mul2dsp.v | 39 ++++++++++++++++++++++++++++----- techlibs/xilinx/synth_xilinx.cc | 3 --- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 75b1242a2..51a6c5fb9 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -148,8 +148,17 @@ module _80_mul (A, B, Y); // reduction' approach also exists... if (i == 0) assign partial_sum[i] = partial[i]; - else - assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; + else begin + // Rewrite the following statement explicitly in order + // to save on a call to 'opt_expr -fine' which would + // optimise away the '<<' op and trim size of adder + //assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; + wire [Y_WIDTH-1:0] shifted_sum = {partial[i], {i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom){1'b0}}}; + assign partial_sum[i] = { + partial_sum[i-1][i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0], + shifted_sum[Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] + partial_sum[i-1][Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] + }; + end end \$__mul #( @@ -163,7 +172,12 @@ module _80_mul (A, B, Y); .B(B), .Y(last_partial) ); - assign partial_sum[n] = (last_partial << n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; + //assign partial_sum[n] = (last_partial << n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; + wire [Y_WIDTH-1:0] shifted_sum = {last_partial, {n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom){1'b0}}}; + assign partial_sum[n] = { + partial_sum[n-1][n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0], + shifted_sum[Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] + partial_sum[n-1][Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] + }; assign Y = partial_sum[n]; end else if (B_WIDTH > `DSP_B_MAXWIDTH) begin @@ -199,8 +213,16 @@ module _80_mul (A, B, Y); // reduction' approach also exists... if (i == 0) assign partial_sum[i] = partial[i]; - else - assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; + else begin + // Rewrite the following statement explicitly in order + // to save on a call to 'opt_expr -fine' which would + // optimise away the '<<' op and trim size of adder + wire [Y_WIDTH-1:0] shifted_sum = {partial[i], {i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom){1'b0}}}; + assign partial_sum[i] = { + partial_sum[i-1][i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0], + shifted_sum[Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] + partial_sum[i-1][Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] + }; + end end \$__mul #( @@ -214,7 +236,12 @@ module _80_mul (A, B, Y); .B(B[B_WIDTH-1 -: last_B_WIDTH]), .Y(last_partial) ); - assign partial_sum[n] = (last_partial << n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; + //assign partial_sum[n] = (last_partial << n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; + wire [Y_WIDTH-1:0] shifted_sum = {last_partial, {n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom){1'b0}}}; + assign partial_sum[n] = { + partial_sum[n-1][n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0], + shifted_sum[Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] + partial_sum[n-1][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] + }; assign Y = partial_sum[n]; end else begin diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 9ad28a933..4ca8a4667 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -325,9 +325,6 @@ struct SynthXilinxPass : public ScriptPass if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); - // Necessary for optimising away $shl cells, as well as $add cells - // that have inputs with 1'b0 LSBs - run("opt_expr -fine", " (skip if '-nodsp')"); run("xilinx_dsp", " (skip if '-nodsp')"); run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); } From f2d030a70f1754e7ee6bd1fb588c5abadac4dd08 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 15:14:55 -0700 Subject: [PATCH 216/356] Be sensitive to signedness --- techlibs/common/mul2dsp.v | 41 ++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 51a6c5fb9..f2b44222e 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -153,11 +153,11 @@ module _80_mul (A, B, Y); // to save on a call to 'opt_expr -fine' which would // optimise away the '<<' op and trim size of adder //assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; - wire [Y_WIDTH-1:0] shifted_sum = {partial[i], {i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom){1'b0}}}; - assign partial_sum[i] = { - partial_sum[i-1][i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0], - shifted_sum[Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] + partial_sum[i-1][Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] - }; + if (A_SIGNED && B_SIGNED) + assign partial_sum[i][Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] = partial[i] + $signed(partial_sum[i-1][Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)]); + else + assign partial_sum[i][Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] = partial[i] + partial_sum[i-1][Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)]; + assign partial_sum[i][i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0] = partial_sum[i-1][i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0]; end end @@ -173,11 +173,11 @@ module _80_mul (A, B, Y); .Y(last_partial) ); //assign partial_sum[n] = (last_partial << n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; - wire [Y_WIDTH-1:0] shifted_sum = {last_partial, {n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom){1'b0}}}; - assign partial_sum[n] = { - partial_sum[n-1][n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0], - shifted_sum[Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] + partial_sum[n-1][Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] - }; + if (A_SIGNED && B_SIGNED) + assign partial_sum[n][Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + $signed(partial_sum[n-1][Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)]); + else + assign partial_sum[n][Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + partial_sum[n-1][Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)]; + assign partial_sum[n][n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0] = partial_sum[n-1][n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0]; assign Y = partial_sum[n]; end else if (B_WIDTH > `DSP_B_MAXWIDTH) begin @@ -217,11 +217,12 @@ module _80_mul (A, B, Y); // Rewrite the following statement explicitly in order // to save on a call to 'opt_expr -fine' which would // optimise away the '<<' op and trim size of adder - wire [Y_WIDTH-1:0] shifted_sum = {partial[i], {i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom){1'b0}}}; - assign partial_sum[i] = { - partial_sum[i-1][i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0], - shifted_sum[Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] + partial_sum[i-1][Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] - }; + //assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; + if (A_SIGNED && B_SIGNED) + assign partial_sum[i][Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = partial[i] + $signed(partial_sum[i-1][Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]); + else + assign partial_sum[i][Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = partial[i] + partial_sum[i-1][Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]; + assign partial_sum[i][i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0] = partial_sum[i-1][i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0]; end end @@ -237,11 +238,11 @@ module _80_mul (A, B, Y); .Y(last_partial) ); //assign partial_sum[n] = (last_partial << n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; - wire [Y_WIDTH-1:0] shifted_sum = {last_partial, {n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom){1'b0}}}; - assign partial_sum[n] = { - partial_sum[n-1][n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0], - shifted_sum[Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] + partial_sum[n-1][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] - }; + if (A_SIGNED && B_SIGNED) + assign partial_sum[n][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + partial_sum[n-1][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]; + else + assign partial_sum[n][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + $signed(partial_sum[n-1][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]); + assign partial_sum[n][n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0] = partial_sum[n-1][n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0]; assign Y = partial_sum[n]; end else begin From 5c1271c51c41b8a067ecf6165d3e09a73eee5fb7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 15:26:56 -0700 Subject: [PATCH 217/356] Move "(skip if -nodsp)" message to label --- techlibs/xilinx/synth_xilinx.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 4ca8a4667..83be66daa 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -321,12 +321,12 @@ struct SynthXilinxPass : public ScriptPass run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); } - if (check_label("map_dsp")) { + if (check_label("map_dsp"), "(skip if '-nodsp')") { if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only - run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); - run("xilinx_dsp", " (skip if '-nodsp')"); - run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')"); + run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); + run("xilinx_dsp"); + run("chtype -set $mul t:$__soft_mul"); } } From 04153c501128ae37c7ed1235266ab6b32902b878 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 16:14:26 -0700 Subject: [PATCH 218/356] Update CHANGELOG --- CHANGELOG | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index c29429295..f0a0d0fae 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -38,6 +38,11 @@ Yosys 0.9 .. Yosys 0.9-dev - Improvements in pmgen: slices, choices, define, generate - Added "xilinx_srl" for Xilinx shift register extraction - Removed "shregmap -tech xilinx" (superseded by "xilinx_srl") + - Added +/mul2dsp.v for decomposing wide multipliers to custom-sized ones + - Added "xilinx_dsp" for Xilinx DSP packing + - "synth_xilinx" to now infer DSP blocks (-nodsp to disable) + - "synth_ecp5" to now infer DSP blocks (-nodsp to disable, experimental) + - "synth_ice40 -dsp" to infer DSP blocks Yosys 0.8 .. Yosys 0.9 ---------------------- From d30b2a6d7eae08411ae588f1081b3b3793810678 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 16:33:13 -0700 Subject: [PATCH 219/356] Update xilinx_dsp help text --- passes/pmgen/xilinx_dsp.cc | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index d48c646c0..40357a22d 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -480,19 +480,37 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) } struct XilinxDspPass : public Pass { - XilinxDspPass() : Pass("xilinx_dsp", "Xilinx: pack DSP registers") { } + XilinxDspPass() : Pass("xilinx_dsp", "Xilinx: pack resources into DSPs") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" xilinx_dsp [options] [selection]\n"); log("\n"); - log("Pack registers into Xilinx DSPs\n"); + log("Pack input registers (A, B, C, D, AD; with optional enable), pipeline registers\n"); + log("(M; with optional enable), output registers (P; with optional enable),\n"); + log("pre-adder and/or post-adder into Xilinx DSP resources.\n"); + log("\n"); + log("Multiply-accumulate operations using the post-adder with feedback on the 'C'\n"); + log("input will be folded into the DSP. In this scenario only, the 'C' input can be\n"); + log("used to override the existing accumulation result with a new value.\n"); + log("\n"); + log("'PCOUT' -> 'PCIN' cascading is detected for 'P' -> 'C' connections, where 'P' is\n"); + log("is right-shifted by 18-bits and used as an input to the post-adder (a common\n"); + log("pattern for summing partial products).\n"); + log("\n"); + log("Not currently supported: reset (RST*) inputs on any register.\n"); + log("\n"); + log("\n"); + log("Experimental feature: addition/subtractions less than 12 or 24 bits with the\n"); + log("'(* use_dsp=\"simd\" *)' attribute attached to the output wire or attached to\n"); + log("the add/subtract operator will cause those operations to be implemented using\n"); + log("the 'SIMD' feature of DSPs.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - log_header(design, "Executing XILINX_DSP pass (pack DSPs).\n"); + log_header(design, "Executing XILINX_DSP pass (pack resources into DSPs).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) From e64e650f9c077094e7fd15c7e149f5b9ec4773d7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 16:35:10 -0700 Subject: [PATCH 220/356] Update help text --- passes/pmgen/xilinx_dsp.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 40357a22d..3e4d596ca 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -495,9 +495,9 @@ struct XilinxDspPass : public Pass { log("input will be folded into the DSP. In this scenario only, the 'C' input can be\n"); log("used to override the existing accumulation result with a new value.\n"); log("\n"); - log("'PCOUT' -> 'PCIN' cascading is detected for 'P' -> 'C' connections, where 'P' is\n"); - log("is right-shifted by 18-bits and used as an input to the post-adder (a common\n"); - log("pattern for summing partial products).\n"); + log("Use of the dedicated 'PCOUT' -> 'PCIN' path is detected for 'P' -> 'C' connections\n"); + log("where 'P' is right-shifted by 18-bits and used as an input to the post-adder (a\n"); + log("pattern common for summing partial products to implement wide multiplies).\n"); log("\n"); log("Not currently supported: reset (RST*) inputs on any register.\n"); log("\n"); From 8b8a68b38a43a082b76747934d98c6e488d1f6e4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 18:27:05 -0700 Subject: [PATCH 221/356] Refactor MREG and PREG to out_dffe subpattern --- passes/pmgen/xilinx_dsp.pmg | 277 ++++++++++++++++-------------------- 1 file changed, 122 insertions(+), 155 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 07432dfc7..09e59c184 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -7,12 +7,12 @@ state postAddAB postAddMuxAB state ffAenpol ffADenpol ffBenpol ffCenpol ffDenpol ffMenpol ffPenpol state ffPoffset -state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux +state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPmux // subpattern -state argQ +state argQ argD state ffenpol -udata dffD +udata dffD dffQ udata dffclock udata dff dffmux udata dffenpol @@ -159,76 +159,20 @@ code argQ ffD ffDmux ffDenpol sigD clock } endcode -match ffMmux - if param(dsp, \MREG).as_int() == 0 - if dsp->parameters.at(\USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY" - if nusers(sigM) == 2 - select ffMmux->type.in($mux) - choice BA {\B, \A} - // new-value net must have exactly two users: dsp and ffMmux - select nusers(port(ffMmux, BA)) == 2 - define AB (BA == \B ? \A : \B) - // keep-last-value net must have at least three users: ffMmux, ffM, downstream sink(s) - select nusers(port(ffMmux, AB)) >= 3 - // ffMmux output must have two users: ffMmux and ffM.D - select nusers(port(ffMmux, \Y)) == 2 - filter GetSize(unextend(port(ffMmux, BA))) <= GetSize(sigM) - filter unextend(port(ffMmux, BA)) == sigM.extract(0, GetSize(unextend(port(ffMmux, BA)))) - // Remaining bits on sigM must not have any other users - filter nusers(sigM.extract_end(GetSize(unextend(port(ffMmux, BA))))) <= 1 - define pol (AB == \A) - set ffMenpol pol - optional -endmatch - -code sigM - if (ffMmux) - sigM = port(ffMmux, \Y); -endcode - -match ffM_enable - if ffMmux - if nusers(sigM) == 2 - select ffM_enable->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffM_enable, \CLK_POLARITY).as_bool() - index port(ffM_enable, \D) === sigM - index port(ffM_enable, \Q) === port(ffMmux, ffMenpol ? \A : \B) -endmatch - -match ffM - if dsp->parameters.at(\USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY" - if !ffM_enable - if param(dsp, \MREG).as_int() == 0 - if nusers(sigM) == 2 - select ffM->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffM, \CLK_POLARITY).as_bool() - index port(ffM, \D) === sigM - optional -endmatch - -code ffM clock sigM sigP - if (ffM_enable) { - log_assert(!ffM); - ffM = ffM_enable; +code argD ffM ffMmux ffMenpol sigM sigP clock + if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) { + argD = sigM; + subpattern(out_dffe); + if (dff) { + ffM = dff; + clock = dffclock; + if (dffmux) { + ffMmux = dffmux; + ffMenpol = dffenpol; + } + sigM = dffQ; + } } - if (ffM) { - sigM = port(ffM, \Q); - - for (auto b : sigM) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffM, \CLK).as_bit(); - if (clock != SigBit() && c != clock) - reject; - clock = c; - } - // No enable mux possible without flop - else if (ffMmux) - reject; - sigP = sigM; endcode @@ -268,90 +212,25 @@ code sigC sigP } endcode -match ffPmux - if param(dsp, \PREG).as_int() == 0 - // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux - if !ffMmux || postAdd || nusers(sigP) == 3 - // Otherwise new-value net must have exactly two users: dsp and ffPmux - if (ffMmux && !postAdd) || nusers(sigP) == 2 - - select ffPmux->type.in($mux) - // ffPmux output must have two users: ffPmux and ffP.D - select nusers(port(ffPmux, \Y)) == 2 - filter GetSize(port(ffPmux, \Y)) >= GetSize(sigP) - - slice offset GetSize(port(ffPmux, \Y)) - filter offset+GetSize(sigP) <= GetSize(port(ffPmux, \Y)) - choice BA {\B, \A} - filter port(ffPmux, BA).extract(offset, GetSize(sigP)) == sigP - - define AB (BA == \B ? \A : \B) - // keep-last-value net must have at least three users: ffPmux, ffP, downstream sink(s) - filter nusers(port(ffPmux, AB)) >= 3 - define pol (AB == \A) - set ffPenpol pol - set ffPoffset offset - optional -endmatch - -code sigP - if (ffPmux) - sigP.replace(port(ffPmux, ffPenpol ? \B : \A), port(ffPmux, \Y)); -endcode - -match ffP_enable - if ffPmux - if nusers(sigP) == 2 - select ffP_enable->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffP_enable, \CLK_POLARITY).as_bool() - index port(ffP_enable, \D) === port(ffPmux, \Y) - index port(ffP_enable, \Q) === port(ffPmux, ffPenpol ? \A : \B) - filter GetSize(port(ffP_enable, \D)) >= GetSize(sigP) - filter ffPoffset+GetSize(sigP) <= GetSize(port(ffP_enable, \D)) - filter port(ffP_enable, \D).extract(ffPoffset, GetSize(sigP)) == sigP -endmatch - -match ffP - if !ffP_enable - if param(dsp, \PREG).as_int() == 0 - // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux - if !ffMmux || postAdd || nusers(sigP) == 3 - // Otherwise new-value net must have exactly two users: dsp and ffPmux - if (ffMmux && !postAdd) || nusers(sigP) == 2 - - select ffP->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffP, \CLK_POLARITY).as_bool() - filter GetSize(port(ffP, \D)) >= GetSize(sigP) - slice offset GetSize(port(ffP, \D)) - filter offset+GetSize(sigP) <= GetSize(port(ffP, \D)) - filter port(ffP, \D).extract(offset, GetSize(sigP)) == sigP - optional -endmatch - -code ffP sigP clock - if (ffP_enable) { - log_assert(!ffP); - ffP = ffP_enable; +code argD ffP ffPmux ffPenpol sigP clock + if (param(dsp, \PREG).as_int() == 0) { + // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux + if ((ffMmux && !postAdd && nusers(sigP) == 3) || + // Otherwise new-value net must have exactly two users: dsp and ffPmux + ((!ffMmux || postAdd) && nusers(sigP) == 2)) { + argD = sigP; + subpattern(out_dffe); + if (dff) { + ffP = dff; + clock = dffclock; + if (dffmux) { + ffPmux = dffmux; + ffPenpol = dffenpol; + } + sigP = dffQ; + } + } } - if (ffP) { - for (auto b : port(ffP, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffP, \CLK).as_bit(); - - if (clock != SigBit() && c != clock) - reject; - - clock = c; - - sigP.replace(port(ffP, \D), port(ffP, \Q)); - } - // No enable mux possible without flop - else if (ffPmux) - reject; endcode match postAddMux @@ -391,6 +270,8 @@ code accept; endcode +// ####################### + subpattern in_dffe arg argQ clock ffenpol @@ -457,3 +338,89 @@ code else dffmux = nullptr; endcode + +// ####################### + +subpattern out_dffe +arg argD clock ffenpol +arg unextend + +match ffmux + select ffmux->type.in($mux) + // ffmux output must have two users: ffmux and ff.D + select nusers(port(ffmux, \Y)) == 2 + filter GetSize(port(ffmux, \Y)) >= GetSize(argD) + + choice BA {\B, \A} + // new-value net must have exactly two users: (upstream) and ffmux + select nusers(port(ffmux, BA)) == 2 + + slice offset GetSize(port(ffmux, \Y)) + filter offset+GetSize(argD) <= GetSize(port(ffmux, \Y)) + filter port(ffmux, BA).extract(offset, GetSize(argD)) == argD + + define AB (BA == \B ? \A : \B) + // keep-last-value net must have at least three users: ffmux, ff, downstream sink(s) + select nusers(port(ffmux, AB)) >= 3 + + filter GetSize(unextend(port(ffmux, BA))) <= GetSize(argD) + filter unextend(port(ffmux, BA)) == argD.extract(0, GetSize(unextend(port(ffmux, BA)))) + // Remaining bits on argD must not have any other users + filter nusers(argD.extract_end(GetSize(unextend(port(ffmux, BA))))) <= 1 + + define pol (AB == \A) + set ffenpol pol + semioptional +endmatch + +code argD + if (ffmux) { + dffmux = ffmux; + dffenpol = ffenpol; + argD = port(ffmux, \Y); + } + else + dffmux = nullptr; +endcode + +match ff_enable + if ffmux + select ff_enable->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ff_enable, \CLK_POLARITY).as_bool() + index port(ff_enable, \D) === argD + index port(ff_enable, \Q) === port(ffmux, ffenpol ? \A : \B) +endmatch + +match ff + if !ff_enable + select ff->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ff, \CLK_POLARITY).as_bool() + index port(ff, \D) === argD + semioptional +endmatch + +code + if (ff_enable) + dff = ff_enable; + else + dff = ff; + log_dump("ffM", dff, dffmux); + if (dff) { + dffQ = port(dff, \Q); + + for (auto b : dffQ) + if (b.wire->get_bool_attribute(\keep)) + reject; + + if (clock != SigBit()) { + if (port(dff, \CLK) != clock) + reject; + } + dffclock = port(dff, \CLK); + } + // No enable mux possible without flop + else if (ffmux) + reject; +endcode From 86700c2beaa4cf8f5142c55f143b5b0d2207d953 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 18:52:54 -0700 Subject: [PATCH 222/356] d?ffmux -> d?ffcemux --- passes/pmgen/xilinx_dsp.pmg | 67 ++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 09e59c184..9d6236d07 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -14,7 +14,7 @@ state argQ argD state ffenpol udata dffD dffQ udata dffclock -udata dff dffmux +udata dff dffcemux udata dffenpol match dsp @@ -60,8 +60,8 @@ code argQ ffAD ffADmux ffADenpol sigA clock if (dff) { ffAD = dff; clock = dffclock; - if (dffmux) { - ffADmux = dffmux; + if (dffcemux) { + ffADmux = dffcemux; ffADenpol = dffenpol; } sigA = dffD; @@ -109,8 +109,8 @@ code argQ ffA ffAmux ffAenpol sigA clock ffAD ffADmux ffADenpol if (dff) { ffA = dff; clock = dffclock; - if (dffmux) { - ffAmux = dffmux; + if (dffcemux) { + ffAmux = dffcemux; ffAenpol = dffenpol; } sigA = dffD; @@ -134,8 +134,8 @@ code argQ ffB ffBmux ffBenpol sigB clock if (dff) { ffB = dff; clock = dffclock; - if (dffmux) { - ffBmux = dffmux; + if (dffcemux) { + ffBmux = dffcemux; ffBenpol = dffenpol; } sigB = dffD; @@ -150,8 +150,8 @@ code argQ ffD ffDmux ffDenpol sigD clock if (dff) { ffD = dff; clock = dffclock; - if (dffmux) { - ffDmux = dffmux; + if (dffcemux) { + ffDmux = dffcemux; ffDenpol = dffenpol; } sigD = dffD; @@ -166,8 +166,8 @@ code argD ffM ffMmux ffMenpol sigM sigP clock if (dff) { ffM = dff; clock = dffclock; - if (dffmux) { - ffMmux = dffmux; + if (dffcemux) { + ffMmux = dffcemux; ffMenpol = dffenpol; } sigM = dffQ; @@ -223,8 +223,8 @@ code argD ffP ffPmux ffPenpol sigP clock if (dff) { ffP = dff; clock = dffclock; - if (dffmux) { - ffPmux = dffmux; + if (dffcemux) { + ffPmux = dffcemux; ffPenpol = dffenpol; } sigP = dffQ; @@ -257,8 +257,8 @@ code argQ ffC ffCmux ffCenpol sigC clock if (dff) { ffC = dff; clock = dffclock; - if (dffmux) { - ffCmux = dffmux; + if (dffcemux) { + ffCmux = dffcemux; ffCenpol = dffenpol; } sigC = dffD; @@ -301,9 +301,9 @@ code argQ dff = ff; dffD = argQ; dffD.replace(port(ff, \Q), port(ff, \D)); - // Only search for ffmux if ff.Q has at - // least 3 users (ff, dsp, ffmux) and - // its ff.D only has two (ff, ffmux) + // Only search for ffcemux if argQ has at + // least 3 users (ff, , ffcemux) and + // its ff.D only has two (ff, ffcemux) if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) argQ = SigSpec(); } @@ -313,30 +313,30 @@ code argQ } endcode -match ffmux +match ffcemux if !argQ.empty() - select ffmux->type.in($mux) - index port(ffmux, \Y) === port(ff, \D) - filter GetSize(port(ffmux, \Y)) >= GetSize(dffD) - slice offset GetSize(port(ffmux, \Y)) - filter offset+GetSize(dffD) <= GetSize(port(ffmux, \Y)) - filter port(ffmux, \Y).extract(offset, GetSize(dffD)) == dffD + select ffcemux->type.in($mux) + index port(ffcemux, \Y) === port(ff, \D) + filter GetSize(port(ffcemux, \Y)) >= GetSize(dffD) + slice offset GetSize(port(ffcemux, \Y)) + filter offset+GetSize(dffD) <= GetSize(port(ffcemux, \Y)) + filter port(ffcemux, \Y).extract(offset, GetSize(dffD)) == dffD choice AB {\A, \B} - filter offset+GetSize(argQ) <= GetSize(port(ffmux, \Y)) - filter port(ffmux, AB).extract(offset, GetSize(argQ)) == argQ + filter offset+GetSize(argQ) <= GetSize(port(ffcemux, \Y)) + filter port(ffcemux, AB).extract(offset, GetSize(argQ)) == argQ define pol (AB == \A) set ffenpol pol semioptional endmatch code - if (ffmux) { - dffmux = ffmux; + if (ffcemux) { + dffcemux = ffcemux; dffenpol = ffenpol; - dffD = port(ffmux, dffenpol ? \B : \A); + dffD = port(ffcemux, dffenpol ? \B : \A); } else - dffmux = nullptr; + dffcemux = nullptr; endcode // ####################### @@ -375,12 +375,12 @@ endmatch code argD if (ffmux) { - dffmux = ffmux; + dffcemux = ffmux; dffenpol = ffenpol; argD = port(ffmux, \Y); } else - dffmux = nullptr; + dffcemux = nullptr; endcode match ff_enable @@ -406,7 +406,6 @@ code dff = ff_enable; else dff = ff; - log_dump("ffM", dff, dffmux); if (dff) { dffQ = port(dff, \Q); From c6df55a9e7c9827a6b971cc885b83fdb69b269d3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 18:59:03 -0700 Subject: [PATCH 223/356] enpol -> cepol --- passes/pmgen/xilinx_dsp.cc | 22 ++++----- passes/pmgen/xilinx_dsp.pmg | 94 +++++++++++++++++++------------------ 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 3e4d596ca..a5fa67083 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -297,7 +297,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffAD) { if (st.ffADmux) { SigSpec S = st.ffADmux->getPort("\\S"); - cell->setPort("\\CEAD", st.ffADenpol ? S : pm.module->Not(NEW_ID, S)); + cell->setPort("\\CEAD", st.ffADcepol ? S : pm.module->Not(NEW_ID, S)); } else cell->setPort("\\CEAD", State::S1); @@ -346,10 +346,10 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) A.replace(Q, D); if (st.ffAmux) { SigSpec Y = st.ffAmux->getPort("\\Y"); - SigSpec AB = st.ffAmux->getPort(st.ffAenpol ? "\\B" : "\\A"); + SigSpec AB = st.ffAmux->getPort(st.ffAcepol ? "\\B" : "\\A"); SigSpec S = st.ffAmux->getPort("\\S"); A.replace(Y, AB); - cell->setPort("\\CEA2", st.ffAenpol ? S : pm.module->Not(NEW_ID, S)); + cell->setPort("\\CEA2", st.ffAcepol ? S : pm.module->Not(NEW_ID, S)); } else cell->setPort("\\CEA2", State::S1); @@ -364,10 +364,10 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) B.replace(Q, D); if (st.ffBmux) { SigSpec Y = st.ffBmux->getPort("\\Y"); - SigSpec AB = st.ffBmux->getPort(st.ffBenpol ? "\\B" : "\\A"); + SigSpec AB = st.ffBmux->getPort(st.ffBcepol ? "\\B" : "\\A"); SigSpec S = st.ffBmux->getPort("\\S"); B.replace(Y, AB); - cell->setPort("\\CEB2", st.ffBenpol ? S : pm.module->Not(NEW_ID, S)); + cell->setPort("\\CEB2", st.ffBcepol ? S : pm.module->Not(NEW_ID, S)); } else cell->setPort("\\CEB2", State::S1); @@ -383,11 +383,11 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffCmux) { SigSpec Y = st.ffCmux->getPort("\\Y"); - SigSpec AB = st.ffCmux->getPort(st.ffCenpol ? "\\B" : "\\A"); + SigSpec AB = st.ffCmux->getPort(st.ffCcepol ? "\\B" : "\\A"); SigSpec S = st.ffCmux->getPort("\\S"); C.replace(Y, AB); - cell->setPort("\\CEC", st.ffCenpol ? S : pm.module->Not(NEW_ID, S)); + cell->setPort("\\CEC", st.ffCcepol ? S : pm.module->Not(NEW_ID, S)); } else cell->setPort("\\CEC", State::S1); @@ -403,11 +403,11 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffDmux) { SigSpec Y = st.ffDmux->getPort("\\Y"); - SigSpec AB = st.ffDmux->getPort(st.ffDenpol ? "\\B" : "\\A"); + SigSpec AB = st.ffDmux->getPort(st.ffDcepol ? "\\B" : "\\A"); SigSpec S = st.ffDmux->getPort("\\S"); D_.replace(Y, AB); - cell->setPort("\\CED", st.ffDenpol ? S : pm.module->Not(NEW_ID, S)); + cell->setPort("\\CED", st.ffDcepol ? S : pm.module->Not(NEW_ID, S)); } else cell->setPort("\\CED", State::S1); @@ -418,7 +418,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffM) { if (st.ffMmux) { SigSpec S = st.ffMmux->getPort("\\S"); - cell->setPort("\\CEM", st.ffMenpol ? S : pm.module->Not(NEW_ID, S)); + cell->setPort("\\CEM", st.ffMcepol ? S : pm.module->Not(NEW_ID, S)); pm.autoremove(st.ffMmux); } else @@ -433,7 +433,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.ffP) { if (st.ffPmux) { SigSpec S = st.ffPmux->getPort("\\S"); - cell->setPort("\\CEP", st.ffPenpol ? S : pm.module->Not(NEW_ID, S)); + cell->setPort("\\CEP", st.ffPcepol ? S : pm.module->Not(NEW_ID, S)); st.ffPmux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); } else diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 9d6236d07..ee9ea1312 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -4,18 +4,19 @@ state > unextend state clock state sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM sigP state postAddAB postAddMuxAB -state ffAenpol ffADenpol ffBenpol ffCenpol ffDenpol ffMenpol ffPenpol +state ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol state ffPoffset state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPmux // subpattern state argQ argD -state ffenpol +state ffcepol +state ffmux udata dffD dffQ udata dffclock udata dff dffcemux -udata dffenpol +udata dffcepol match dsp select dsp->type.in(\DSP48E1) @@ -53,7 +54,7 @@ code unextend sigA sigB sigC sigD sigM sigM = P; endcode -code argQ ffAD ffADmux ffADenpol sigA clock +code argQ ffAD ffADmux ffADcepol sigA clock if (param(dsp, \ADREG).as_int() == 0) { argQ = sigA; subpattern(in_dffe); @@ -62,7 +63,7 @@ code argQ ffAD ffADmux ffADenpol sigA clock clock = dffclock; if (dffcemux) { ffADmux = dffcemux; - ffADenpol = dffenpol; + ffADcepol = dffcepol; } sigA = dffD; } @@ -99,7 +100,7 @@ code sigA sigD } endcode -code argQ ffA ffAmux ffAenpol sigA clock ffAD ffADmux ffADenpol +code argQ ffA ffAmux ffAcepol sigA clock ffAD ffADmux ffADcepol // Only search for ffA if there was a pre-adder // (otherwise ffA would have been matched as ffAD) if (preAdd) { @@ -111,7 +112,7 @@ code argQ ffA ffAmux ffAenpol sigA clock ffAD ffADmux ffADenpol clock = dffclock; if (dffcemux) { ffAmux = dffcemux; - ffAenpol = dffenpol; + ffAcepol = dffcepol; } sigA = dffD; } @@ -123,11 +124,11 @@ code argQ ffA ffAmux ffAenpol sigA clock ffAD ffADmux ffADenpol log_assert(!ffA && !ffAmux); std::swap(ffA, ffAD); std::swap(ffAmux, ffADmux); - ffAenpol = ffADenpol; + ffAcepol = ffADcepol; } endcode -code argQ ffB ffBmux ffBenpol sigB clock +code argQ ffB ffBmux ffBcepol sigB clock if (param(dsp, \BREG).as_int() == 0) { argQ = sigB; subpattern(in_dffe); @@ -136,14 +137,14 @@ code argQ ffB ffBmux ffBenpol sigB clock clock = dffclock; if (dffcemux) { ffBmux = dffcemux; - ffBenpol = dffenpol; + ffBcepol = dffcepol; } sigB = dffD; } } endcode -code argQ ffD ffDmux ffDenpol sigD clock +code argQ ffD ffDmux ffDcepol sigD clock if (param(dsp, \DREG).as_int() == 0) { argQ = sigD; subpattern(in_dffe); @@ -152,14 +153,14 @@ code argQ ffD ffDmux ffDenpol sigD clock clock = dffclock; if (dffcemux) { ffDmux = dffcemux; - ffDenpol = dffenpol; + ffDcepol = dffcepol; } sigD = dffD; } } endcode -code argD ffM ffMmux ffMenpol sigM sigP clock +code argD ffM ffMmux ffMcepol sigM sigP clock if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) { argD = sigM; subpattern(out_dffe); @@ -168,7 +169,7 @@ code argD ffM ffMmux ffMenpol sigM sigP clock clock = dffclock; if (dffcemux) { ffMmux = dffcemux; - ffMenpol = dffenpol; + ffMcepol = dffcepol; } sigM = dffQ; } @@ -212,7 +213,7 @@ code sigC sigP } endcode -code argD ffP ffPmux ffPenpol sigP clock +code argD ffP ffPmux ffPcepol sigP clock if (param(dsp, \PREG).as_int() == 0) { // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux if ((ffMmux && !postAdd && nusers(sigP) == 3) || @@ -225,7 +226,7 @@ code argD ffP ffPmux ffPenpol sigP clock clock = dffclock; if (dffcemux) { ffPmux = dffcemux; - ffPenpol = dffenpol; + ffPcepol = dffcepol; } sigP = dffQ; } @@ -250,7 +251,7 @@ code sigC sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A); endcode -code argQ ffC ffCmux ffCenpol sigC clock +code argQ ffC ffCmux ffCcepol sigC clock if (param(dsp, \CREG).as_int() == 0) { argQ = sigC; subpattern(in_dffe); @@ -259,7 +260,7 @@ code argQ ffC ffCmux ffCenpol sigC clock clock = dffclock; if (dffcemux) { ffCmux = dffcemux; - ffCenpol = dffenpol; + ffCcepol = dffcepol; } sigC = dffD; } @@ -273,7 +274,7 @@ endcode // ####################### subpattern in_dffe -arg argQ clock ffenpol +arg argQ clock ffcepol match ff select ff->type.in($dff) @@ -325,15 +326,15 @@ match ffcemux filter offset+GetSize(argQ) <= GetSize(port(ffcemux, \Y)) filter port(ffcemux, AB).extract(offset, GetSize(argQ)) == argQ define pol (AB == \A) - set ffenpol pol + set ffcepol pol semioptional endmatch code if (ffcemux) { dffcemux = ffcemux; - dffenpol = ffenpol; - dffD = port(ffcemux, dffenpol ? \B : \A); + dffcepol = ffcepol; + dffD = port(ffcemux, dffcepol ? \B : \A); } else dffcemux = nullptr; @@ -342,42 +343,43 @@ endcode // ####################### subpattern out_dffe -arg argD clock ffenpol -arg unextend +arg argD clock ffcepol +arg unextend ffmux -match ffmux - select ffmux->type.in($mux) - // ffmux output must have two users: ffmux and ff.D - select nusers(port(ffmux, \Y)) == 2 - filter GetSize(port(ffmux, \Y)) >= GetSize(argD) +match ffcemux + select ffcemux->type.in($mux) + // ffcemux output must have two users: ffcemux and ff.D + select nusers(port(ffcemux, \Y)) == 2 + filter GetSize(port(ffcemux, \Y)) >= GetSize(argD) choice BA {\B, \A} - // new-value net must have exactly two users: (upstream) and ffmux - select nusers(port(ffmux, BA)) == 2 + // new-value net must have exactly two users: (upstream) and ffcemux + select nusers(port(ffcemux, BA)) == 2 - slice offset GetSize(port(ffmux, \Y)) - filter offset+GetSize(argD) <= GetSize(port(ffmux, \Y)) - filter port(ffmux, BA).extract(offset, GetSize(argD)) == argD + slice offset GetSize(port(ffcemux, \Y)) + filter offset+GetSize(argD) <= GetSize(port(ffcemux, \Y)) + filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD define AB (BA == \B ? \A : \B) - // keep-last-value net must have at least three users: ffmux, ff, downstream sink(s) - select nusers(port(ffmux, AB)) >= 3 + // keep-last-value net must have at least three users: ffcemux, ff, downstream sink(s) + select nusers(port(ffcemux, AB)) >= 3 - filter GetSize(unextend(port(ffmux, BA))) <= GetSize(argD) - filter unextend(port(ffmux, BA)) == argD.extract(0, GetSize(unextend(port(ffmux, BA)))) + filter GetSize(unextend(port(ffcemux, BA))) <= GetSize(argD) + filter unextend(port(ffcemux, BA)) == argD.extract(0, GetSize(unextend(port(ffcemux, BA)))) // Remaining bits on argD must not have any other users - filter nusers(argD.extract_end(GetSize(unextend(port(ffmux, BA))))) <= 1 + filter nusers(argD.extract_end(GetSize(unextend(port(ffcemux, BA))))) <= 1 define pol (AB == \A) - set ffenpol pol + set ffcepol pol semioptional endmatch -code argD - if (ffmux) { - dffcemux = ffmux; - dffenpol = ffenpol; - argD = port(ffmux, \Y); +code argD ffmux + if (ffcemux) { + dffcemux = ffcemux; + dffcepol = ffcepol; + argD = port(ffcemux, \Y); + ffmux = ffcemux; } else dffcemux = nullptr; @@ -389,7 +391,7 @@ match ff_enable // DSP48E1 does not support clock inversion select param(ff_enable, \CLK_POLARITY).as_bool() index port(ff_enable, \D) === argD - index port(ff_enable, \Q) === port(ffmux, ffenpol ? \A : \B) + index port(ff_enable, \Q) === port(ffmux, ffcepol ? \A : \B) endmatch match ff From af147d14300a8fbff2db8d823cf3622ec5a81ca6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 20:51:48 -0700 Subject: [PATCH 224/356] Add support for RSTP --- passes/pmgen/xilinx_dsp.cc | 16 ++++++-- passes/pmgen/xilinx_dsp.pmg | 80 +++++++++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index a5fa67083..fe82b1307 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -273,7 +273,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("postAdd: %s\n", log_id(st.postAdd, "--")); log("postAddMux: %s\n", log_id(st.postAddMux, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); - log("ffPmux: %s\n", log_id(st.ffPmux, "--")); + log("ffPcemux: %s\n", log_id(st.ffPcemux, "--")); + log("ffPrstmux: %s\n", log_id(st.ffPrstmux, "--")); #endif log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); @@ -431,10 +432,17 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) pm.autoremove(st.ffM); } if (st.ffP) { - if (st.ffPmux) { - SigSpec S = st.ffPmux->getPort("\\S"); + if (st.ffPrstmux) { + SigSpec S = st.ffPrstmux->getPort("\\S"); + cell->setPort("\\RSTP", st.ffPrstpol ? S : pm.module->Not(NEW_ID, S)); + st.ffPrstmux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); + } + else + cell->setPort("\\RSTP", State::S1); + if (st.ffPcemux) { + SigSpec S = st.ffPcemux->getPort("\\S"); cell->setPort("\\CEP", st.ffPcepol ? S : pm.module->Not(NEW_ID, S)); - st.ffPmux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); + st.ffPcemux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); } else cell->setPort("\\CEP", State::S1); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index ee9ea1312..05837d057 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -4,19 +4,18 @@ state > unextend state clock state sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM sigP state postAddAB postAddMuxAB -state ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol +state ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol ffPrstpol state ffPoffset -state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPmux +state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPcemux ffPrstmux // subpattern state argQ argD -state ffcepol -state ffmux +state ffcepol ffrstpol udata dffD dffQ udata dffclock -udata dff dffcemux -udata dffcepol +udata dff dffcemux dffrstmux +udata dffcepol dffrstpol match dsp select dsp->type.in(\DSP48E1) @@ -213,11 +212,11 @@ code sigC sigP } endcode -code argD ffP ffPmux ffPcepol sigP clock +code argD ffP ffPcemux ffPrstmux ffPcepol ffPrstpol sigP clock if (param(dsp, \PREG).as_int() == 0) { - // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux + // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPcemux if ((ffMmux && !postAdd && nusers(sigP) == 3) || - // Otherwise new-value net must have exactly two users: dsp and ffPmux + // Otherwise new-value net must have exactly two users: dsp and ffPcemux ((!ffMmux || postAdd) && nusers(sigP) == 2)) { argD = sigP; subpattern(out_dffe); @@ -225,8 +224,10 @@ code argD ffP ffPmux ffPcepol sigP clock ffP = dff; clock = dffclock; if (dffcemux) { - ffPmux = dffcemux; + ffPcemux = dffcemux; ffPcepol = dffcepol; + ffPrstmux = dffrstmux; + ffPrstpol = dffrstpol; } sigP = dffQ; } @@ -343,8 +344,8 @@ endcode // ####################### subpattern out_dffe -arg argD clock ffcepol -arg unextend ffmux +arg argD argQ clock +arg unextend match ffcemux select ffcemux->type.in($mux) @@ -356,14 +357,11 @@ match ffcemux // new-value net must have exactly two users: (upstream) and ffcemux select nusers(port(ffcemux, BA)) == 2 - slice offset GetSize(port(ffcemux, \Y)) - filter offset+GetSize(argD) <= GetSize(port(ffcemux, \Y)) - filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD - define AB (BA == \B ? \A : \B) // keep-last-value net must have at least three users: ffcemux, ff, downstream sink(s) select nusers(port(ffcemux, AB)) >= 3 + slice offset GetSize(port(ffcemux, \Y)) filter GetSize(unextend(port(ffcemux, BA))) <= GetSize(argD) filter unextend(port(ffcemux, BA)) == argD.extract(0, GetSize(unextend(port(ffcemux, BA)))) // Remaining bits on argD must not have any other users @@ -374,24 +372,62 @@ match ffcemux semioptional endmatch -code argD ffmux +code argD argQ if (ffcemux) { dffcemux = ffcemux; dffcepol = ffcepol; argD = port(ffcemux, \Y); - ffmux = ffcemux; + argQ = port(ffcemux, ffcepol ? \A : \B); } else dffcemux = nullptr; endcode +match ffrstmux + if !argQ.empty() + select ffrstmux->type.in($mux) + // ffrstmux output must have two users: ffrstmux and ff.D + select nusers(port(ffrstmux, \Y)) == 2 + filter GetSize(port(ffrstmux, \Y)) >= GetSize(argD) + + choice BA {\B, \A} + // DSP48E1 only supports reset to zero + select port(ffrstmux, BA).is_fully_zero() + + define AB (BA == \B ? \A : \B) + // keep-last-value net must have exactly 2 users: ffrstmux, ffcemux/ + select nusers(port(ffrstmux, AB)) == 2 + + slice offset GetSize(port(ffrstmux, \Y)) + filter GetSize(port(ffrstmux, AB)) <= GetSize(argD) + filter port(ffrstmux, AB) == argD.extract(0, GetSize(port(ffrstmux, AB))) + // Remaining bits on argD must not have any other users + filter nusers(argD.extract_end(GetSize(port(ffrstmux, AB)))) <= 1 + + define pol (AB == \A) + set ffrstpol pol + semioptional +endmatch + +code argD argQ + if (ffrstmux) { + dffrstmux = ffrstmux; + dffrstpol = ffrstpol; + argD = port(ffrstmux, \Y); + } + else { + dffrstmux = nullptr; + argQ = SigSpec(); + } +endcode + match ff_enable - if ffmux + if !argQ.empty() select ff_enable->type.in($dff) // DSP48E1 does not support clock inversion select param(ff_enable, \CLK_POLARITY).as_bool() index port(ff_enable, \D) === argD - index port(ff_enable, \Q) === port(ffmux, ffcepol ? \A : \B) + index port(ff_enable, \Q) === argQ endmatch match ff @@ -421,7 +457,7 @@ code } dffclock = port(dff, \CLK); } - // No enable mux possible without flop - else if (ffmux) + // No enable/reset mux possible without flop + else if (ffcemux || ffrstmux) reject; endcode From 37a34eeb0438261f432917fb5d60a5320f56a8de Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 20:56:13 -0700 Subject: [PATCH 225/356] Fix RSTP --- passes/pmgen/xilinx_dsp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index fe82b1307..055b3d6aa 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -438,7 +438,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) st.ffPrstmux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); } else - cell->setPort("\\RSTP", State::S1); + cell->setPort("\\RSTP", State::S0); if (st.ffPcemux) { SigSpec S = st.ffPcemux->getPort("\\S"); cell->setPort("\\CEP", st.ffPcepol ? S : pm.module->Not(NEW_ID, S)); From b08797da6bf0061073dc662441e03b2fd218f11f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 21:33:14 -0700 Subject: [PATCH 226/356] Only pack out registers if \init is zero or x; then remove \init from PREG --- passes/pmgen/xilinx_dsp.cc | 10 ++++++++++ passes/pmgen/xilinx_dsp.pmg | 12 ++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 055b3d6aa..5d50c7795 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -451,6 +451,16 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) P.replace(pm.sigmap(D), Q); st.ffP->connections_.at("\\Q").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); + for (auto c : Q.chunks()) { + auto it = c.wire->attributes.find("\\init"); + if (it == c.wire->attributes.end()) + continue; + for (int i = c.offset; i < c.offset+c.width; i++) { + log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); + it->second[i] = State::Sx; + } + } + cell->setParam("\\PREG", State::S1); } diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 05837d057..7db8e95a6 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -290,8 +290,8 @@ endmatch code argQ if (ff) { - for (auto b : argQ) - if (b.wire->get_bool_attribute(\keep)) + for (auto c : argQ.chunks()) + if (c.wire->get_bool_attribute(\keep)) reject; if (clock != SigBit()) { @@ -447,9 +447,13 @@ code if (dff) { dffQ = port(dff, \Q); - for (auto b : dffQ) - if (b.wire->get_bool_attribute(\keep)) + for (auto c : dffQ.chunks()) { + if (c.wire->get_bool_attribute(\keep)) reject; + Const init = c.wire->attributes.at(\init, State::Sx); + if (!init.is_fully_undef() && !init.is_fully_zero()) + reject; + } if (clock != SigBit()) { if (port(dff, \CLK) != clock) From ded805ae5d9d9884be319a710f159007e73c9636 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 07:34:14 -0700 Subject: [PATCH 227/356] Add support for RSTM --- passes/pmgen/xilinx_dsp.cc | 31 +++++--- passes/pmgen/xilinx_dsp.pmg | 152 +++++++++++++++++++++--------------- 2 files changed, 109 insertions(+), 74 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 5d50c7795..0700d3f61 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -269,7 +269,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("ffDmux: %s\n", log_id(st.ffDmux, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); log("ffM: %s\n", log_id(st.ffM, "--")); - log("ffMmux: %s\n", log_id(st.ffMmux, "--")); + log("ffMcemux: %s\n", log_id(st.ffMcemux, "--")); + log("ffMrstmux: %s\n", log_id(st.ffMrstmux, "--")); log("postAdd: %s\n", log_id(st.postAdd, "--")); log("postAddMux: %s\n", log_id(st.postAddMux, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); @@ -417,38 +418,48 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) cell->setParam("\\DREG", 1); } if (st.ffM) { - if (st.ffMmux) { - SigSpec S = st.ffMmux->getPort("\\S"); + if (st.ffMrstmux) { + SigSpec S = st.ffMrstmux->getPort("\\S"); + cell->setPort("\\RSTM", st.ffMrstpol ? S : pm.module->Not(NEW_ID, S)); + } + else + cell->setPort("\\RSTM", State::S0); + if (st.ffMcemux) { + SigSpec S = st.ffMcemux->getPort("\\S"); cell->setPort("\\CEM", st.ffMcepol ? S : pm.module->Not(NEW_ID, S)); - pm.autoremove(st.ffMmux); } else cell->setPort("\\CEM", State::S1); SigSpec D = st.ffM->getPort("\\D"); SigSpec Q = st.ffM->getPort("\\Q"); - P.replace(pm.sigmap(D), Q); + st.ffM->connections_.at("\\Q").replace(st.sigM, pm.module->addWire(NEW_ID, GetSize(st.sigM))); + + for (auto c : Q.chunks()) { + auto it = c.wire->attributes.find("\\init"); + if (it == c.wire->attributes.end()) + continue; + for (int i = c.offset; i < c.offset+c.width; i++) { + log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); + it->second[i] = State::Sx; + } + } cell->setParam("\\MREG", State::S1); - pm.autoremove(st.ffM); } if (st.ffP) { if (st.ffPrstmux) { SigSpec S = st.ffPrstmux->getPort("\\S"); cell->setPort("\\RSTP", st.ffPrstpol ? S : pm.module->Not(NEW_ID, S)); - st.ffPrstmux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); } else cell->setPort("\\RSTP", State::S0); if (st.ffPcemux) { SigSpec S = st.ffPcemux->getPort("\\S"); cell->setPort("\\CEP", st.ffPcepol ? S : pm.module->Not(NEW_ID, S)); - st.ffPcemux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); } else cell->setPort("\\CEP", State::S1); - SigSpec D = st.ffP->getPort("\\D"); SigSpec Q = st.ffP->getPort("\\Q"); - P.replace(pm.sigmap(D), Q); st.ffP->connections_.at("\\Q").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); for (auto c : Q.chunks()) { diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 7db8e95a6..686efd8c4 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -4,14 +4,15 @@ state > unextend state clock state sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM sigP state postAddAB postAddMuxAB -state ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol ffPrstpol +state ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffMrstpol ffPcepol ffPrstpol state ffPoffset -state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPcemux ffPrstmux +state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux // subpattern state argQ argD state ffcepol ffrstpol +state ffoffset udata dffD dffQ udata dffclock udata dff dffcemux dffrstmux @@ -159,7 +160,7 @@ code argQ ffD ffDmux ffDcepol sigD clock } endcode -code argD ffM ffMmux ffMcepol sigM sigP clock +code argD ffM ffMcemux ffMrstmux ffMcepol ffMrstpol sigM sigP clock if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) { argD = sigM; subpattern(out_dffe); @@ -167,8 +168,10 @@ code argD ffM ffMmux ffMcepol sigM sigP clock ffM = dff; clock = dffclock; if (dffcemux) { - ffMmux = dffcemux; + ffMcemux = dffcemux; + ffMrstmux = dffrstmux; ffMcepol = dffcepol; + ffMrstpol = dffrstpol; } sigM = dffQ; } @@ -185,8 +188,8 @@ match postAdd select nusers(port(postAdd, \Y)) == 2 choice AB {\A, \B} select nusers(port(postAdd, AB)) <= 3 - filter ffMmux || nusers(port(postAdd, AB)) == 2 - filter !ffMmux || nusers(port(postAdd, AB)) == 3 + filter ffMcemux || nusers(port(postAdd, AB)) == 2 + filter !ffMcemux || nusers(port(postAdd, AB)) == 3 filter GetSize(unextend(port(postAdd, AB))) <= GetSize(sigP) filter unextend(port(postAdd, AB)) == sigP.extract(0, GetSize(unextend(port(postAdd, AB)))) filter nusers(sigP.extract_end(GetSize(unextend(port(postAdd, AB))))) <= 1 @@ -214,10 +217,10 @@ endcode code argD ffP ffPcemux ffPrstmux ffPcepol ffPrstpol sigP clock if (param(dsp, \PREG).as_int() == 0) { - // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPcemux - if ((ffMmux && !postAdd && nusers(sigP) == 3) || + // If ffMcemux and no postAdd new-value net must have exactly three users: ffMcemux, ffM and ffPcemux + if ((ffMcemux && !postAdd && nusers(sigP) == 3) || // Otherwise new-value net must have exactly two users: dsp and ffPcemux - ((!ffMmux || postAdd) && nusers(sigP) == 2)) { + ((!ffMcemux || postAdd) && nusers(sigP) == 2)) { argD = sigP; subpattern(out_dffe); if (dff) { @@ -347,107 +350,130 @@ subpattern out_dffe arg argD argQ clock arg unextend +code + dff = nullptr; +endcode + match ffcemux select ffcemux->type.in($mux) // ffcemux output must have two users: ffcemux and ff.D select nusers(port(ffcemux, \Y)) == 2 - filter GetSize(port(ffcemux, \Y)) >= GetSize(argD) - choice BA {\B, \A} - // new-value net must have exactly two users: (upstream) and ffcemux - select nusers(port(ffcemux, BA)) == 2 - - define AB (BA == \B ? \A : \B) + choice AB {\A, \B} // keep-last-value net must have at least three users: ffcemux, ff, downstream sink(s) select nusers(port(ffcemux, AB)) >= 3 slice offset GetSize(port(ffcemux, \Y)) - filter GetSize(unextend(port(ffcemux, BA))) <= GetSize(argD) - filter unextend(port(ffcemux, BA)) == argD.extract(0, GetSize(unextend(port(ffcemux, BA)))) - // Remaining bits on argD must not have any other users - filter nusers(argD.extract_end(GetSize(unextend(port(ffcemux, BA))))) <= 1 - - define pol (AB == \A) + define BA (AB == \A ? \B : \A) + index port(ffcemux, BA)[offset] === argD[0] + set ffoffset offset + define pol (BA == \B) set ffcepol pol + semioptional endmatch code argD argQ + dffcemux = ffcemux; if (ffcemux) { + SigSpec BA = port(ffcemux, ffcepol ? \B : \A); + if (ffoffset + GetSize(argD) > GetSize(BA)) + reject; + + for (int i = 1; i < GetSize(argD); i++) + if (BA[ffoffset+i] != argD[i]) + reject; + + SigSpec Y = port(ffcemux, \Y); + argQ = argD; + argD.replace(BA, Y); + argQ.replace(BA, port(ffcemux, ffcepol ? \A : \B)); + dffcemux = ffcemux; dffcepol = ffcepol; - argD = port(ffcemux, \Y); - argQ = port(ffcemux, ffcepol ? \A : \B); } - else - dffcemux = nullptr; endcode match ffrstmux - if !argQ.empty() select ffrstmux->type.in($mux) // ffrstmux output must have two users: ffrstmux and ff.D select nusers(port(ffrstmux, \Y)) == 2 - filter GetSize(port(ffrstmux, \Y)) >= GetSize(argD) choice BA {\B, \A} // DSP48E1 only supports reset to zero select port(ffrstmux, BA).is_fully_zero() - define AB (BA == \B ? \A : \B) - // keep-last-value net must have exactly 2 users: ffrstmux, ffcemux/ - select nusers(port(ffrstmux, AB)) == 2 - slice offset GetSize(port(ffrstmux, \Y)) - filter GetSize(port(ffrstmux, AB)) <= GetSize(argD) - filter port(ffrstmux, AB) == argD.extract(0, GetSize(port(ffrstmux, AB))) - // Remaining bits on argD must not have any other users - filter nusers(argD.extract_end(GetSize(port(ffrstmux, AB)))) <= 1 + define AB (BA == \B ? \A : \B) + index port(ffrstmux, AB)[offset] === argD[0] + filter !ffcemux || ffoffset == offset + set ffoffset offset define pol (AB == \A) set ffrstpol pol + semioptional endmatch code argD argQ + dffrstmux = ffrstmux; if (ffrstmux) { + SigSpec AB = port(ffrstmux, ffcepol ? \A : \B); + if (ffoffset + GetSize(argD) > GetSize(AB)) + reject; + + for (int i = 1; i < GetSize(argD); i++) + if (AB[ffoffset+i] != argD[i]) + reject; + + SigSpec Y = port(ffrstmux, \Y); + argD.replace(AB, Y); + dffrstmux = ffrstmux; dffrstpol = ffrstpol; - argD = port(ffrstmux, \Y); - } - else { - dffrstmux = nullptr; - argQ = SigSpec(); } endcode -match ff_enable - if !argQ.empty() - select ff_enable->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ff_enable, \CLK_POLARITY).as_bool() - index port(ff_enable, \D) === argD - index port(ff_enable, \Q) === argQ -endmatch - match ff - if !ff_enable select ff->type.in($dff) // DSP48E1 does not support clock inversion select param(ff, \CLK_POLARITY).as_bool() - index port(ff, \D) === argD + + slice offset GetSize(port(ff, \D)) + index port(ff, \D)[offset] === argD[0] + + filter (!ffcemux && !ffrstmux) || ffoffset == offset + set ffoffset offset + semioptional endmatch -code - if (ff_enable) - dff = ff_enable; - else - dff = ff; - if (dff) { - dffQ = port(dff, \Q); +code argQ + if (ff) { + if (clock != SigBit()) { + if (port(ff, \CLK) != clock) + reject; + } - for (auto c : dffQ.chunks()) { + SigSpec D = port(ff, \D); + if (ffoffset + GetSize(argD) > GetSize(D)) + reject; + for (int i = 1; i < GetSize(argD); i++) + if (D[ffoffset+i] != argD[i]) + reject; + + SigSpec Q = port(ff, \Q); + if (ffcemux) { + for (int i = 0; i < GetSize(argQ); i++) + if (Q[ffoffset+i] != argQ[i]) + reject; + } + else { + argQ = argD; + argQ.replace(D, Q); + } + + for (auto c : argQ.chunks()) { if (c.wire->get_bool_attribute(\keep)) reject; Const init = c.wire->attributes.at(\init, State::Sx); @@ -455,13 +481,11 @@ code reject; } - if (clock != SigBit()) { - if (port(dff, \CLK) != clock) - reject; - } + dff = ff; + dffQ = argQ; dffclock = port(dff, \CLK); } // No enable/reset mux possible without flop - else if (ffcemux || ffrstmux) + else if (dffcemux || dffrstmux) reject; endcode From 36d6db7f8aac6568acc2fb2d4ea5a5427d00d667 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 09:09:08 -0700 Subject: [PATCH 228/356] Extend test for RSTP and RSTM --- tests/xilinx/macc.v | 36 ++++++++++++++++++++++++++++++++++-- tests/xilinx/macc.ys | 17 ++++++++++++++++- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/tests/xilinx/macc.v b/tests/xilinx/macc.v index 0bb673316..c6ad2a578 100644 --- a/tests/xilinx/macc.v +++ b/tests/xilinx/macc.v @@ -35,7 +35,39 @@ always @(posedge clk) adder_out <= old_result + mult_reg; end - // Output accumulation result - assign accum_out = adder_out; +// Output accumulation result +assign accum_out = adder_out; + +endmodule + +// Adapted variant of above +module macc2 # (parameter SIZEIN = 16, SIZEOUT = 40) ( + input clk, ce, rst, + input signed [SIZEIN-1:0] a, b, + output signed [SIZEOUT-1:0] accum_out +); +// Declare registers for intermediate values +reg signed [SIZEIN-1:0] a_reg, b_reg; +reg rst_reg; +reg signed [2*SIZEIN-1:0] mult_reg; +reg signed [SIZEOUT-1:0] adder_out, old_result; +always @(posedge clk) begin + if (ce) + begin + a_reg <= a; + b_reg <= b; + mult_reg <= a_reg * b_reg; + rst_reg <= rst; + // Store accumulation result into a register + adder_out <= adder_out + mult_reg; + end + if (rst) begin + mult_reg <= 0; + adder_out <= 0; + end +end + +// Output accumulation result +assign accum_out = adder_out; endmodule diff --git a/tests/xilinx/macc.ys b/tests/xilinx/macc.ys index de408162c..294b83c69 100644 --- a/tests/xilinx/macc.ys +++ b/tests/xilinx/macc.ys @@ -1,6 +1,8 @@ read_verilog macc.v +design -save read + proc -hierarchy -auto-top +hierarchy -top macc #equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx ### TODO equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx miter -equiv -flatten -make_assert -make_outputs gold gate miter @@ -11,3 +13,16 @@ select -assert-count 1 t:BUFG select -assert-count 1 t:FDRE select -assert-count 1 t:DSP48E1 select -assert-none t:BUFG t:FDRE t:DSP48E1 %% t:* %D + +design -load read +proc +hierarchy -top macc2 +#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx ### TODO +equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -seq 10 -show-inputs -show-outputs miter +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd macc2 # Constrain all select calls below inside the top module +select -assert-count 1 t:BUFG +select -assert-count 1 t:DSP48E1 +select -assert-none t:BUFG t:DSP48E1 %% t:* %D From 6a95ecd41d31a841537357a1ffaabf4ea5c7ed93 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 10:13:13 -0700 Subject: [PATCH 229/356] Update test with a/b reset --- tests/xilinx/macc.v | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/xilinx/macc.v b/tests/xilinx/macc.v index c6ad2a578..5dc99ab8e 100644 --- a/tests/xilinx/macc.v +++ b/tests/xilinx/macc.v @@ -61,10 +61,12 @@ always @(posedge clk) begin // Store accumulation result into a register adder_out <= adder_out + mult_reg; end - if (rst) begin + if (rst) begin + a_reg <= 0; + b_reg <= 0; mult_reg <= 0; adder_out <= 0; - end + end end // Output accumulation result From 0d709d2bb56fed3a1100b72071ca8d584746a095 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 10:15:19 -0700 Subject: [PATCH 230/356] Add support for A/B/C/D/AD reset --- passes/pmgen/xilinx_dsp.cc | 121 +++++++++------------------ passes/pmgen/xilinx_dsp.pmg | 159 +++++++++++++++++++++++------------- 2 files changed, 141 insertions(+), 139 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 0700d3f61..fdd0ac2fa 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -257,25 +257,16 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) #if 1 log("\n"); log("preAdd: %s\n", log_id(st.preAdd, "--")); - log("ffAD: %s\n", log_id(st.ffAD, "--")); - log("ffADmux: %s\n", log_id(st.ffADmux, "--")); - log("ffA: %s\n", log_id(st.ffA, "--")); - log("ffAmux: %s\n", log_id(st.ffAmux, "--")); - log("ffB: %s\n", log_id(st.ffB, "--")); - log("ffBmux: %s\n", log_id(st.ffBmux, "--")); - log("ffC: %s\n", log_id(st.ffC, "--")); - log("ffCmux: %s\n", log_id(st.ffCmux, "--")); - log("ffD: %s\n", log_id(st.ffD, "--")); - log("ffDmux: %s\n", log_id(st.ffDmux, "--")); + log("ffAD: %s %s %s\n", log_id(st.ffAD, "--"), log_id(st.ffADcemux, "--"), log_id(st.ffADrstmux, "--")); + log("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAcemux, "--"), log_id(st.ffArstmux, "--")); + log("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBcemux, "--"), log_id(st.ffBrstmux, "--")); + log("ffC: %s %s %s\n", log_id(st.ffC, "--"), log_id(st.ffCcemux, "--"), log_id(st.ffCrstmux, "--")); + log("ffD: %s %s %s\n", log_id(st.ffD, "--"), log_id(st.ffDcemux, "--"), log_id(st.ffDrstmux, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); - log("ffM: %s\n", log_id(st.ffM, "--")); - log("ffMcemux: %s\n", log_id(st.ffMcemux, "--")); - log("ffMrstmux: %s\n", log_id(st.ffMrstmux, "--")); + log("ffM: %s %s %s\n", log_id(st.ffM, "--"), log_id(st.ffMcemux, "--"), log_id(st.ffMrstmux, "--")); log("postAdd: %s\n", log_id(st.postAdd, "--")); log("postAddMux: %s\n", log_id(st.postAddMux, "--")); - log("ffP: %s\n", log_id(st.ffP, "--")); - log("ffPcemux: %s\n", log_id(st.ffPcemux, "--")); - log("ffPrstmux: %s\n", log_id(st.ffPrstmux, "--")); + log("ffP: %s %s %s\n", log_id(st.ffP, "--"), log_id(st.ffPcemux, "--"), log_id(st.ffPrstmux, "--")); #endif log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); @@ -297,8 +288,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) cell->connections_.at("\\INMODE") = Const::from_string("00100"); if (st.ffAD) { - if (st.ffADmux) { - SigSpec S = st.ffADmux->getPort("\\S"); + if (st.ffADcemux) { + SigSpec S = st.ffADcemux->getPort("\\S"); cell->setPort("\\CEAD", st.ffADcepol ? S : pm.module->Not(NEW_ID, S)); } else @@ -341,80 +332,46 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) { cell->setPort("\\CLK", st.clock); - if (st.ffA) { - SigSpec A = cell->getPort("\\A"); - SigSpec D = st.ffA->getPort("\\D"); - SigSpec Q = pm.sigmap(st.ffA->getPort("\\Q")); + auto f = [&pm,cell](IdString port, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) { + SigSpec A = cell->getPort(port); + SigSpec D = ff->getPort("\\D"); + SigSpec Q = pm.sigmap(ff->getPort("\\Q")); A.replace(Q, D); - if (st.ffAmux) { - SigSpec Y = st.ffAmux->getPort("\\Y"); - SigSpec AB = st.ffAmux->getPort(st.ffAcepol ? "\\B" : "\\A"); - SigSpec S = st.ffAmux->getPort("\\S"); + if (rstmux) { + SigSpec Y = rstmux->getPort("\\Y"); + SigSpec AB = rstmux->getPort(rstpol ? "\\A" : "\\B"); + SigSpec S = rstmux->getPort("\\S"); A.replace(Y, AB); - cell->setPort("\\CEA2", st.ffAcepol ? S : pm.module->Not(NEW_ID, S)); + cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S)); } else - cell->setPort("\\CEA2", State::S1); - cell->setPort("\\A", A); + cell->setPort(rstport, State::S0); + if (cemux) { + SigSpec Y = cemux->getPort("\\Y"); + SigSpec BA = cemux->getPort(cepol ? "\\B" : "\\A"); + SigSpec S = cemux->getPort("\\S"); + A.replace(Y, BA); + cell->setPort(ceport, cepol ? S : pm.module->Not(NEW_ID, S)); + } + else + cell->setPort(ceport, State::S1); + cell->setPort(port, A); + }; + if (st.ffA) { + f("\\A", st.ffA, st.ffAcemux, st.ffAcepol, "\\CEA2", st.ffArstmux, st.ffArstpol, "\\RSTA"); cell->setParam("\\AREG", 1); } if (st.ffB) { - SigSpec B = cell->getPort("\\B"); - SigSpec D = st.ffB->getPort("\\D"); - SigSpec Q = st.ffB->getPort("\\Q"); - B.replace(Q, D); - if (st.ffBmux) { - SigSpec Y = st.ffBmux->getPort("\\Y"); - SigSpec AB = st.ffBmux->getPort(st.ffBcepol ? "\\B" : "\\A"); - SigSpec S = st.ffBmux->getPort("\\S"); - B.replace(Y, AB); - cell->setPort("\\CEB2", st.ffBcepol ? S : pm.module->Not(NEW_ID, S)); - } - else - cell->setPort("\\CEB2", State::S1); - cell->setPort("\\B", B); - + f("\\B", st.ffB, st.ffBcemux, st.ffBcepol, "\\CEB2", st.ffBrstmux, st.ffBrstpol, "\\RSTB"); cell->setParam("\\BREG", 1); } if (st.ffC) { - SigSpec C = cell->getPort("\\C"); - SigSpec D = st.ffC->getPort("\\D"); - SigSpec Q = st.ffC->getPort("\\Q"); - C.replace(Q, D); - - if (st.ffCmux) { - SigSpec Y = st.ffCmux->getPort("\\Y"); - SigSpec AB = st.ffCmux->getPort(st.ffCcepol ? "\\B" : "\\A"); - SigSpec S = st.ffCmux->getPort("\\S"); - C.replace(Y, AB); - - cell->setPort("\\CEC", st.ffCcepol ? S : pm.module->Not(NEW_ID, S)); - } - else - cell->setPort("\\CEC", State::S1); - cell->setPort("\\C", C); - + f("\\C", st.ffC, st.ffCcemux, st.ffCcepol, "\\CEC", st.ffCrstmux, st.ffCrstpol, "\\RSTC"); cell->setParam("\\CREG", 1); } if (st.ffD) { - SigSpec D_ = cell->getPort("\\D"); - SigSpec D = st.ffD->getPort("\\D"); - SigSpec Q = st.ffD->getPort("\\Q"); - D_.replace(Q, D); - - if (st.ffDmux) { - SigSpec Y = st.ffDmux->getPort("\\Y"); - SigSpec AB = st.ffDmux->getPort(st.ffDcepol ? "\\B" : "\\A"); - SigSpec S = st.ffDmux->getPort("\\S"); - D_.replace(Y, AB); - - cell->setPort("\\CED", st.ffDcepol ? S : pm.module->Not(NEW_ID, S)); - } - else - cell->setPort("\\CED", State::S1); - cell->setPort("\\D", D_); - + f("\\D", st.ffD, st.ffDcemux, st.ffDcepol, "\\CED", st.ffDrstmux, st.ffDrstpol, "\\RSTD"); cell->setParam("\\DREG", 1); } if (st.ffM) { @@ -516,9 +473,9 @@ struct XilinxDspPass : public Pass { log("\n"); log(" xilinx_dsp [options] [selection]\n"); log("\n"); - log("Pack input registers (A, B, C, D, AD; with optional enable), pipeline registers\n"); - log("(M; with optional enable), output registers (P; with optional enable),\n"); - log("pre-adder and/or post-adder into Xilinx DSP resources.\n"); + log("Pack input registers (A, B, C, D, AD; with optional enable/reset), pipeline\n"); + log("registers (M; with optional enable/reset), output registers (P; with optional\n"); + log("enable/reset), pre-adder and/or post-adder into Xilinx DSP resources.\n"); log("\n"); log("Multiply-accumulate operations using the post-adder with feedback on the 'C'\n"); log("input will be folded into the DSP. In this scenario only, the 'C' input can be\n"); @@ -528,8 +485,6 @@ struct XilinxDspPass : public Pass { log("where 'P' is right-shifted by 18-bits and used as an input to the post-adder (a\n"); log("pattern common for summing partial products to implement wide multiplies).\n"); log("\n"); - log("Not currently supported: reset (RST*) inputs on any register.\n"); - log("\n"); log("\n"); log("Experimental feature: addition/subtractions less than 12 or 24 bits with the\n"); log("'(* use_dsp=\"simd\" *)' attribute attached to the output wire or attached to\n"); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 686efd8c4..6e726d1c2 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -2,12 +2,13 @@ pattern xilinx_dsp state > unextend state clock -state sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM sigP +state sigA sigffAcemuxY sigB sigffBcemuxY sigC sigffCcemuxY sigD sigffDcemuxY sigM sigP state postAddAB postAddMuxAB -state ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffMrstpol ffPcepol ffPrstpol -state ffPoffset +state ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol +state ffArstpol ffADrstpol ffBrstpol ffCrstpol ffDrstpol ffMrstpol ffPrstpol -state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux +state ffAD ffADcemux ffADrstmux ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffC ffCcemux ffCrstmux +state ffD ffDcemux ffDrstmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux // subpattern state argQ argD @@ -54,7 +55,7 @@ code unextend sigA sigB sigC sigD sigM sigM = P; endcode -code argQ ffAD ffADmux ffADcepol sigA clock +code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock if (param(dsp, \ADREG).as_int() == 0) { argQ = sigA; subpattern(in_dffe); @@ -62,8 +63,10 @@ code argQ ffAD ffADmux ffADcepol sigA clock ffAD = dff; clock = dffclock; if (dffcemux) { - ffADmux = dffcemux; + ffADcemux = dffcemux; + ffADrstmux = dffrstmux; ffADcepol = dffcepol; + ffADrstpol = dffrstpol; } sigA = dffD; } @@ -100,7 +103,7 @@ code sigA sigD } endcode -code argQ ffA ffAmux ffAcepol sigA clock ffAD ffADmux ffADcepol +code argQ ffA ffAcemux ffArstmux ffAcepol ffArstpol sigA clock ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol // Only search for ffA if there was a pre-adder // (otherwise ffA would have been matched as ffAD) if (preAdd) { @@ -111,8 +114,10 @@ code argQ ffA ffAmux ffAcepol sigA clock ffAD ffADmux ffADcepol ffA = dff; clock = dffclock; if (dffcemux) { - ffAmux = dffcemux; + ffAcemux = dffcemux; + ffArstmux = dffrstmux; ffAcepol = dffcepol; + ffArstpol = dffrstpol; } sigA = dffD; } @@ -121,14 +126,16 @@ code argQ ffA ffAmux ffAcepol sigA clock ffAD ffADmux ffADcepol // And if there wasn't a pre-adder, // move AD register to A else if (ffAD) { - log_assert(!ffA && !ffAmux); + log_assert(!ffA && !ffAcemux && !ffArstmux); std::swap(ffA, ffAD); - std::swap(ffAmux, ffADmux); + std::swap(ffAcemux, ffADcemux); + std::swap(ffArstmux, ffADrstmux); ffAcepol = ffADcepol; + ffArstpol = ffADrstpol; } endcode -code argQ ffB ffBmux ffBcepol sigB clock +code argQ ffB ffBcemux ffBrstmux ffBcepol ffBrstpol sigB clock if (param(dsp, \BREG).as_int() == 0) { argQ = sigB; subpattern(in_dffe); @@ -136,15 +143,17 @@ code argQ ffB ffBmux ffBcepol sigB clock ffB = dff; clock = dffclock; if (dffcemux) { - ffBmux = dffcemux; + ffBcemux = dffcemux; + ffBrstmux = dffrstmux; ffBcepol = dffcepol; + ffBrstpol = dffrstpol; } sigB = dffD; } } endcode -code argQ ffD ffDmux ffDcepol sigD clock +code argQ ffD ffDcemux ffDrstmux ffDcepol ffDrstpol sigD clock if (param(dsp, \DREG).as_int() == 0) { argQ = sigD; subpattern(in_dffe); @@ -152,8 +161,10 @@ code argQ ffD ffDmux ffDcepol sigD clock ffD = dff; clock = dffclock; if (dffcemux) { - ffDmux = dffcemux; + ffDcemux = dffcemux; + ffDrstmux = dffrstmux; ffDcepol = dffcepol; + ffDrstpol = dffrstpol; } sigD = dffD; } @@ -255,16 +266,18 @@ code sigC sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A); endcode -code argQ ffC ffCmux ffCcepol sigC clock - if (param(dsp, \CREG).as_int() == 0) { +code argQ ffC ffCcemux ffCrstmux ffCcepol ffCrstpol sigC clock + if (param(dsp, \CREG).as_int() == 0 && sigC != sigP) { argQ = sigC; subpattern(in_dffe); if (dff) { ffC = dff; clock = dffclock; if (dffcemux) { - ffCmux = dffcemux; + ffCcemux = dffcemux; + ffCrstmux = dffrstmux; ffCcepol = dffcepol; + ffCrstpol = dffrstpol; } sigC = dffD; } @@ -278,67 +291,102 @@ endcode // ####################### subpattern in_dffe -arg argQ clock ffcepol +arg argD argQ clock + +code + dff = nullptr; + for (auto c : argQ.chunks()) { + if (!c.wire) + reject; + if (c.wire->get_bool_attribute(\keep)) + reject; + } +endcode match ff select ff->type.in($dff) // DSP48E1 does not support clock inversion select param(ff, \CLK_POLARITY).as_bool() - filter GetSize(port(ff, \Q)) >= GetSize(argQ) - slice offset GetSize(port(ff, \Q)) - filter offset+GetSize(argQ) <= GetSize(port(ff, \Q)) - filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ + + slice offset GetSize(port(ff, \D)) + index port(ff, \Q)[offset] === argQ[0] + set ffoffset offset +endmatch + +code argQ argD +{ + if (clock != SigBit()) { + if (port(ff, \CLK) != clock) + reject; + } + + SigSpec Q = port(ff, \Q); + if (ffoffset + GetSize(argQ) > GetSize(Q)) + reject; + for (int i = 1; i < GetSize(argQ); i++) + if (Q[ffoffset+i] != argQ[i]) + reject; + + dff = ff; + dffclock = port(ff, \CLK); + dffD = argQ; + argD = port(ff, \D); + argQ = Q; + dffD.replace(argQ, argD); + // Only search for ffrstmux if dffD only + // has two (ff, ffrstmux) users + if (nusers(dffD) > 2) + argD = SigSpec(); +} +endcode + +match ffrstmux + if !argD.empty() + select ffrstmux->type.in($mux) + index port(ffrstmux, \Y) === argD + + choice BA {\B, \A} + // DSP48E1 only supports reset to zero + select port(ffrstmux, BA).is_fully_zero() + + define pol (BA == \B) + set ffrstpol pol semioptional endmatch -code argQ - if (ff) { - for (auto c : argQ.chunks()) - if (c.wire->get_bool_attribute(\keep)) - reject; +code argD + if (ffrstmux) { + dffrstmux = ffrstmux; + dffrstpol = ffrstpol; + argD = port(ffrstmux, ffrstpol ? \A : \B); + dffD.replace(port(ffrstmux, \Y), argD); - if (clock != SigBit()) { - if (port(ff, \CLK) != clock) - reject; - } - dffclock = port(ff, \CLK); - - dff = ff; - dffD = argQ; - dffD.replace(port(ff, \Q), port(ff, \D)); - // Only search for ffcemux if argQ has at - // least 3 users (ff, , ffcemux) and - // its ff.D only has two (ff, ffcemux) + // Only search for ffrstmux if argQ has at + // least 3 users (ff, , ffrstmux) and + // dffD only has two (ff, ffrstmux) if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) - argQ = SigSpec(); - } - else { - dff = nullptr; - argQ = SigSpec(); + argD = SigSpec(); } + else + dffrstmux = nullptr; endcode match ffcemux - if !argQ.empty() + if !argD.empty() select ffcemux->type.in($mux) - index port(ffcemux, \Y) === port(ff, \D) - filter GetSize(port(ffcemux, \Y)) >= GetSize(dffD) - slice offset GetSize(port(ffcemux, \Y)) - filter offset+GetSize(dffD) <= GetSize(port(ffcemux, \Y)) - filter port(ffcemux, \Y).extract(offset, GetSize(dffD)) == dffD + index port(ffcemux, \Y) === argD choice AB {\A, \B} - filter offset+GetSize(argQ) <= GetSize(port(ffcemux, \Y)) - filter port(ffcemux, AB).extract(offset, GetSize(argQ)) == argQ + index port(ffcemux, AB) === argQ define pol (AB == \A) set ffcepol pol semioptional endmatch -code +code argD if (ffcemux) { dffcemux = ffcemux; dffcepol = ffcepol; - dffD = port(ffcemux, dffcepol ? \B : \A); + dffD.replace(port(ffcemux, \Y), argD); } else dffcemux = nullptr; @@ -379,7 +427,6 @@ code argD argQ SigSpec BA = port(ffcemux, ffcepol ? \B : \A); if (ffoffset + GetSize(argD) > GetSize(BA)) reject; - for (int i = 1; i < GetSize(argD); i++) if (BA[ffoffset+i] != argD[i]) reject; @@ -440,7 +487,7 @@ match ff select param(ff, \CLK_POLARITY).as_bool() slice offset GetSize(port(ff, \D)) - index port(ff, \D)[offset] === argD[0] + index port(ff, \D)[offset] === argD[0] filter (!ffcemux && !ffrstmux) || ffoffset == offset set ffoffset offset From e5bdb521fa5ca535ef51d080f11d3470003b49e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 10:55:45 -0700 Subject: [PATCH 231/356] More cleanup --- passes/pmgen/xilinx_dsp.cc | 90 ++++++++++++-------------------------- 1 file changed, 28 insertions(+), 62 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index fdd0ac2fa..f28b729dd 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -273,7 +273,6 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) Cell *cell = st.dsp; bit_to_driver.insert(std::make_pair(cell->getPort("\\P")[17], cell)); - SigSpec P = st.sigP; if (st.preAdd) { log(" preadder %s (%s)\n", log_id(st.preAdd), log_id(st.preAdd->type)); @@ -310,7 +309,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) opmode[4] = st.postAddMux->getPort("\\S"); pm.autoremove(st.postAddMux); } - else if (st.ffP && st.sigC == P) + else if (st.ffP && st.sigC == st.sigP) opmode[4] = State::S0; else opmode[4] = State::S1; @@ -332,16 +331,17 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) { cell->setPort("\\CLK", st.clock); - auto f = [&pm,cell](IdString port, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) { - SigSpec A = cell->getPort(port); + auto f = [&pm,cell](SigSpec &A, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) { SigSpec D = ff->getPort("\\D"); SigSpec Q = pm.sigmap(ff->getPort("\\Q")); - A.replace(Q, D); + if (!A.empty()) + A.replace(Q, D); if (rstmux) { SigSpec Y = rstmux->getPort("\\Y"); SigSpec AB = rstmux->getPort(rstpol ? "\\A" : "\\B"); SigSpec S = rstmux->getPort("\\S"); - A.replace(Y, AB); + if (!A.empty()) + A.replace(Y, AB); cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S)); } else @@ -350,85 +350,50 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) SigSpec Y = cemux->getPort("\\Y"); SigSpec BA = cemux->getPort(cepol ? "\\B" : "\\A"); SigSpec S = cemux->getPort("\\S"); - A.replace(Y, BA); + if (!A.empty()) + A.replace(Y, BA); cell->setPort(ceport, cepol ? S : pm.module->Not(NEW_ID, S)); } else cell->setPort(ceport, State::S1); - cell->setPort(port, A); + + for (auto c : Q.chunks()) { + auto it = c.wire->attributes.find("\\init"); + if (it == c.wire->attributes.end()) + continue; + for (int i = c.offset; i < c.offset+c.width; i++) { + log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); + it->second[i] = State::Sx; + } + } }; if (st.ffA) { - f("\\A", st.ffA, st.ffAcemux, st.ffAcepol, "\\CEA2", st.ffArstmux, st.ffArstpol, "\\RSTA"); + f(cell->connections_.at("\\A"), st.ffA, st.ffAcemux, st.ffAcepol, "\\CEA2", st.ffArstmux, st.ffArstpol, "\\RSTA"); cell->setParam("\\AREG", 1); } if (st.ffB) { - f("\\B", st.ffB, st.ffBcemux, st.ffBcepol, "\\CEB2", st.ffBrstmux, st.ffBrstpol, "\\RSTB"); + f(cell->connections_.at("\\B"), st.ffB, st.ffBcemux, st.ffBcepol, "\\CEB2", st.ffBrstmux, st.ffBrstpol, "\\RSTB"); cell->setParam("\\BREG", 1); } if (st.ffC) { - f("\\C", st.ffC, st.ffCcemux, st.ffCcepol, "\\CEC", st.ffCrstmux, st.ffCrstpol, "\\RSTC"); + f(cell->connections_.at("\\C"), st.ffC, st.ffCcemux, st.ffCcepol, "\\CEC", st.ffCrstmux, st.ffCrstpol, "\\RSTC"); cell->setParam("\\CREG", 1); } if (st.ffD) { - f("\\D", st.ffD, st.ffDcemux, st.ffDcepol, "\\CED", st.ffDrstmux, st.ffDrstpol, "\\RSTD"); + f(cell->connections_.at("\\D"), st.ffD, st.ffDcemux, st.ffDcepol, "\\CED", st.ffDrstmux, st.ffDrstpol, "\\RSTD"); cell->setParam("\\DREG", 1); } if (st.ffM) { - if (st.ffMrstmux) { - SigSpec S = st.ffMrstmux->getPort("\\S"); - cell->setPort("\\RSTM", st.ffMrstpol ? S : pm.module->Not(NEW_ID, S)); - } - else - cell->setPort("\\RSTM", State::S0); - if (st.ffMcemux) { - SigSpec S = st.ffMcemux->getPort("\\S"); - cell->setPort("\\CEM", st.ffMcepol ? S : pm.module->Not(NEW_ID, S)); - } - else - cell->setPort("\\CEM", State::S1); - SigSpec D = st.ffM->getPort("\\D"); - SigSpec Q = st.ffM->getPort("\\Q"); + SigSpec _; + f(_, st.ffM, st.ffMcemux, st.ffMcepol, "\\CEM", st.ffMrstmux, st.ffMrstpol, "\\RSTM"); st.ffM->connections_.at("\\Q").replace(st.sigM, pm.module->addWire(NEW_ID, GetSize(st.sigM))); - - for (auto c : Q.chunks()) { - auto it = c.wire->attributes.find("\\init"); - if (it == c.wire->attributes.end()) - continue; - for (int i = c.offset; i < c.offset+c.width; i++) { - log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); - it->second[i] = State::Sx; - } - } - cell->setParam("\\MREG", State::S1); } if (st.ffP) { - if (st.ffPrstmux) { - SigSpec S = st.ffPrstmux->getPort("\\S"); - cell->setPort("\\RSTP", st.ffPrstpol ? S : pm.module->Not(NEW_ID, S)); - } - else - cell->setPort("\\RSTP", State::S0); - if (st.ffPcemux) { - SigSpec S = st.ffPcemux->getPort("\\S"); - cell->setPort("\\CEP", st.ffPcepol ? S : pm.module->Not(NEW_ID, S)); - } - else - cell->setPort("\\CEP", State::S1); - SigSpec Q = st.ffP->getPort("\\Q"); - st.ffP->connections_.at("\\Q").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); - - for (auto c : Q.chunks()) { - auto it = c.wire->attributes.find("\\init"); - if (it == c.wire->attributes.end()) - continue; - for (int i = c.offset; i < c.offset+c.width; i++) { - log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); - it->second[i] = State::Sx; - } - } - + SigSpec _; + f(_, st.ffP, st.ffPcemux, st.ffPcepol, "\\CEP", st.ffPrstmux, st.ffPrstpol, "\\RSTP"); + st.ffP->connections_.at("\\Q").replace(st.sigP, pm.module->addWire(NEW_ID, GetSize(st.sigP))); cell->setParam("\\PREG", State::S1); } @@ -458,6 +423,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("\n"); } + SigSpec P = st.sigP; if (GetSize(P) < 48) P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); cell->setPort("\\P", P); From d232e6a6cd8ed0ac0e76a1e6b787cb6dead855f0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 11:46:21 -0700 Subject: [PATCH 232/356] Input registers to add DSP as new siguser to block upstream packing --- passes/pmgen/xilinx_dsp.cc | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index f28b729dd..d9d1bfea4 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -369,30 +369,38 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) }; if (st.ffA) { - f(cell->connections_.at("\\A"), st.ffA, st.ffAcemux, st.ffAcepol, "\\CEA2", st.ffArstmux, st.ffArstpol, "\\RSTA"); + SigSpec &A = cell->connections_.at("\\A"); + f(A, st.ffA, st.ffAcemux, st.ffAcepol, "\\CEA2", st.ffArstmux, st.ffArstpol, "\\RSTA"); + pm.add_siguser(A, cell); cell->setParam("\\AREG", 1); } if (st.ffB) { - f(cell->connections_.at("\\B"), st.ffB, st.ffBcemux, st.ffBcepol, "\\CEB2", st.ffBrstmux, st.ffBrstpol, "\\RSTB"); + SigSpec &B = cell->connections_.at("\\B"); + f(B, st.ffB, st.ffBcemux, st.ffBcepol, "\\CEB2", st.ffBrstmux, st.ffBrstpol, "\\RSTB"); + pm.add_siguser(B, cell); cell->setParam("\\BREG", 1); } if (st.ffC) { - f(cell->connections_.at("\\C"), st.ffC, st.ffCcemux, st.ffCcepol, "\\CEC", st.ffCrstmux, st.ffCrstpol, "\\RSTC"); + SigSpec &C = cell->connections_.at("\\C"); + f(C, st.ffC, st.ffCcemux, st.ffCcepol, "\\CEC", st.ffCrstmux, st.ffCrstpol, "\\RSTC"); + pm.add_siguser(C, cell); cell->setParam("\\CREG", 1); } if (st.ffD) { - f(cell->connections_.at("\\D"), st.ffD, st.ffDcemux, st.ffDcepol, "\\CED", st.ffDrstmux, st.ffDrstpol, "\\RSTD"); + SigSpec &D = cell->connections_.at("\\D"); + f(D, st.ffD, st.ffDcemux, st.ffDcepol, "\\CED", st.ffDrstmux, st.ffDrstpol, "\\RSTD"); + pm.add_siguser(D, cell); cell->setParam("\\DREG", 1); } if (st.ffM) { - SigSpec _; - f(_, st.ffM, st.ffMcemux, st.ffMcepol, "\\CEM", st.ffMrstmux, st.ffMrstpol, "\\RSTM"); + SigSpec M; // unused + f(M, st.ffM, st.ffMcemux, st.ffMcepol, "\\CEM", st.ffMrstmux, st.ffMrstpol, "\\RSTM"); st.ffM->connections_.at("\\Q").replace(st.sigM, pm.module->addWire(NEW_ID, GetSize(st.sigM))); cell->setParam("\\MREG", State::S1); } if (st.ffP) { - SigSpec _; - f(_, st.ffP, st.ffPcemux, st.ffPcepol, "\\CEP", st.ffPrstmux, st.ffPrstpol, "\\RSTP"); + SigSpec P; // unused + f(P, st.ffP, st.ffPcemux, st.ffPcepol, "\\CEP", st.ffPrstmux, st.ffPrstpol, "\\RSTP"); st.ffP->connections_.at("\\Q").replace(st.sigP, pm.module->addWire(NEW_ID, GetSize(st.sigP))); cell->setParam("\\PREG", State::S1); } From e9eb855d38b3bd4d5a61471af49e791be12817ba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 13:06:49 -0700 Subject: [PATCH 233/356] Make unextend a udata --- passes/pmgen/xilinx_dsp.pmg | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 6e726d1c2..6998d6e84 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,6 +1,6 @@ pattern xilinx_dsp -state > unextend +udata > unextend state clock state sigA sigffAcemuxY sigB sigffBcemuxY sigC sigffCcemuxY sigD sigffDcemuxY sigM sigP state postAddAB postAddMuxAB @@ -23,7 +23,7 @@ match dsp select dsp->type.in(\DSP48E1) endmatch -code unextend sigA sigB sigC sigD sigM +code sigA sigB sigC sigD sigM unextend = [](const SigSpec &sig) { int i; for (i = GetSize(sig)-1; i > 0; i--) @@ -396,7 +396,6 @@ endcode subpattern out_dffe arg argD argQ clock -arg unextend code dff = nullptr; From 0ebbecf833712165c495fc15fe67b6287cf1fb72 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 13:06:59 -0700 Subject: [PATCH 234/356] Missing space --- techlibs/xilinx/synth_xilinx.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 3d92c3e2c..e822d9b7e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -83,6 +83,7 @@ struct SynthXilinxPass : public ScriptPass log("\n"); 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"); From 690b1a064d9c9c85260cbe841beecff538834833 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 13:48:45 -0700 Subject: [PATCH 235/356] Add PCOUT -> PCIN non-shifted cascading --- passes/pmgen/xilinx_dsp.cc | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index d9d1bfea4..df3d60e09 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -272,7 +272,6 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); Cell *cell = st.dsp; - bit_to_driver.insert(std::make_pair(cell->getPort("\\P")[17], cell)); if (st.preAdd) { log(" preadder %s (%s)\n", log_id(st.preAdd), log_id(st.preAdd->type)); @@ -317,10 +316,10 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) opmode[5] = State::S1; if (opmode[4] != State::S0) { - if (st.postAddMuxAB == "\\A") - st.sigC.extend_u0(48, st.postAdd->getParam("\\B_SIGNED").as_bool()); - else - st.sigC.extend_u0(48, st.postAdd->getParam("\\A_SIGNED").as_bool()); + //if (st.postAddMuxAB == "\\A") + // st.sigC.extend_u0(48, st.postAdd->getParam("\\B_SIGNED").as_bool()); + //else + // st.sigC.extend_u0(48, st.postAdd->getParam("\\A_SIGNED").as_bool()); cell->setPort("\\C", st.sigC); } @@ -436,6 +435,9 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); cell->setPort("\\P", P); + bit_to_driver.insert(std::make_pair(P[0], cell)); + bit_to_driver.insert(std::make_pair(P[17], cell)); + pm.blacklist(cell); } @@ -489,6 +491,7 @@ struct XilinxDspPass : public Pass { auto f = [&bit_to_driver](xilinx_dsp_pm &pm){ pack_xilinx_dsp(bit_to_driver, pm); }; pm.run_xilinx_dsp(f); + auto &unextend = pm.ud_xilinx_dsp.unextend; // Look for ability to convert C input from another DSP into PCIN // NB: Needs to be done after pattern matcher has folded all // $add cells into the DSP @@ -500,22 +503,26 @@ struct XilinxDspPass : public Pass { SigSpec &opmode = cell->connections_.at("\\OPMODE"); if (opmode.extract(4,3) != Const::from_string("011")) continue; - SigSpec C = pm.sigmap(cell->getPort("\\C")); - if (C.has_const()) + SigSpec C = unextend(pm.sigmap(cell->getPort("\\C"))); + if (!C[0].wire) continue; auto it = bit_to_driver.find(C[0]); if (it == bit_to_driver.end()) continue; auto driver = it->second; - // Unextend C - int i; - for (i = GetSize(C)-1; i > 0; i--) - if (C[i] != C[i-1]) - break; - if (i > 48-17) - continue; - if (driver->getPort("\\P").extract(17, i) == C.extract(0, i)) { + SigSpec P = driver->getPort("\\P"); + if (GetSize(P) >= GetSize(C) && P.extract(0, GetSize(C)) == C) { + cell->setPort("\\C", Const(0, 48)); + Wire *cascade = module->addWire(NEW_ID, 48); + driver->setPort("\\PCOUT", cascade); + cell->setPort("\\PCIN", cascade); + opmode[6] = State::S0; + opmode[5] = State::S0; + opmode[4] = State::S1; + bit_to_driver.erase(it); + } + else if (GetSize(P) >= GetSize(C)+17 && P.extract(17, GetSize(C)) == C) { cell->setPort("\\C", Const(0, 48)); Wire *cascade = module->addWire(NEW_ID, 48); driver->setPort("\\PCOUT", cascade); From 63431fe42a364f257f9d5571433e139d54cd2c11 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 14:17:45 -0700 Subject: [PATCH 236/356] Fix UB --- passes/pmgen/peepopt_dffmux.pmg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/peepopt_dffmux.pmg b/passes/pmgen/peepopt_dffmux.pmg index 60a708616..fbabf90f0 100644 --- a/passes/pmgen/peepopt_dffmux.pmg +++ b/passes/pmgen/peepopt_dffmux.pmg @@ -35,8 +35,8 @@ match cemux endmatch code - SigSpec &D = cemux->connections_.at(cemuxAB == \A ? \B : \A); - SigSpec &Q = dff->connections_.at(\Q); + SigSpec D = port(cemux, cemuxAB == \A ? \B : \A); + SigSpec Q = port(dff, \Q); Const rst; if (rstmux) rst = port(rstmux, rstmuxBA).as_const(); From 6fa6bf483c5e5ba7d3a467c37f66ecf6be9db7d5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 16:21:24 -0700 Subject: [PATCH 237/356] Rename {A,B} -> {A2,B2} --- passes/pmgen/xilinx_dsp.cc | 28 +++++++++++++------------- passes/pmgen/xilinx_dsp.pmg | 39 +++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index df3d60e09..52ffa5465 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -258,8 +258,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("\n"); log("preAdd: %s\n", log_id(st.preAdd, "--")); log("ffAD: %s %s %s\n", log_id(st.ffAD, "--"), log_id(st.ffADcemux, "--"), log_id(st.ffADrstmux, "--")); - log("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAcemux, "--"), log_id(st.ffArstmux, "--")); - log("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBcemux, "--"), log_id(st.ffBrstmux, "--")); + log("ffA2: %s %s %s\n", log_id(st.ffA2, "--"), log_id(st.ffA2cemux, "--"), log_id(st.ffA2rstmux, "--")); + log("ffB2: %s %s %s\n", log_id(st.ffB2, "--"), log_id(st.ffB2cemux, "--"), log_id(st.ffB2rstmux, "--")); log("ffC: %s %s %s\n", log_id(st.ffC, "--"), log_id(st.ffCcemux, "--"), log_id(st.ffCrstmux, "--")); log("ffD: %s %s %s\n", log_id(st.ffD, "--"), log_id(st.ffDcemux, "--"), log_id(st.ffDrstmux, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); @@ -367,16 +367,16 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) } }; - if (st.ffA) { - SigSpec &A = cell->connections_.at("\\A"); - f(A, st.ffA, st.ffAcemux, st.ffAcepol, "\\CEA2", st.ffArstmux, st.ffArstpol, "\\RSTA"); - pm.add_siguser(A, cell); + if (st.ffA2) { + SigSpec &A2 = cell->connections_.at("\\A"); + f(A2, st.ffA2, st.ffA2cemux, st.ffA2cepol, "\\CEA2", st.ffA2rstmux, st.ffArstpol, "\\RSTA"); + pm.add_siguser(A2, cell); cell->setParam("\\AREG", 1); } - if (st.ffB) { - SigSpec &B = cell->connections_.at("\\B"); - f(B, st.ffB, st.ffBcemux, st.ffBcepol, "\\CEB2", st.ffBrstmux, st.ffBrstpol, "\\RSTB"); - pm.add_siguser(B, cell); + if (st.ffB2) { + SigSpec &B2 = cell->connections_.at("\\B"); + f(B2, st.ffB2, st.ffB2cemux, st.ffB2cepol, "\\CEB2", st.ffB2rstmux, st.ffBrstpol, "\\RSTB"); + pm.add_siguser(B2, cell); cell->setParam("\\BREG", 1); } if (st.ffC) { @@ -406,14 +406,14 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), "posedge"); - if (st.ffA) - log(" ffA:%s", log_id(st.ffA)); + if (st.ffA2) + log(" ffA2:%s", log_id(st.ffA2)); if (st.ffAD) log(" ffAD:%s", log_id(st.ffAD)); - if (st.ffB) - log(" ffB:%s", log_id(st.ffB)); + if (st.ffB2) + log(" ffB2:%s", log_id(st.ffB2)); if (st.ffC) log(" ffC:%s", log_id(st.ffC)); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 6998d6e84..8c7477efa 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -4,10 +4,11 @@ udata > unextend state clock state sigA sigffAcemuxY sigB sigffBcemuxY sigC sigffCcemuxY sigD sigffDcemuxY sigM sigP state postAddAB postAddMuxAB -state ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol +state ffA1cepol ffA2cepol ffADcepol ffB1cepol ffB2cepol ffCcepol ffDcepol ffMcepol ffPcepol state ffArstpol ffADrstpol ffBrstpol ffCrstpol ffDrstpol ffMrstpol ffPrstpol -state ffAD ffADcemux ffADrstmux ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffC ffCcemux ffCrstmux +state ffAD ffADcemux ffADrstmux ffA1 ffA1cemux ffA1rstmux ffA2 ffA2cemux ffA2rstmux +state ffB1 ffB1cemux ffB1rstmux ffB2 ffB2cemux ffB2rstmux ffC ffCcemux ffCrstmux state ffD ffDcemux ffDrstmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux // subpattern @@ -103,20 +104,20 @@ code sigA sigD } endcode -code argQ ffA ffAcemux ffArstmux ffAcepol ffArstpol sigA clock ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol - // Only search for ffA if there was a pre-adder - // (otherwise ffA would have been matched as ffAD) +code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cemux ffA2rstmux ffA2cepol ffArstpol + // Only search for ffA2 if there was a pre-adder + // (otherwise ffA2 would have been matched as ffA2) if (preAdd) { if (param(dsp, \AREG).as_int() == 0) { argQ = sigA; subpattern(in_dffe); if (dff) { - ffA = dff; + ffA2 = dff; clock = dffclock; if (dffcemux) { - ffAcemux = dffcemux; - ffArstmux = dffrstmux; - ffAcepol = dffcepol; + ffA2cemux = dffcemux; + ffA2rstmux = dffrstmux; + ffA2cepol = dffcepol; ffArstpol = dffrstpol; } sigA = dffD; @@ -126,26 +127,26 @@ code argQ ffA ffAcemux ffArstmux ffAcepol ffArstpol sigA clock ffAD ffADcemux ff // And if there wasn't a pre-adder, // move AD register to A else if (ffAD) { - log_assert(!ffA && !ffAcemux && !ffArstmux); - std::swap(ffA, ffAD); - std::swap(ffAcemux, ffADcemux); - std::swap(ffArstmux, ffADrstmux); - ffAcepol = ffADcepol; + log_assert(!ffA2 && !ffA2cemux && !ffA2rstmux); + std::swap(ffA2, ffAD); + std::swap(ffA2cemux, ffADcemux); + std::swap(ffA2rstmux, ffADrstmux); + ffA2cepol = ffADcepol; ffArstpol = ffADrstpol; } endcode -code argQ ffB ffBcemux ffBrstmux ffBcepol ffBrstpol sigB clock +code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock if (param(dsp, \BREG).as_int() == 0) { argQ = sigB; subpattern(in_dffe); if (dff) { - ffB = dff; + ffB2 = dff; clock = dffclock; if (dffcemux) { - ffBcemux = dffcemux; - ffBrstmux = dffrstmux; - ffBcepol = dffcepol; + ffB2cemux = dffcemux; + ffB2rstmux = dffrstmux; + ffB2cepol = dffcepol; ffBrstpol = dffrstpol; } sigB = dffD; From 7d644f40ed42f3f0c5e5218c5f0274a7bcdfca85 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 17:05:47 -0700 Subject: [PATCH 238/356] Add AREG=2 BREG=2 test --- tests/xilinx/macc.v | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/xilinx/macc.v b/tests/xilinx/macc.v index 5dc99ab8e..9d684477f 100644 --- a/tests/xilinx/macc.v +++ b/tests/xilinx/macc.v @@ -47,7 +47,7 @@ module macc2 # (parameter SIZEIN = 16, SIZEOUT = 40) ( output signed [SIZEOUT-1:0] accum_out ); // Declare registers for intermediate values -reg signed [SIZEIN-1:0] a_reg, b_reg; +reg signed [SIZEIN-1:0] a_reg, b_reg, a_reg2, b_reg2; reg rst_reg; reg signed [2*SIZEIN-1:0] mult_reg; reg signed [SIZEOUT-1:0] adder_out, old_result; @@ -56,14 +56,18 @@ always @(posedge clk) begin begin a_reg <= a; b_reg <= b; - mult_reg <= a_reg * b_reg; + a_reg2 <= a_reg; + b_reg2 <= b_reg; + mult_reg <= a_reg2 * b_reg2; rst_reg <= rst; // Store accumulation result into a register adder_out <= adder_out + mult_reg; end if (rst) begin a_reg <= 0; + a_reg2 <= 0; b_reg <= 0; + b_reg2 <= 0; mult_reg <= 0; adder_out <= 0; end From 4369fc17d03d5c1db84823a37ff0f56eb1477e8f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 17:06:37 -0700 Subject: [PATCH 239/356] Raise a RuntimeError instead of AssertionError --- passes/pmgen/pmgen.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index 573722d68..335d26f16 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -305,7 +305,8 @@ def process_pmgfile(f, filename): block["states"] = set() for s in line.split()[1:]: - assert s in state_types[current_pattern] + if s not in state_types[current_pattern]: + raise RuntimeError("'%s' not in state_types" % s) block["states"].add(s) codetype = "code" From f3081c20e7a9ac9b69581396999633272096b1e8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 11 Sep 2019 17:16:46 -0700 Subject: [PATCH 240/356] Add support for A1 and B1 registers --- passes/pmgen/xilinx_dsp.cc | 59 +++++++++++++++++++++---------- passes/pmgen/xilinx_dsp.pmg | 70 ++++++++++++++++++++++++++++++++++--- 2 files changed, 105 insertions(+), 24 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 52ffa5465..ae8cd64da 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -259,7 +259,9 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("preAdd: %s\n", log_id(st.preAdd, "--")); log("ffAD: %s %s %s\n", log_id(st.ffAD, "--"), log_id(st.ffADcemux, "--"), log_id(st.ffADrstmux, "--")); log("ffA2: %s %s %s\n", log_id(st.ffA2, "--"), log_id(st.ffA2cemux, "--"), log_id(st.ffA2rstmux, "--")); + log("ffA1: %s %s %s\n", log_id(st.ffA1, "--"), log_id(st.ffA1cemux, "--"), log_id(st.ffA1rstmux, "--")); log("ffB2: %s %s %s\n", log_id(st.ffB2, "--"), log_id(st.ffB2cemux, "--"), log_id(st.ffB2rstmux, "--")); + log("ffB1: %s %s %s\n", log_id(st.ffB1, "--"), log_id(st.ffB1cemux, "--"), log_id(st.ffB1rstmux, "--")); log("ffC: %s %s %s\n", log_id(st.ffC, "--"), log_id(st.ffCcemux, "--"), log_id(st.ffCrstmux, "--")); log("ffD: %s %s %s\n", log_id(st.ffD, "--"), log_id(st.ffDcemux, "--"), log_id(st.ffDrstmux, "--")); log("dsp: %s\n", log_id(st.dsp, "--")); @@ -338,12 +340,14 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (rstmux) { SigSpec Y = rstmux->getPort("\\Y"); SigSpec AB = rstmux->getPort(rstpol ? "\\A" : "\\B"); - SigSpec S = rstmux->getPort("\\S"); if (!A.empty()) A.replace(Y, AB); - cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S)); + if (rstport != IdString()) { + SigSpec S = rstmux->getPort("\\S"); + cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S)); + } } - else + else if (rstport != IdString()) cell->setPort(rstport, State::S0); if (cemux) { SigSpec Y = cemux->getPort("\\Y"); @@ -368,16 +372,26 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) }; if (st.ffA2) { - SigSpec &A2 = cell->connections_.at("\\A"); - f(A2, st.ffA2, st.ffA2cemux, st.ffA2cepol, "\\CEA2", st.ffA2rstmux, st.ffArstpol, "\\RSTA"); - pm.add_siguser(A2, cell); - cell->setParam("\\AREG", 1); + SigSpec &A = cell->connections_.at("\\A"); + f(A, st.ffA2, st.ffA2cemux, st.ffA2cepol, "\\CEA2", st.ffA2rstmux, st.ffArstpol, "\\RSTA"); + pm.add_siguser(A, cell); + if (st.ffA1) { + f(A, st.ffA1, st.ffA1cemux, st.ffA1cepol, "\\CEA1", st.ffA1rstmux, st.ffArstpol, IdString()); + cell->setParam("\\AREG", 2); + } + else + cell->setParam("\\AREG", 1); } if (st.ffB2) { - SigSpec &B2 = cell->connections_.at("\\B"); - f(B2, st.ffB2, st.ffB2cemux, st.ffB2cepol, "\\CEB2", st.ffB2rstmux, st.ffBrstpol, "\\RSTB"); - pm.add_siguser(B2, cell); - cell->setParam("\\BREG", 1); + SigSpec &B = cell->connections_.at("\\B"); + f(B, st.ffB2, st.ffB2cemux, st.ffB2cepol, "\\CEB2", st.ffB2rstmux, st.ffBrstpol, "\\RSTB"); + pm.add_siguser(B, cell); + if (st.ffB1) { + f(B, st.ffB1, st.ffB1cemux, st.ffB1cepol, "\\CEB1", st.ffB1rstmux, st.ffBrstpol, IdString()); + cell->setParam("\\BREG", 2); + } + else + cell->setParam("\\BREG", 1); } if (st.ffC) { SigSpec &C = cell->connections_.at("\\C"); @@ -406,14 +420,20 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), "posedge"); - if (st.ffA2) + if (st.ffA2) { log(" ffA2:%s", log_id(st.ffA2)); + if (st.ffA1) + log(" ffA1:%s", log_id(st.ffA1)); + } if (st.ffAD) log(" ffAD:%s", log_id(st.ffAD)); - if (st.ffB2) + if (st.ffB2) { log(" ffB2:%s", log_id(st.ffB2)); + if (st.ffB1) + log(" ffB1:%s", log_id(st.ffB1)); + } if (st.ffC) log(" ffC:%s", log_id(st.ffC)); @@ -449,17 +469,18 @@ struct XilinxDspPass : public Pass { log("\n"); log(" xilinx_dsp [options] [selection]\n"); log("\n"); - log("Pack input registers (A, B, C, D, AD; with optional enable/reset), pipeline\n"); - log("registers (M; with optional enable/reset), output registers (P; with optional\n"); - log("enable/reset), pre-adder and/or post-adder into Xilinx DSP resources.\n"); + log("Pack input registers (A2, A1, B2, B1, C, D, AD; with optional enable/reset),\n"); + log("pipeline registers (M; with optional enable/reset), output registers (P; with\n"); + log("optional enable/reset), pre-adder and/or post-adder into Xilinx DSP resources.\n"); log("\n"); log("Multiply-accumulate operations using the post-adder with feedback on the 'C'\n"); log("input will be folded into the DSP. In this scenario only, the 'C' input can be\n"); log("used to override the existing accumulation result with a new value.\n"); log("\n"); - log("Use of the dedicated 'PCOUT' -> 'PCIN' path is detected for 'P' -> 'C' connections\n"); - log("where 'P' is right-shifted by 18-bits and used as an input to the post-adder (a\n"); - log("pattern common for summing partial products to implement wide multiplies).\n"); + log("Use of the dedicated 'PCOUT' -> 'PCIN' cascade path is detected for 'P' -> 'C'\n"); + log("connections (optionally, where 'P' is right-shifted by 18-bits and used as an\n"); + log("input to the post-adder -- a pattern common for summing partial products to\n"); + log("implement wide multipliers).\n"); log("\n"); log("\n"); log("Experimental feature: addition/subtractions less than 12 or 24 bits with the\n"); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 8c7477efa..fa845b593 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -104,9 +104,9 @@ code sigA sigD } endcode -code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cemux ffA2rstmux ffA2cepol ffArstpol +code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cemux ffA2rstmux ffA2cepol ffArstpol ffA1 ffA1cemux ffA1rstmux ffA1cepol // Only search for ffA2 if there was a pre-adder - // (otherwise ffA2 would have been matched as ffA2) + // (otherwise ffA2 would have been matched as ffAD) if (preAdd) { if (param(dsp, \AREG).as_int() == 0) { argQ = sigA; @@ -114,11 +114,13 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cem if (dff) { ffA2 = dff; clock = dffclock; + if (dffrstmux) { + ffA2cepol = dffcepol; + ffArstpol = dffrstpol; + } if (dffcemux) { ffA2cemux = dffcemux; ffA2rstmux = dffrstmux; - ffA2cepol = dffcepol; - ffArstpol = dffrstpol; } sigA = dffD; } @@ -134,9 +136,37 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cem ffA2cepol = ffADcepol; ffArstpol = ffADrstpol; } + + // Now attempt to match A1 + if (ffA2) { + argQ = sigA; + subpattern(in_dffe); + if (dff) { + if ((ffA2rstmux != nullptr) ^ (dffrstmux != nullptr)) + goto ffA1_end; + if (dffrstmux) { + if (ffArstpol != dffrstpol) + goto ffA1_end; + if (port(ffA2rstmux, \S) != port(dffrstmux, \S)) + goto ffA1_end; + ffA1rstmux = dffrstmux; + } + + ffA1 = dff; + clock = dffclock; + + if (dffcemux) { + ffA1cemux = dffcemux; + ffA1cepol = dffcepol; + } + sigA = dffD; + +ffA1_end: ; + } + } endcode -code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock +code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock ffB1 ffB1cemux ffB1rstmux ffB1cepol if (param(dsp, \BREG).as_int() == 0) { argQ = sigB; subpattern(in_dffe); @@ -150,6 +180,35 @@ code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock ffBrstpol = dffrstpol; } sigB = dffD; + + // Now attempt to match B1 + if (ffB2) { + argQ = sigB; + subpattern(in_dffe); + if (dff) { + if ((ffB2rstmux != nullptr) ^ (dffrstmux != nullptr)) + goto ffB1_end; + if (dffrstmux) { + if (ffBrstpol != dffrstpol) + goto ffB1_end; + if (port(ffB2rstmux, \S) != port(dffrstmux, \S)) + goto ffB1_end; + ffB1rstmux = dffrstmux; + } + + ffB1 = dff; + clock = dffclock; + + if (dffcemux) { + ffB1cemux = dffcemux; + ffB1cepol = dffcepol; + } + sigB = dffD; + +ffB1_end: ; + } + } + } } endcode @@ -387,6 +446,7 @@ code argD if (ffcemux) { dffcemux = ffcemux; dffcepol = ffcepol; + argD = port(ffcemux, ffcepol ? \B : \A); dffD.replace(port(ffcemux, \Y), argD); } else From 3a390733027584071d0cd3b2d99c738ce6f1a829 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 12 Sep 2019 17:10:43 -0700 Subject: [PATCH 241/356] Set more ports explicitly --- passes/pmgen/xilinx_dsp.cc | 2 ++ techlibs/xilinx/dsp_map.v | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index ae8cd64da..e0c7823ed 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -44,6 +44,8 @@ static Cell* addDsp(Module *module) { cell->setParam("\\OPMODEREG", 0); cell->setParam("\\PREG", 0); cell->setParam("\\USE_MULT", Const("NONE")); + cell->setParam("\\USE_SIMD", Const("ONE48")); + cell->setParam("\\USE_DPORT", Const("FALSE")); cell->setPort("\\D", Const(0, 24)); cell->setPort("\\INMODE", Const(0, 5)); diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v index cc37f0085..8901b215b 100644 --- a/techlibs/xilinx/dsp_map.v +++ b/techlibs/xilinx/dsp_map.v @@ -25,7 +25,8 @@ module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); .OPMODEREG(0), .PREG(0), .USE_MULT("MULTIPLY"), - .USE_SIMD("ONE48") + .USE_SIMD("ONE48"), + .USE_DPORT("FALSE") ) _TECHMAP_REPLACE_ ( //Data path .A({{5{A[24]}}, A}), From 6bb8e6a7267b4e3d8c1717cde87d41d04fdac82d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 12 Sep 2019 17:11:01 -0700 Subject: [PATCH 242/356] Initial DSP48E1 box support --- techlibs/xilinx/abc_map.v | 216 +++++++++++++++++++++ techlibs/xilinx/abc_model.v | 108 +++++++++++ techlibs/xilinx/abc_unmap.v | 176 +++++++++++++++++ techlibs/xilinx/abc_xc7.box | 367 ++++++++++++++++++++++++++++++++++++ 4 files changed, 867 insertions(+) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 0c85d6656..be69ae256 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -121,3 +121,219 @@ module SRLC32E ( ); \$__ABC_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q)); endmodule + +module DSP48E1 ( + output [29:0] ACOUT, + output [17:0] BCOUT, + output reg CARRYCASCOUT, + output reg [3:0] CARRYOUT, + output reg MULTSIGNOUT, + output OVERFLOW, + output reg signed [47:0] P, + output PATTERNBDETECT, + output PATTERNDETECT, + output [47:0] PCOUT, + output UNDERFLOW, + input signed [29:0] A, + input [29:0] ACIN, + input [3:0] ALUMODE, + input signed [17:0] B, + input [17:0] BCIN, + input [47:0] C, + input CARRYCASCIN, + input CARRYIN, + input [2:0] CARRYINSEL, + input CEA1, + input CEA2, + input CEAD, + input CEALUMODE, + input CEB1, + input CEB2, + input CEC, + input CECARRYIN, + input CECTRL, + input CED, + input CEINMODE, + input CEM, + input CEP, + input CLK, + input [24:0] D, + input [4:0] INMODE, + input MULTSIGNIN, + input [6:0] OPMODE, + input [47:0] PCIN, + input RSTA, + input RSTALLCARRYIN, + input RSTALUMODE, + input RSTB, + input RSTC, + input RSTCTRL, + input RSTD, + input RSTINMODE, + input RSTM, + input RSTP +); + parameter integer ACASCREG = 1; + parameter integer ADREG = 1; + parameter integer ALUMODEREG = 1; + parameter integer AREG = 1; + parameter AUTORESET_PATDET = "NO_RESET"; + parameter A_INPUT = "DIRECT"; + parameter integer BCASCREG = 1; + parameter integer BREG = 1; + parameter B_INPUT = "DIRECT"; + parameter integer CARRYINREG = 1; + parameter integer CARRYINSELREG = 1; + parameter integer CREG = 1; + parameter integer DREG = 1; + parameter integer INMODEREG = 1; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter SEL_MASK = "MASK"; + parameter SEL_PATTERN = "PATTERN"; + parameter USE_DPORT = "FALSE"; + parameter USE_MULT = "MULTIPLY"; + parameter USE_PATTERN_DETECT = "NO_PATDET"; + parameter USE_SIMD = "ONE48"; + parameter [47:0] MASK = 48'h3FFFFFFFFFFF; + parameter [47:0] PATTERN = 48'h000000000000; + parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; + parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + parameter [4:0] IS_INMODE_INVERTED = 5'b0; + parameter [6:0] IS_OPMODE_INVERTED = 7'b0; + + parameter _TECHMAP_CELLTYPE_ = ""; + + generate + if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin + wire [29:0] iA; + wire [17:0] iB; + wire [47:0] iC; + wire [24:0] iD; + + wire pA, pB, pC, pD, pAD, pM, pP; + wire [47:0] oP, oPCOUT; + + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken + if (AREG == 0 || MREG == 1 || PREG == 1) + assign iA = A; + else + \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); + if (BREG == 0 || MREG == 1 || PREG == 1) + assign iB = B; + else + \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); + if (CREG == 0 || PREG == 1) + assign iC = C; + else + \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); + if (DREG == 0) + assign iD = D; + else if (_TECHMAP_CELLTYPE_ != "") + $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + if (ADREG == 1 && _TECHMAP_CELLTYPE_ != "") + $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); + if (PREG == 0) begin + if (MREG == 1) + \$__ABC_DSP48E1_REG rM (.Q(pM)); + end + else + \$__ABC_DSP48E1_REG rP (.Q(pP)); + + \$__ABC_DSP48E1_MULT_P_MUX muxP ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) + ); + \$__ABC_DSP48E1_MULT_PCOUT_MUX muxPCOUT ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) + ); + + \$__ABC_DSP48E1_MULT #( + .ACASCREG(ACASCREG), + .ADREG(ADREG), + .ALUMODEREG(ALUMODEREG), + .AREG(AREG), + .AUTORESET_PATDET(AUTORESET_PATDET), + .A_INPUT(A_INPUT), + .BCASCREG(BCASCREG), + .BREG(BREG), + .B_INPUT(B_INPUT), + .CARRYINREG(CARRYINREG), + .CARRYINSELREG(CARRYINSELREG), + .CREG(CREG), + .DREG(DREG), + .INMODEREG(INMODEREG), + .MREG(MREG), + .OPMODEREG(OPMODEREG), + .PREG(PREG), + .SEL_MASK(SEL_MASK), + .SEL_PATTERN(SEL_PATTERN), + .USE_DPORT(USE_DPORT), + .USE_MULT(USE_MULT), + .USE_PATTERN_DETECT(USE_PATTERN_DETECT), + .USE_SIMD(USE_SIMD), + .MASK(MASK), + .PATTERN(PATTERN), + .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), + .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), + .IS_CLK_INVERTED(IS_CLK_INVERTED), + .IS_INMODE_INVERTED(IS_INMODE_INVERTED), + .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED) + ) _TECHMAP_REPLACE_ ( + .ACOUT(ACOUT), + .BCOUT(BCOUT), + .CARRYCASCOUT(CARRYCASCOUT), + .CARRYOUT(CARRYOUT), + .MULTSIGNOUT(MULTSIGNOUT), + .OVERFLOW(OVERFLOW), + .P(oP), + .PATTERNBDETECT(PATTERNBDETECT), + .PATTERNDETECT(PATTERNDETECT), + .PCOUT(oPCOUT), + .UNDERFLOW(UNDERFLOW), + .A(iA), + .ACIN(ACIN), + .ALUMODE(ALUMODE), + .B(iB), + .BCIN(BCIN), + .C(iC), + .CARRYCASCIN(CARRYCASCIN), + .CARRYIN(CARRYIN), + .CARRYINSEL(CARRYINSEL), + .CEA1(CEA1), + .CEA2(CEA2), + .CEAD(CEAD), + .CEALUMODE(CEALUMODE), + .CEB1(CEB1), + .CEB2(CEB2), + .CEC(CEC), + .CECARRYIN(CECARRYIN), + .CECTRL(CECTRL), + .CED(CED), + .CEINMODE(CEINMODE), + .CEM(CEM), + .CEP(CEP), + .CLK(CLK), + .D(iD), + .INMODE(INMODE), + .MULTSIGNIN(MULTSIGNIN), + .OPMODE(OPMODE), + .PCIN(PCIN), + .RSTA(RSTA), + .RSTALLCARRYIN(RSTALLCARRYIN), + .RSTALUMODE(RSTALUMODE), + .RSTB(RSTB), + .RSTC(RSTC), + .RSTCTRL(RSTCTRL), + .RSTD(RSTD), + .RSTINMODE(RSTINMODE), + .RSTM(RSTM), + .RSTP(RSTP) + ); + end + else + wire _TECHMAP_FAIL_ = 1; + endgenerate +endmodule diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index 655b993f6..95a368306 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -20,15 +20,123 @@ // ============================================================================ +// Box containing MUXF7.[AB] + MUXF8, +// Necessary to make these an atomic unit so that +// ABC cannot optimise just one of the MUXF7 away +// and expect to save on its delay (* abc_box_id = 3, lib_whitebox *) module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); assign O = S1 ? (S0 ? I3 : I2) : (S0 ? I1 : I0); endmodule +// Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} +// Necessary since RAMD* and SRL* have both combinatorial (i.e. +// same-cycle read operation) and sequential (write operation +// is only committed on the next clock edge). +// To model the combinatorial path, such cells have to be split +// into comb and seq parts, with this box modelling only the former. (* abc_box_id=2000 *) module \$__ABC_LUT6 (input A, input [5:0] S, output Y); endmodule +// Box to emulate comb/seq behaviour of RAMD128 (* abc_box_id=2001 *) module \$__ABC_LUT7 (input A, input [6:0] S, output Y); endmodule + +(* abc_box_id=2100 *) +module \$__ABC_DSP48E1_MULT_P_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); +endmodule +(* abc_box_id=2101 *) +module \$__ABC_DSP48E1_MULT_PCOUT_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); +endmodule + +// Box used to represent the comb/seq behaviour of DSP48E1 +// abc_map.v is responsible for disconnecting inputs to +// the combinatorial DSP48E1 model by a register (e.g. +// disconnecting A when AREG, MREG or PREG is enabled) +(* abc_box_id=3000 *) +module \$__ABC_DSP48E1_MULT ( + output [29:0] ACOUT, + output [17:0] BCOUT, + output reg CARRYCASCOUT, + output reg [3:0] CARRYOUT, + output reg MULTSIGNOUT, + output OVERFLOW, + output reg signed [47:0] P, + output PATTERNBDETECT, + output PATTERNDETECT, + output [47:0] PCOUT, + output UNDERFLOW, + input signed [29:0] A, + input [29:0] ACIN, + input [3:0] ALUMODE, + input signed [17:0] B, + input [17:0] BCIN, + input [47:0] C, + input CARRYCASCIN, + input CARRYIN, + input [2:0] CARRYINSEL, + input CEA1, + input CEA2, + input CEAD, + input CEALUMODE, + input CEB1, + input CEB2, + input CEC, + input CECARRYIN, + input CECTRL, + input CED, + input CEINMODE, + input CEM, + input CEP, + input CLK, + input [24:0] D, + input [4:0] INMODE, + input MULTSIGNIN, + input [6:0] OPMODE, + input [47:0] PCIN, + input RSTA, + input RSTALLCARRYIN, + input RSTALUMODE, + input RSTB, + input RSTC, + input RSTCTRL, + input RSTD, + input RSTINMODE, + input RSTM, + input RSTP +); + parameter integer ACASCREG = 1; + parameter integer ADREG = 1; + parameter integer ALUMODEREG = 1; + parameter integer AREG = 1; + parameter AUTORESET_PATDET = "NO_RESET"; + parameter A_INPUT = "DIRECT"; + parameter integer BCASCREG = 1; + parameter integer BREG = 1; + parameter B_INPUT = "DIRECT"; + parameter integer CARRYINREG = 1; + parameter integer CARRYINSELREG = 1; + parameter integer CREG = 1; + parameter integer DREG = 1; + parameter integer INMODEREG = 1; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter SEL_MASK = "MASK"; + parameter SEL_PATTERN = "PATTERN"; + parameter USE_DPORT = "FALSE"; + parameter USE_MULT = "MULTIPLY"; + parameter USE_PATTERN_DETECT = "NO_PATDET"; + parameter USE_SIMD = "ONE48"; + parameter [47:0] MASK = 48'h3FFFFFFFFFFF; + parameter [47:0] PATTERN = 48'h000000000000; + parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; + parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + parameter [4:0] IS_INMODE_INVERTED = 5'b0; + parameter [6:0] IS_OPMODE_INVERTED = 7'b0; +endmodule + + diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index f101a22d0..bcb1069bc 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -26,3 +26,179 @@ endmodule module \$__ABC_LUT7 (input A, input [6:0] S, output Y); assign Y = A; endmodule + +module \$__ABC_DSP48E1_REG (input [47:0] I, output [47:0] O, output Q); + assign O = I; +endmodule +module \$__ABC_DSP48E1_MULT_P_MUX (input Aq, Bq, Cq, Dq, ADq, Mq, input [47:0] P, input Pq, output [47:0] O); + assign O = P; +endmodule +module \$__ABC_DSP48E1_MULT_PCOUT_MUX (input Aq, Bq, Cq, Dq, ADq, Mq, input [47:0] P, input Pq, output [47:0] O); + assign O = P; +endmodule + +module \$__ABC_DSP48E1_MULT ( + output [29:0] ACOUT, + output [17:0] BCOUT, + output reg CARRYCASCOUT, + output reg [3:0] CARRYOUT, + output reg MULTSIGNOUT, + output OVERFLOW, + output reg signed [47:0] P, + output PATTERNBDETECT, + output PATTERNDETECT, + output [47:0] PCOUT, + output UNDERFLOW, + input signed [29:0] A, + input [29:0] ACIN, + input [3:0] ALUMODE, + input signed [17:0] B, + input [17:0] BCIN, + input [47:0] C, + input CARRYCASCIN, + input CARRYIN, + input [2:0] CARRYINSEL, + input CEA1, + input CEA2, + input CEAD, + input CEALUMODE, + input CEB1, + input CEB2, + input CEC, + input CECARRYIN, + input CECTRL, + input CED, + input CEINMODE, + input CEM, + input CEP, + input CLK, + input [24:0] D, + input [4:0] INMODE, + input MULTSIGNIN, + input [6:0] OPMODE, + input [47:0] PCIN, + input RSTA, + input RSTALLCARRYIN, + input RSTALUMODE, + input RSTB, + input RSTC, + input RSTCTRL, + input RSTD, + input RSTINMODE, + input RSTM, + input RSTP +); + parameter integer ACASCREG = 1; + parameter integer ADREG = 1; + parameter integer ALUMODEREG = 1; + parameter integer AREG = 1; + parameter AUTORESET_PATDET = "NO_RESET"; + parameter A_INPUT = "DIRECT"; + parameter integer BCASCREG = 1; + parameter integer BREG = 1; + parameter B_INPUT = "DIRECT"; + parameter integer CARRYINREG = 1; + parameter integer CARRYINSELREG = 1; + parameter integer CREG = 1; + parameter integer DREG = 1; + parameter integer INMODEREG = 1; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter SEL_MASK = "MASK"; + parameter SEL_PATTERN = "PATTERN"; + parameter USE_DPORT = "FALSE"; + parameter USE_MULT = "MULTIPLY"; + parameter USE_PATTERN_DETECT = "NO_PATDET"; + parameter USE_SIMD = "ONE48"; + parameter [47:0] MASK = 48'h3FFFFFFFFFFF; + parameter [47:0] PATTERN = 48'h000000000000; + parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; + parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + parameter [4:0] IS_INMODE_INVERTED = 5'b0; + parameter [6:0] IS_OPMODE_INVERTED = 7'b0; + + DSP48E1 #( + .ACASCREG(ACASCREG), + .ADREG(ADREG), + .ALUMODEREG(ALUMODEREG), + .AREG(AREG), + .AUTORESET_PATDET(AUTORESET_PATDET), + .A_INPUT(A_INPUT), + .BCASCREG(BCASCREG), + .BREG(BREG), + .B_INPUT(B_INPUT), + .CARRYINREG(CARRYINREG), + .CARRYINSELREG(CARRYINSELREG), + .CREG(CREG), + .DREG(DREG), + .INMODEREG(INMODEREG), + .MREG(MREG), + .OPMODEREG(OPMODEREG), + .PREG(PREG), + .SEL_MASK(SEL_MASK), + .SEL_PATTERN(SEL_PATTERN), + .USE_DPORT(USE_DPORT), + .USE_MULT(USE_MULT), + .USE_PATTERN_DETECT(USE_PATTERN_DETECT), + .USE_SIMD(USE_SIMD), + .MASK(MASK), + .PATTERN(PATTERN), + .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), + .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), + .IS_CLK_INVERTED(IS_CLK_INVERTED), + .IS_INMODE_INVERTED(IS_INMODE_INVERTED), + .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED) + ) _TECHMAP_REPLACE_ ( + .ACOUT(ACOUT), + .BCOUT(BCOUT), + .CARRYCASCOUT(CARRYCASCOUT), + .CARRYOUT(CARRYOUT), + .MULTSIGNOUT(MULTSIGNOUT), + .OVERFLOW(OVERFLOW), + .P(P), + .PATTERNBDETECT(PATTERNBDETECT), + .PATTERNDETECT(PATTERNDETECT), + .PCOUT(PCOUT), + .UNDERFLOW(UNDERFLOW), + .A(A), + .ACIN(ACIN), + .ALUMODE(ALUMODE), + .B(B), + .BCIN(BCIN), + .C(C), + .CARRYCASCIN(CARRYCASCIN), + .CARRYIN(CARRYIN), + .CARRYINSEL(CARRYINSEL), + .CEA1(CEA1), + .CEA2(CEA2), + .CEAD(CEAD), + .CEALUMODE(CEALUMODE), + .CEB1(CEB1), + .CEB2(CEB2), + .CEC(CEC), + .CECARRYIN(CECARRYIN), + .CECTRL(CECTRL), + .CED(CED), + .CEINMODE(CEINMODE), + .CEM(CEM), + .CEP(CEP), + .CLK(CLK), + .D(D), + .INMODE(INMODE), + .MULTSIGNIN(MULTSIGNIN), + .OPMODE(OPMODE), + .PCIN(PCIN), + .RSTA(RSTA), + .RSTALLCARRYIN(RSTALLCARRYIN), + .RSTALUMODE(RSTALUMODE), + .RSTB(RSTB), + .RSTC(RSTC), + .RSTCTRL(RSTCTRL), + .RSTD(RSTD), + .RSTINMODE(RSTINMODE), + .RSTM(RSTM), + .RSTP(RSTP) + ); +endmodule diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 20da3b8a0..bbd38d90c 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -59,3 +59,370 @@ $__ABC_LUT6 2000 0 7 1 # Outputs: DPO SPO $__ABC_LUT7 2001 0 8 1 0 1047 1036 877 812 643 532 478 + +$__ABC_DSP48E1_MULT_P_MUX 2100 0 55 48 +# A AD B C D M P Pq +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 + +$__ABC_DSP48E1_MULT_PCOUT_MUX 2101 0 55 48 +# A AD B C D M P Pq +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 + +$__ABC_DSP48E1_MULT 3000 0 263 154 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From aaeaab4ac035aaf79f46873e27b8d464675d1c9c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 12 Sep 2019 17:45:02 -0700 Subject: [PATCH 243/356] Rename to techmap_guard --- techlibs/xilinx/abc_map.v | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index be69ae256..f52397c9f 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -205,6 +205,7 @@ module DSP48E1 ( parameter [6:0] IS_OPMODE_INVERTED = 7'b0; parameter _TECHMAP_CELLTYPE_ = ""; + localparam techmap_guard = (_TECHMAP_CELLTYPE_ != ""); generate if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin @@ -232,9 +233,9 @@ module DSP48E1 ( \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0) assign iD = D; - else if (_TECHMAP_CELLTYPE_ != "") + else if (techmap_guard) $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); - if (ADREG == 1 && _TECHMAP_CELLTYPE_ != "") + if (ADREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); if (PREG == 0) begin if (MREG == 1) From c52863f147c45727dc38dd349f3f5d756baf27ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 12 Sep 2019 18:01:49 -0700 Subject: [PATCH 244/356] Finish explanation --- techlibs/xilinx/abc_model.v | 14 ++++++++++---- techlibs/xilinx/abc_xc7.box | 11 ++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index 95a368306..504f8a0d8 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -44,6 +44,16 @@ endmodule module \$__ABC_LUT7 (input A, input [6:0] S, output Y); endmodule +// Boxes used to represent the comb/seq behaviour of DSP48E1 +// With abc_map.v responsible for disconnecting inputs to +// the combinatorial DSP48E1 model by a register (e.g. +// disconnecting A when AREG, MREG or PREG is enabled) +// this mux captures the existence of a replacement path +// between AREG/BREG/CREG/etc. and P/PCOUT. +// Since the Aq/ADq/Bq/etc. inputs are assumed to arrive at +// the mux at zero time, the combinatorial delay through +// these muxes thus represents the clock-to-q delay at +// P/PCOUT. (* abc_box_id=2100 *) module \$__ABC_DSP48E1_MULT_P_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); endmodule @@ -51,10 +61,6 @@ endmodule module \$__ABC_DSP48E1_MULT_PCOUT_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); endmodule -// Box used to represent the comb/seq behaviour of DSP48E1 -// abc_map.v is responsible for disconnecting inputs to -// the combinatorial DSP48E1 model by a register (e.g. -// disconnecting A when AREG, MREG or PREG is enabled) (* abc_box_id=3000 *) module \$__ABC_DSP48E1_MULT ( output [29:0] ACOUT, diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index bbd38d90c..e4b1dcd32 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -60,6 +60,16 @@ $__ABC_LUT6 2000 0 7 1 $__ABC_LUT7 2001 0 8 1 0 1047 1036 877 812 643 532 478 +# Boxes used to represent the comb/seq behaviour of DSP48E1 +# With abc_map.v responsible for disconnecting inputs to +# the combinatorial DSP48E1 model by a register (e.g. +# disconnecting A when AREG, MREG or PREG is enabled) +# this mux captures the existence of a replacement path +# between AREG/BREG/CREG/etc. and P/PCOUT. +# Since the Aq/ADq/Bq/etc. inputs are assumed to arrive at +# the mux at zero time, the combinatorial delay through +# these muxes thus represents the clock-to-q delay at +# P/PCOUT. $__ABC_DSP48E1_MULT_P_MUX 2100 0 55 48 # A AD B C D M P Pq 2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 @@ -110,7 +120,6 @@ $__ABC_DSP48E1_MULT_P_MUX 2100 0 55 48 2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 - $__ABC_DSP48E1_MULT_PCOUT_MUX 2101 0 55 48 # A AD B C D M P Pq 3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 From 734034a8727023fdb74c9a6acd2cb6d1bfe3e81c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 12 Sep 2019 18:13:46 -0700 Subject: [PATCH 245/356] Add an ASCII drawing --- techlibs/xilinx/abc_model.v | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index 504f8a0d8..109804f09 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -48,12 +48,31 @@ endmodule // With abc_map.v responsible for disconnecting inputs to // the combinatorial DSP48E1 model by a register (e.g. // disconnecting A when AREG, MREG or PREG is enabled) -// this mux captures the existence of a replacement path -// between AREG/BREG/CREG/etc. and P/PCOUT. +// this blackbox captures the existence of a replacement +// path between AREG/BREG/CREG/etc. and P/PCOUT. // Since the Aq/ADq/Bq/etc. inputs are assumed to arrive at -// the mux at zero time, the combinatorial delay through +// the box at zero time, the combinatorial delay through // these muxes thus represents the clock-to-q delay at // P/PCOUT. +// Doing so should means that ABC is able to analyse the +// worst-case delay through to P. +// However, the true value of being as complete as this is +// questionable since if AREG=1 and BREG=0 (as below) +// then the worse-case path would very likely be through B +// and very unlikely to be through AREG.Q...? +// +// In graphical form: +// +// NEW "PI" >>---+ +// for AREG.Q | +// | +// +---------+ | __ +// A --X X-| | +--| \ +// | DSP48E1 |P | |--- P +// | AREG=1 |-------|__/ +// B ------| | +// +---------+ +// (* abc_box_id=2100 *) module \$__ABC_DSP48E1_MULT_P_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); endmodule From e235dd07854ad31617a4609c59dbdeacb9323ad0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 13 Sep 2019 09:34:40 -0700 Subject: [PATCH 246/356] Refine diagram --- techlibs/xilinx/abc_model.v | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index 109804f09..5963258e8 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -52,10 +52,12 @@ endmodule // path between AREG/BREG/CREG/etc. and P/PCOUT. // Since the Aq/ADq/Bq/etc. inputs are assumed to arrive at // the box at zero time, the combinatorial delay through -// these muxes thus represents the clock-to-q delay at -// P/PCOUT. +// these boxes thus represents the clock-to-q delay +// (arrival time) at P/PCOUT. // Doing so should means that ABC is able to analyse the -// worst-case delay through to P. +// worst-case delay through to P, regardless of if it was +// through any combinatorial paths (e.g. B, below) or an +// internal register (A2REG). // However, the true value of being as complete as this is // questionable since if AREG=1 and BREG=0 (as below) // then the worse-case path would very likely be through B @@ -63,15 +65,15 @@ endmodule // // In graphical form: // -// NEW "PI" >>---+ -// for AREG.Q | -// | -// +---------+ | __ -// A --X X-| | +--| \ -// | DSP48E1 |P | |--- P -// | AREG=1 |-------|__/ -// B ------| | -// +---------+ +// NEW "PI" >>---+ +// for AREG.Q | +// | +// +---------+ | __ +// A >>--X X-| | +--| \ +// | DSP48E1 |P | |--->> P +// | AREG=1 |-------|__/ +// B >>------| | +// +---------+ // (* abc_box_id=2100 *) module \$__ABC_DSP48E1_MULT_P_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); From 247a63f55df2e85f0aa15a9a05f436c1225f9ec1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 13 Sep 2019 11:45:55 -0700 Subject: [PATCH 247/356] Add support for MULT and DPORT --- techlibs/xilinx/abc_map.v | 134 ++++++++++++- techlibs/xilinx/abc_model.v | 90 ++++++++- techlibs/xilinx/abc_unmap.v | 9 +- techlibs/xilinx/abc_xc7.box | 365 ++++++++++++++++++++++++++++++++++++ 4 files changed, 588 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index f52397c9f..27133fc1e 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -219,15 +219,15 @@ module DSP48E1 ( // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken - if (AREG == 0 || MREG == 1 || PREG == 1) + if (AREG == 0 && MREG == 0 && PREG == 0) assign iA = A; else \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); - if (BREG == 0 || MREG == 1 || PREG == 1) + if (BREG == 0 && MREG == 0 && PREG == 0) assign iB = B; else \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); - if (CREG == 0 || PREG == 1) + if (CREG == 0 && PREG == 0) assign iC = C; else \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); @@ -334,7 +334,133 @@ module DSP48E1 ( .RSTP(RSTP) ); end + else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin + wire [29:0] iA; + wire [17:0] iB; + wire [47:0] iC; + wire [24:0] iD; + + wire pA, pB, pC, pD, pAD, pM, pP; + wire [47:0] oP, oPCOUT; + + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken + if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 1) + assign iA = A; + else + \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); + if (BREG == 0 && MREG == 0 && PREG == 0) + assign iB = B; + else + \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); + if (CREG == 0 && PREG == 0) + assign iC = C; + else + \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); + if (DREG == 0 && ADREG == 0) + assign iD = D; + else + \$__ABC_DSP48E1_REG rD (.I(D), .O(iD), .Q(pD)); + if (PREG == 0) begin + if (MREG == 1) + \$__ABC_DSP48E1_REG rM (.Q(pM)); + else if (ADREG == 1) + \$__ABC_DSP48E1_REG rAD (.Q(pAD)); + end + else + \$__ABC_DSP48E1_REG rP (.Q(pP)); + + \$__ABC_DSP48E1_MULT_DPORT_P_MUX muxP ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) + ); + \$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) + ); + + \$__ABC_DSP48E1_MULT_DPORT #( + .ACASCREG(ACASCREG), + .ADREG(ADREG), + .ALUMODEREG(ALUMODEREG), + .AREG(AREG), + .AUTORESET_PATDET(AUTORESET_PATDET), + .A_INPUT(A_INPUT), + .BCASCREG(BCASCREG), + .BREG(BREG), + .B_INPUT(B_INPUT), + .CARRYINREG(CARRYINREG), + .CARRYINSELREG(CARRYINSELREG), + .CREG(CREG), + .DREG(DREG), + .INMODEREG(INMODEREG), + .MREG(MREG), + .OPMODEREG(OPMODEREG), + .PREG(PREG), + .SEL_MASK(SEL_MASK), + .SEL_PATTERN(SEL_PATTERN), + .USE_DPORT(USE_DPORT), + .USE_MULT(USE_MULT), + .USE_PATTERN_DETECT(USE_PATTERN_DETECT), + .USE_SIMD(USE_SIMD), + .MASK(MASK), + .PATTERN(PATTERN), + .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), + .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), + .IS_CLK_INVERTED(IS_CLK_INVERTED), + .IS_INMODE_INVERTED(IS_INMODE_INVERTED), + .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED) + ) _TECHMAP_REPLACE_ ( + .ACOUT(ACOUT), + .BCOUT(BCOUT), + .CARRYCASCOUT(CARRYCASCOUT), + .CARRYOUT(CARRYOUT), + .MULTSIGNOUT(MULTSIGNOUT), + .OVERFLOW(OVERFLOW), + .P(oP), + .PATTERNBDETECT(PATTERNBDETECT), + .PATTERNDETECT(PATTERNDETECT), + .PCOUT(oPCOUT), + .UNDERFLOW(UNDERFLOW), + .A(iA), + .ACIN(ACIN), + .ALUMODE(ALUMODE), + .B(iB), + .BCIN(BCIN), + .C(iC), + .CARRYCASCIN(CARRYCASCIN), + .CARRYIN(CARRYIN), + .CARRYINSEL(CARRYINSEL), + .CEA1(CEA1), + .CEA2(CEA2), + .CEAD(CEAD), + .CEALUMODE(CEALUMODE), + .CEB1(CEB1), + .CEB2(CEB2), + .CEC(CEC), + .CECARRYIN(CECARRYIN), + .CECTRL(CECTRL), + .CED(CED), + .CEINMODE(CEINMODE), + .CEM(CEM), + .CEP(CEP), + .CLK(CLK), + .D(iD), + .INMODE(INMODE), + .MULTSIGNIN(MULTSIGNIN), + .OPMODE(OPMODE), + .PCIN(PCIN), + .RSTA(RSTA), + .RSTALLCARRYIN(RSTALLCARRYIN), + .RSTALUMODE(RSTALUMODE), + .RSTB(RSTB), + .RSTC(RSTC), + .RSTCTRL(RSTCTRL), + .RSTD(RSTD), + .RSTINMODE(RSTINMODE), + .RSTM(RSTM), + .RSTP(RSTP) + ); + end else - wire _TECHMAP_FAIL_ = 1; + $error("Invalid DSP48E1 configuration"); endgenerate endmodule diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index 5963258e8..4310ad39e 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -81,6 +81,12 @@ endmodule (* abc_box_id=2101 *) module \$__ABC_DSP48E1_MULT_PCOUT_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); endmodule +(* abc_box_id=2102 *) +module \$__ABC_DSP48E1_MULT_DPORT_P_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); +endmodule +(* abc_box_id=2103 *) +module \$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); +endmodule (* abc_box_id=3000 *) module \$__ABC_DSP48E1_MULT ( @@ -166,4 +172,86 @@ module \$__ABC_DSP48E1_MULT ( parameter [6:0] IS_OPMODE_INVERTED = 7'b0; endmodule - +(* abc_box_id=3001 *) +module \$__ABC_DSP48E1_MULT_DPORT ( + output [29:0] ACOUT, + output [17:0] BCOUT, + output reg CARRYCASCOUT, + output reg [3:0] CARRYOUT, + output reg MULTSIGNOUT, + output OVERFLOW, + output reg signed [47:0] P, + output PATTERNBDETECT, + output PATTERNDETECT, + output [47:0] PCOUT, + output UNDERFLOW, + input signed [29:0] A, + input [29:0] ACIN, + input [3:0] ALUMODE, + input signed [17:0] B, + input [17:0] BCIN, + input [47:0] C, + input CARRYCASCIN, + input CARRYIN, + input [2:0] CARRYINSEL, + input CEA1, + input CEA2, + input CEAD, + input CEALUMODE, + input CEB1, + input CEB2, + input CEC, + input CECARRYIN, + input CECTRL, + input CED, + input CEINMODE, + input CEM, + input CEP, + input CLK, + input [24:0] D, + input [4:0] INMODE, + input MULTSIGNIN, + input [6:0] OPMODE, + input [47:0] PCIN, + input RSTA, + input RSTALLCARRYIN, + input RSTALUMODE, + input RSTB, + input RSTC, + input RSTCTRL, + input RSTD, + input RSTINMODE, + input RSTM, + input RSTP +); + parameter integer ACASCREG = 1; + parameter integer ADREG = 1; + parameter integer ALUMODEREG = 1; + parameter integer AREG = 1; + parameter AUTORESET_PATDET = "NO_RESET"; + parameter A_INPUT = "DIRECT"; + parameter integer BCASCREG = 1; + parameter integer BREG = 1; + parameter B_INPUT = "DIRECT"; + parameter integer CARRYINREG = 1; + parameter integer CARRYINSELREG = 1; + parameter integer CREG = 1; + parameter integer DREG = 1; + parameter integer INMODEREG = 1; + parameter integer MREG = 1; + parameter integer OPMODEREG = 1; + parameter integer PREG = 1; + parameter SEL_MASK = "MASK"; + parameter SEL_PATTERN = "PATTERN"; + parameter USE_DPORT = "FALSE"; + parameter USE_MULT = "MULTIPLY"; + parameter USE_PATTERN_DETECT = "NO_PATDET"; + parameter USE_SIMD = "ONE48"; + parameter [47:0] MASK = 48'h3FFFFFFFFFFF; + parameter [47:0] PATTERN = 48'h000000000000; + parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; + parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + parameter [4:0] IS_INMODE_INVERTED = 5'b0; + parameter [6:0] IS_OPMODE_INVERTED = 7'b0; +endmodule diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index bcb1069bc..f9b5bd518 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -30,14 +30,13 @@ endmodule module \$__ABC_DSP48E1_REG (input [47:0] I, output [47:0] O, output Q); assign O = I; endmodule -module \$__ABC_DSP48E1_MULT_P_MUX (input Aq, Bq, Cq, Dq, ADq, Mq, input [47:0] P, input Pq, output [47:0] O); - assign O = P; -endmodule -module \$__ABC_DSP48E1_MULT_PCOUT_MUX (input Aq, Bq, Cq, Dq, ADq, Mq, input [47:0] P, input Pq, output [47:0] O); +(* techmap_celltype = "$__ABC_DSP48E1_MULT_P_MUX $__ABC_DSP48E1_MULT_PCOUT_MUX $__ABC_DSP48E1_MULT_DPORT_P_MUX $__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX" *) +module \$__ABC_DSP48E1_MUX (input Aq, Bq, Cq, Dq, ADq, Mq, input [47:0] P, input Pq, output [47:0] O); assign O = P; endmodule -module \$__ABC_DSP48E1_MULT ( +(* techmap_celltype = "$__ABC_DSP48E1_MULT $__ABC_DSP48E1_MULT_DPORT" *) +module \$__ABC_DSP48E1 ( output [29:0] ACOUT, output [17:0] BCOUT, output reg CARRYCASCOUT, diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index e4b1dcd32..7e56e6121 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -170,6 +170,106 @@ $__ABC_DSP48E1_MULT_PCOUT_MUX 2101 0 55 48 3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +$__ABC_DSP48E1_MULT_DPORT_P_MUX 2102 0 55 48 +# A AD B C D M P Pq +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 55 48 +# A AD B C D M P Pq +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 $__ABC_DSP48E1_MULT 3000 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - @@ -435,3 +535,268 @@ $__ABC_DSP48E1_MULT 3000 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +$__ABC_DSP48E1_MULT_DPORT 3001 0 263 154 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From d0b202c58d45145e79243caac55f155328008d39 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 13 Sep 2019 12:05:14 -0700 Subject: [PATCH 248/356] Add no MULT no DPORT config --- techlibs/xilinx/abc_map.v | 292 +++++++++++++---------------- techlibs/xilinx/abc_model.v | 110 ++--------- techlibs/xilinx/abc_unmap.v | 4 +- techlibs/xilinx/abc_xc7.box | 365 +++++++++++++++++++++++++++++++++++- 4 files changed, 508 insertions(+), 263 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 27133fc1e..6e36417e2 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -207,6 +207,91 @@ module DSP48E1 ( parameter _TECHMAP_CELLTYPE_ = ""; localparam techmap_guard = (_TECHMAP_CELLTYPE_ != ""); +`define DSP48E1_inst(__CELL__) """ +__CELL__ #( + .ACASCREG(ACASCREG), + .ADREG(ADREG), + .ALUMODEREG(ALUMODEREG), + .AREG(AREG), + .AUTORESET_PATDET(AUTORESET_PATDET), + .A_INPUT(A_INPUT), + .BCASCREG(BCASCREG), + .BREG(BREG), + .B_INPUT(B_INPUT), + .CARRYINREG(CARRYINREG), + .CARRYINSELREG(CARRYINSELREG), + .CREG(CREG), + .DREG(DREG), + .INMODEREG(INMODEREG), + .MREG(MREG), + .OPMODEREG(OPMODEREG), + .PREG(PREG), + .SEL_MASK(SEL_MASK), + .SEL_PATTERN(SEL_PATTERN), + .USE_DPORT(USE_DPORT), + .USE_MULT(USE_MULT), + .USE_PATTERN_DETECT(USE_PATTERN_DETECT), + .USE_SIMD(USE_SIMD), + .MASK(MASK), + .PATTERN(PATTERN), + .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), + .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), + .IS_CLK_INVERTED(IS_CLK_INVERTED), + .IS_INMODE_INVERTED(IS_INMODE_INVERTED), + .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED) + ) _TECHMAP_REPLACE_ ( + .ACOUT(ACOUT), + .BCOUT(BCOUT), + .CARRYCASCOUT(CARRYCASCOUT), + .CARRYOUT(CARRYOUT), + .MULTSIGNOUT(MULTSIGNOUT), + .OVERFLOW(OVERFLOW), + .P(oP), + .PATTERNBDETECT(PATTERNBDETECT), + .PATTERNDETECT(PATTERNDETECT), + .PCOUT(oPCOUT), + .UNDERFLOW(UNDERFLOW), + .A(iA), + .ACIN(ACIN), + .ALUMODE(ALUMODE), + .B(iB), + .BCIN(BCIN), + .C(iC), + .CARRYCASCIN(CARRYCASCIN), + .CARRYIN(CARRYIN), + .CARRYINSEL(CARRYINSEL), + .CEA1(CEA1), + .CEA2(CEA2), + .CEAD(CEAD), + .CEALUMODE(CEALUMODE), + .CEB1(CEB1), + .CEB2(CEB2), + .CEC(CEC), + .CECARRYIN(CECARRYIN), + .CECTRL(CECTRL), + .CED(CED), + .CEINMODE(CEINMODE), + .CEM(CEM), + .CEP(CEP), + .CLK(CLK), + .D(iD), + .INMODE(INMODE), + .MULTSIGNIN(MULTSIGNIN), + .OPMODE(OPMODE), + .PCIN(PCIN), + .RSTA(RSTA), + .RSTALLCARRYIN(RSTALLCARRYIN), + .RSTALUMODE(RSTALUMODE), + .RSTB(RSTB), + .RSTC(RSTC), + .RSTCTRL(RSTCTRL), + .RSTD(RSTD), + .RSTINMODE(RSTINMODE), + .RSTM(RSTM), + .RSTP(RSTP) + ); +""" + generate if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin wire [29:0] iA; @@ -251,88 +336,7 @@ module DSP48E1 ( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) ); - \$__ABC_DSP48E1_MULT #( - .ACASCREG(ACASCREG), - .ADREG(ADREG), - .ALUMODEREG(ALUMODEREG), - .AREG(AREG), - .AUTORESET_PATDET(AUTORESET_PATDET), - .A_INPUT(A_INPUT), - .BCASCREG(BCASCREG), - .BREG(BREG), - .B_INPUT(B_INPUT), - .CARRYINREG(CARRYINREG), - .CARRYINSELREG(CARRYINSELREG), - .CREG(CREG), - .DREG(DREG), - .INMODEREG(INMODEREG), - .MREG(MREG), - .OPMODEREG(OPMODEREG), - .PREG(PREG), - .SEL_MASK(SEL_MASK), - .SEL_PATTERN(SEL_PATTERN), - .USE_DPORT(USE_DPORT), - .USE_MULT(USE_MULT), - .USE_PATTERN_DETECT(USE_PATTERN_DETECT), - .USE_SIMD(USE_SIMD), - .MASK(MASK), - .PATTERN(PATTERN), - .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), - .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), - .IS_CLK_INVERTED(IS_CLK_INVERTED), - .IS_INMODE_INVERTED(IS_INMODE_INVERTED), - .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED) - ) _TECHMAP_REPLACE_ ( - .ACOUT(ACOUT), - .BCOUT(BCOUT), - .CARRYCASCOUT(CARRYCASCOUT), - .CARRYOUT(CARRYOUT), - .MULTSIGNOUT(MULTSIGNOUT), - .OVERFLOW(OVERFLOW), - .P(oP), - .PATTERNBDETECT(PATTERNBDETECT), - .PATTERNDETECT(PATTERNDETECT), - .PCOUT(oPCOUT), - .UNDERFLOW(UNDERFLOW), - .A(iA), - .ACIN(ACIN), - .ALUMODE(ALUMODE), - .B(iB), - .BCIN(BCIN), - .C(iC), - .CARRYCASCIN(CARRYCASCIN), - .CARRYIN(CARRYIN), - .CARRYINSEL(CARRYINSEL), - .CEA1(CEA1), - .CEA2(CEA2), - .CEAD(CEAD), - .CEALUMODE(CEALUMODE), - .CEB1(CEB1), - .CEB2(CEB2), - .CEC(CEC), - .CECARRYIN(CECARRYIN), - .CECTRL(CECTRL), - .CED(CED), - .CEINMODE(CEINMODE), - .CEM(CEM), - .CEP(CEP), - .CLK(CLK), - .D(iD), - .INMODE(INMODE), - .MULTSIGNIN(MULTSIGNIN), - .OPMODE(OPMODE), - .PCIN(PCIN), - .RSTA(RSTA), - .RSTALLCARRYIN(RSTALLCARRYIN), - .RSTALUMODE(RSTALUMODE), - .RSTB(RSTB), - .RSTC(RSTC), - .RSTCTRL(RSTCTRL), - .RSTD(RSTD), - .RSTINMODE(RSTINMODE), - .RSTM(RSTM), - .RSTP(RSTP) - ); + `DSP48E1_inst(\$__ABC_DSP48E1_MULT ) end else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin wire [29:0] iA; @@ -345,7 +349,7 @@ module DSP48E1 ( // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken - if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 1) + if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0) assign iA = A; else \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); @@ -377,88 +381,48 @@ module DSP48E1 ( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) ); - \$__ABC_DSP48E1_MULT_DPORT #( - .ACASCREG(ACASCREG), - .ADREG(ADREG), - .ALUMODEREG(ALUMODEREG), - .AREG(AREG), - .AUTORESET_PATDET(AUTORESET_PATDET), - .A_INPUT(A_INPUT), - .BCASCREG(BCASCREG), - .BREG(BREG), - .B_INPUT(B_INPUT), - .CARRYINREG(CARRYINREG), - .CARRYINSELREG(CARRYINSELREG), - .CREG(CREG), - .DREG(DREG), - .INMODEREG(INMODEREG), - .MREG(MREG), - .OPMODEREG(OPMODEREG), - .PREG(PREG), - .SEL_MASK(SEL_MASK), - .SEL_PATTERN(SEL_PATTERN), - .USE_DPORT(USE_DPORT), - .USE_MULT(USE_MULT), - .USE_PATTERN_DETECT(USE_PATTERN_DETECT), - .USE_SIMD(USE_SIMD), - .MASK(MASK), - .PATTERN(PATTERN), - .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), - .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), - .IS_CLK_INVERTED(IS_CLK_INVERTED), - .IS_INMODE_INVERTED(IS_INMODE_INVERTED), - .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED) - ) _TECHMAP_REPLACE_ ( - .ACOUT(ACOUT), - .BCOUT(BCOUT), - .CARRYCASCOUT(CARRYCASCOUT), - .CARRYOUT(CARRYOUT), - .MULTSIGNOUT(MULTSIGNOUT), - .OVERFLOW(OVERFLOW), - .P(oP), - .PATTERNBDETECT(PATTERNBDETECT), - .PATTERNDETECT(PATTERNDETECT), - .PCOUT(oPCOUT), - .UNDERFLOW(UNDERFLOW), - .A(iA), - .ACIN(ACIN), - .ALUMODE(ALUMODE), - .B(iB), - .BCIN(BCIN), - .C(iC), - .CARRYCASCIN(CARRYCASCIN), - .CARRYIN(CARRYIN), - .CARRYINSEL(CARRYINSEL), - .CEA1(CEA1), - .CEA2(CEA2), - .CEAD(CEAD), - .CEALUMODE(CEALUMODE), - .CEB1(CEB1), - .CEB2(CEB2), - .CEC(CEC), - .CECARRYIN(CECARRYIN), - .CECTRL(CECTRL), - .CED(CED), - .CEINMODE(CEINMODE), - .CEM(CEM), - .CEP(CEP), - .CLK(CLK), - .D(iD), - .INMODE(INMODE), - .MULTSIGNIN(MULTSIGNIN), - .OPMODE(OPMODE), - .PCIN(PCIN), - .RSTA(RSTA), - .RSTALLCARRYIN(RSTALLCARRYIN), - .RSTALUMODE(RSTALUMODE), - .RSTB(RSTB), - .RSTC(RSTC), - .RSTCTRL(RSTCTRL), - .RSTD(RSTD), - .RSTINMODE(RSTINMODE), - .RSTM(RSTM), - .RSTP(RSTP) + `DSP48E1_inst(\$__ABC_DSP48E1_MULTD_PORT ) + end + else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin + wire [29:0] iA; + wire [17:0] iB; + wire [47:0] iC; + wire [24:0] iD; + + wire pA, pB, pC, pD, pAD, pM, pP; + wire [47:0] oP, oPCOUT; + + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken + if (AREG == 0 && PREG == 0) + assign iA = A; + else + \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); + if (BREG == 0 && PREG == 0) + assign iB = B; + else + \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); + if (CREG == 0 && PREG == 0) + assign iC = C; + else + \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); + if (MREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\""); + if (DREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + if (ADREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); + if (PREG == 1) + \$__ABC_DSP48E1_REG rP (.Q(pP)); + + \$__ABC_DSP48E1_P_MUX muxP ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) ); + \$__ABC_DSP48E1_PCOUT_MUX muxPCOUT ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) + ); + + `DSP48E1_inst(\$__ABC_DSP48E1_MULTD_PORT ) end else $error("Invalid DSP48E1 configuration"); diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index 4310ad39e..a8f6deafc 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -75,20 +75,18 @@ endmodule // B >>------| | // +---------+ // -(* abc_box_id=2100 *) -module \$__ABC_DSP48E1_MULT_P_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); -endmodule -(* abc_box_id=2101 *) -module \$__ABC_DSP48E1_MULT_PCOUT_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); -endmodule -(* abc_box_id=2102 *) -module \$__ABC_DSP48E1_MULT_DPORT_P_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); -endmodule -(* abc_box_id=2103 *) -module \$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); +`define ABC_DSP48E1_MUX(__NAME__) """ +module __NAME__ (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); endmodule +""" +(* abc_box_id=2100 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_P_MUX ) +(* abc_box_id=2101 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_PCOUT_MUX ) +(* abc_box_id=2102 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_DPORT_P_MUX ) +(* abc_box_id=2103 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX ) +(* abc_box_id=2104 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_P_MUX ) +(* abc_box_id=2105 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_PCOUT_MUX ) -(* abc_box_id=3000 *) +`define ABC_DSP48E1(__NAME__) """ module \$__ABC_DSP48E1_MULT ( output [29:0] ACOUT, output [17:0] BCOUT, @@ -171,87 +169,7 @@ module \$__ABC_DSP48E1_MULT ( parameter [4:0] IS_INMODE_INVERTED = 5'b0; parameter [6:0] IS_OPMODE_INVERTED = 7'b0; endmodule - -(* abc_box_id=3001 *) -module \$__ABC_DSP48E1_MULT_DPORT ( - output [29:0] ACOUT, - output [17:0] BCOUT, - output reg CARRYCASCOUT, - output reg [3:0] CARRYOUT, - output reg MULTSIGNOUT, - output OVERFLOW, - output reg signed [47:0] P, - output PATTERNBDETECT, - output PATTERNDETECT, - output [47:0] PCOUT, - output UNDERFLOW, - input signed [29:0] A, - input [29:0] ACIN, - input [3:0] ALUMODE, - input signed [17:0] B, - input [17:0] BCIN, - input [47:0] C, - input CARRYCASCIN, - input CARRYIN, - input [2:0] CARRYINSEL, - input CEA1, - input CEA2, - input CEAD, - input CEALUMODE, - input CEB1, - input CEB2, - input CEC, - input CECARRYIN, - input CECTRL, - input CED, - input CEINMODE, - input CEM, - input CEP, - input CLK, - input [24:0] D, - input [4:0] INMODE, - input MULTSIGNIN, - input [6:0] OPMODE, - input [47:0] PCIN, - input RSTA, - input RSTALLCARRYIN, - input RSTALUMODE, - input RSTB, - input RSTC, - input RSTCTRL, - input RSTD, - input RSTINMODE, - input RSTM, - input RSTP -); - parameter integer ACASCREG = 1; - parameter integer ADREG = 1; - parameter integer ALUMODEREG = 1; - parameter integer AREG = 1; - parameter AUTORESET_PATDET = "NO_RESET"; - parameter A_INPUT = "DIRECT"; - parameter integer BCASCREG = 1; - parameter integer BREG = 1; - parameter B_INPUT = "DIRECT"; - parameter integer CARRYINREG = 1; - parameter integer CARRYINSELREG = 1; - parameter integer CREG = 1; - parameter integer DREG = 1; - parameter integer INMODEREG = 1; - parameter integer MREG = 1; - parameter integer OPMODEREG = 1; - parameter integer PREG = 1; - parameter SEL_MASK = "MASK"; - parameter SEL_PATTERN = "PATTERN"; - parameter USE_DPORT = "FALSE"; - parameter USE_MULT = "MULTIPLY"; - parameter USE_PATTERN_DETECT = "NO_PATDET"; - parameter USE_SIMD = "ONE48"; - parameter [47:0] MASK = 48'h3FFFFFFFFFFF; - parameter [47:0] PATTERN = 48'h000000000000; - parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; - parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - parameter [4:0] IS_INMODE_INVERTED = 5'b0; - parameter [6:0] IS_OPMODE_INVERTED = 7'b0; -endmodule +""" +(* abc_box_id=3000 *) `ABC_DSP48E1(\$__ABC_DSP48E1_MULT ) +(* abc_box_id=3001 *) `ABC_DSP48E1(\$__ABC_DSP48E1_MULT_DPORT ) +(* abc_box_id=3002 *) `ABC_DSP48E1(\$__ABC_DSP48E1 ) diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index f9b5bd518..2ef507bf2 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -30,12 +30,12 @@ endmodule module \$__ABC_DSP48E1_REG (input [47:0] I, output [47:0] O, output Q); assign O = I; endmodule -(* techmap_celltype = "$__ABC_DSP48E1_MULT_P_MUX $__ABC_DSP48E1_MULT_PCOUT_MUX $__ABC_DSP48E1_MULT_DPORT_P_MUX $__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX" *) +(* techmap_celltype = "$__ABC_DSP48E1_MULT_P_MUX $__ABC_DSP48E1_MULT_PCOUT_MUX $__ABC_DSP48E1_MULT_DPORT_P_MUX $__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX $__ABC_DSP48E1_P_MUX $__ABC_DSP48E1_PCOUT_MUX" *) module \$__ABC_DSP48E1_MUX (input Aq, Bq, Cq, Dq, ADq, Mq, input [47:0] P, input Pq, output [47:0] O); assign O = P; endmodule -(* techmap_celltype = "$__ABC_DSP48E1_MULT $__ABC_DSP48E1_MULT_DPORT" *) +(* techmap_celltype = "$__ABC_DSP48E1_MULT $__ABC_DSP48E1_MULT_DPORT $__ABC_DSP48E1" *) module \$__ABC_DSP48E1 ( output [29:0] ACOUT, output [17:0] BCOUT, diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 7e56e6121..9a968fedf 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -270,6 +270,106 @@ $__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 55 48 4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +$__ABC_DSP48E1_P_MUX 2104 0 55 48 +# A AD B C D M P Pq +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC_DSP48E1_PCOUT_MUX 2105 0 55 48 +# A AD B C D M P Pq +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 $__ABC_DSP48E1_MULT 3000 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - @@ -535,7 +635,6 @@ $__ABC_DSP48E1_MULT 3000 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $__ABC_DSP48E1_MULT_DPORT 3001 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 - @@ -800,3 +899,267 @@ $__ABC_DSP48E1_MULT_DPORT 3001 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +$__ABC_DSP48E1 3002 0 263 154 +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 1509 - - 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 1658 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 1107 - - 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 1255 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 61877e13704405a93a7ec70d0d7158f24fcafb82 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 13 Sep 2019 13:32:55 -0700 Subject: [PATCH 249/356] Fix D -> P{,COUT} delay --- techlibs/xilinx/abc_xc7.box | 220 ++++++++++++++++++------------------ 1 file changed, 110 insertions(+), 110 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 9a968fedf..79b400d40 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -700,6 +700,116 @@ $__ABC_DSP48E1_MULT_DPORT 3001 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 - - 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 2838 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - @@ -718,116 +828,6 @@ $__ABC_DSP48E1_MULT_DPORT 3001 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 3717 - - 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 1325 - - 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 1474 - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 681be20ca219fc64e2bf0f9d2c24937f98903455 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 13 Sep 2019 17:07:18 -0700 Subject: [PATCH 250/356] Add `undef DSP48E1_INST --- techlibs/xilinx/abc_map.v | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 6e36417e2..31fd79861 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -207,7 +207,7 @@ module DSP48E1 ( parameter _TECHMAP_CELLTYPE_ = ""; localparam techmap_guard = (_TECHMAP_CELLTYPE_ != ""); -`define DSP48E1_inst(__CELL__) """ +`define DSP48E1_INST(__CELL__) """ __CELL__ #( .ACASCREG(ACASCREG), .ADREG(ADREG), @@ -336,7 +336,7 @@ __CELL__ #( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) ); - `DSP48E1_inst(\$__ABC_DSP48E1_MULT ) + `DSP48E1_INST(\$__ABC_DSP48E1_MULT ) end else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin wire [29:0] iA; @@ -381,7 +381,7 @@ __CELL__ #( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) ); - `DSP48E1_inst(\$__ABC_DSP48E1_MULTD_PORT ) + `DSP48E1_INST(\$__ABC_DSP48E1_MULTD_PORT ) end else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin wire [29:0] iA; @@ -422,9 +422,10 @@ __CELL__ #( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) ); - `DSP48E1_inst(\$__ABC_DSP48E1_MULTD_PORT ) + `DSP48E1_INST(\$__ABC_DSP48E1_MULTD_PORT ) end else $error("Invalid DSP48E1 configuration"); endgenerate + `undef DSP48E1_INST endmodule From 0932e23dffe0a270d4e41a0f09c0bf06b6998091 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Sep 2019 09:34:42 -0700 Subject: [PATCH 251/356] Separate dffrstmux from dffcemux, fix typos --- passes/pmgen/xilinx_dsp.pmg | 52 +++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index fa845b593..407489658 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -63,11 +63,13 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock if (dff) { ffAD = dff; clock = dffclock; + if (dffrstmux) { + ffADrstmux = dffrstmux; + ffADrstpol = dffrstpol; + } if (dffcemux) { ffADcemux = dffcemux; - ffADrstmux = dffrstmux; ffADcepol = dffcepol; - ffADrstpol = dffrstpol; } sigA = dffD; } @@ -115,12 +117,12 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cem ffA2 = dff; clock = dffclock; if (dffrstmux) { - ffA2cepol = dffcepol; + ffA2rstmux = dffrstmux; ffArstpol = dffrstpol; } if (dffcemux) { + ffA2cepol = dffcepol; ffA2cemux = dffcemux; - ffA2rstmux = dffrstmux; } sigA = dffD; } @@ -173,11 +175,13 @@ code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock ffB1 ffB1cemu if (dff) { ffB2 = dff; clock = dffclock; + if (dffrstmux) { + ffB2rstmux = dffrstmux; + ffBrstpol = dffrstpol; + } if (dffcemux) { ffB2cemux = dffcemux; - ffB2rstmux = dffrstmux; ffB2cepol = dffcepol; - ffBrstpol = dffrstpol; } sigB = dffD; @@ -220,11 +224,13 @@ code argQ ffD ffDcemux ffDrstmux ffDcepol ffDrstpol sigD clock if (dff) { ffD = dff; clock = dffclock; + if (dffrstmux) { + ffDrstmux = dffrstmux; + ffDrstpol = dffrstpol; + } if (dffcemux) { ffDcemux = dffcemux; - ffDrstmux = dffrstmux; ffDcepol = dffcepol; - ffDrstpol = dffrstpol; } sigD = dffD; } @@ -238,11 +244,13 @@ code argD ffM ffMcemux ffMrstmux ffMcepol ffMrstpol sigM sigP clock if (dff) { ffM = dff; clock = dffclock; + if (dffrstmux) { + ffMrstmux = dffrstmux; + ffMrstpol = dffrstpol; + } if (dffcemux) { ffMcemux = dffcemux; - ffMrstmux = dffrstmux; ffMcepol = dffcepol; - ffMrstpol = dffrstpol; } sigM = dffQ; } @@ -288,20 +296,22 @@ endcode code argD ffP ffPcemux ffPrstmux ffPcepol ffPrstpol sigP clock if (param(dsp, \PREG).as_int() == 0) { - // If ffMcemux and no postAdd new-value net must have exactly three users: ffMcemux, ffM and ffPcemux - if ((ffMcemux && !postAdd && nusers(sigP) == 3) || - // Otherwise new-value net must have exactly two users: dsp and ffPcemux - ((!ffMcemux || postAdd) && nusers(sigP) == 2)) { + int users = 2; + // If ffMcemux and no postAdd new-value net must have three users: ffMcemux, ffM and ffPcemux + if (ffMcemux && !postAdd) users++; + if (nusers(sigP) == users) { argD = sigP; subpattern(out_dffe); if (dff) { ffP = dff; clock = dffclock; + if (dffrstmux) { + ffPrstmux = dffrstmux; + ffPrstpol = dffrstpol; + } if (dffcemux) { ffPcemux = dffcemux; ffPcepol = dffcepol; - ffPrstmux = dffrstmux; - ffPrstpol = dffrstpol; } sigP = dffQ; } @@ -333,11 +343,13 @@ code argQ ffC ffCcemux ffCrstmux ffCcepol ffCrstpol sigC clock if (dff) { ffC = dff; clock = dffclock; + if (dffrstmux) { + ffCrstmux = dffrstmux; + ffCrstpol = dffrstpol; + } if (dffcemux) { ffCcemux = dffcemux; - ffCrstmux = dffrstmux; ffCcepol = dffcepol; - ffCrstpol = dffrstpol; } sigC = dffD; } @@ -421,7 +433,7 @@ code argD argD = port(ffrstmux, ffrstpol ? \A : \B); dffD.replace(port(ffrstmux, \Y), argD); - // Only search for ffrstmux if argQ has at + // Only search for ffcemux if argQ has at // least 3 users (ff, , ffrstmux) and // dffD only has two (ff, ffrstmux) if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) @@ -525,7 +537,7 @@ endmatch code argD argQ dffrstmux = ffrstmux; if (ffrstmux) { - SigSpec AB = port(ffrstmux, ffcepol ? \A : \B); + SigSpec AB = port(ffrstmux, ffrstpol ? \A : \B); if (ffoffset + GetSize(argD) > GetSize(AB)) reject; From 1f18736d20787ec3f88b63df2e277e4ca3034415 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Sep 2019 09:39:59 -0700 Subject: [PATCH 252/356] Add support for overflow using pattern detector --- passes/pmgen/xilinx_dsp.cc | 19 +++++++++++++++++++ passes/pmgen/xilinx_dsp.pmg | 13 ++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index e0c7823ed..786582cfa 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -271,6 +271,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("postAdd: %s\n", log_id(st.postAdd, "--")); log("postAddMux: %s\n", log_id(st.postAddMux, "--")); log("ffP: %s %s %s\n", log_id(st.ffP, "--"), log_id(st.ffPcemux, "--"), log_id(st.ffPrstmux, "--")); + log("overflow: %s\n", log_id(st.overflow, "--")); #endif log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); @@ -329,6 +330,24 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) pm.autoremove(st.postAdd); } + if (st.overflow) { + log(" overflow %s (%s)\n", log_id(st.overflow), log_id(st.overflow->type)); + cell->setParam("\\USE_PATTERN_DETECT", Const("PATDET")); + cell->setParam("\\SEL_PATTERN", Const("PATTERN")); + cell->setParam("\\SEL_MASK", Const("MASK")); + + if (st.overflow->type == "$ge") { + int B = st.overflow->getPort("\\B").as_int(); + log_assert((B & (B-1)) == 0); // Exact power of 2 + + cell->setParam("\\MASK", Const(B-1, 48)); + cell->setParam("\\PATTERN", Const(0, 48)); + cell->setPort("\\OVERFLOW", st.overflow->getPort("\\Y")); + } + else log_abort(); + + pm.autoremove(st.overflow); + } if (st.clock != SigBit()) { diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 407489658..b93162a0e 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -264,7 +264,6 @@ match postAdd select postAdd->type.in($add) select GetSize(port(postAdd, \Y)) <= 48 - select nusers(port(postAdd, \Y)) == 2 choice AB {\A, \B} select nusers(port(postAdd, AB)) <= 3 filter ffMcemux || nusers(port(postAdd, AB)) == 2 @@ -356,6 +355,18 @@ code argQ ffC ffCcemux ffCrstmux ffCcepol ffCrstpol sigC clock } endcode +match overflow + if ffP + if dsp->parameters.at(\USE_PATTERN_DETECT, Const("NO_PATDET")).decode_string() == "NO_PATDET" + select overflow->type.in($ge) + select GetSize(port(overflow, \Y)) <= 48 + select port(overflow, \B).is_fully_const() + // Check is exact power of 2 + select (port(overflow, \B).as_int() & (port(overflow, \B).as_int()-1)) == 0 + index port(overflow, \A) === sigP + optional +endmatch + code accept; endcode From e992dbf2c525fc3d4e4b4ddaf9bf9ceaae7804d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Sep 2019 10:45:04 -0700 Subject: [PATCH 253/356] Add pattern detection support for DSP48E1 model, check against vendor --- techlibs/xilinx/cells_sim.v | 47 ++++++++++++++++++-- techlibs/xilinx/tests/test_dsp_model.sh | 6 +-- techlibs/xilinx/tests/test_dsp_model.v | 57 ++++++++++++++++++++++++- 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index ed421f85e..2f586e798 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -498,8 +498,8 @@ module DSP48E1 ( output reg MULTSIGNOUT, output OVERFLOW, output reg signed [47:0] P, - output PATTERNBDETECT, - output PATTERNDETECT, + output reg PATTERNBDETECT, + output reg PATTERNDETECT, output [47:0] PCOUT, output UNDERFLOW, input signed [29:0] A, @@ -575,10 +575,8 @@ module DSP48E1 ( initial begin `ifdef __ICARUS__ if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value"); - //if (PREG != 0) $fatal(1, "Unsupported PREG value"); if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value"); if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value"); - if (USE_PATTERN_DETECT != "NO_PATDET") $fatal(1, "Unsupported USE_PATTERN_DETECT value"); if (USE_SIMD != "ONE48" && USE_SIMD != "TWO24" && USE_SIMD != "FOUR12") $fatal(1, "Unsupported USE_SIMD value"); if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value"); if (IS_CARRYIN_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CARRYIN_INVERTED value"); @@ -897,4 +895,45 @@ module DSP48E1 ( assign PCOUT = P; + generate + wire PATTERNDETECTd, PATTERNBDETECTd; + + if (USE_PATTERN_DETECT == "PATDET") begin + // TODO: Support SEL_PATTERN != "PATTERN" and SEL_MASK != "MASK + assign PATTERNDETECTd = &(~(Pd ^ PATTERN) | MASK); + assign PATTERNBDETECTd = &((Pd ^ PATTERN) | MASK); + end else begin + assign PATTERNDETECTd = 1'b1; + assign PATTERNBDETECTd = 1'b1; + end + + if (PREG == 1) begin + reg PATTERNDETECTPAST, PATTERNBDETECTPAST; + initial PATTERNDETECT = 1'b0; + initial PATTERNBDETECT = 1'b0; + initial PATTERNDETECTPAST = 1'b0; + initial PATTERNBDETECTPAST = 1'b0; + always @(posedge CLK) + if (RSTP) begin + PATTERNDETECT <= 1'b0; + PATTERNBDETECT <= 1'b0; + PATTERNDETECTPAST <= 1'b0; + PATTERNBDETECTPAST <= 1'b0; + end else if (CEP) begin + PATTERNDETECT <= PATTERNDETECTd; + PATTERNBDETECT <= PATTERNBDETECTd; + PATTERNDETECTPAST <= PATTERNDETECT; + PATTERNBDETECTPAST <= PATTERNBDETECT; + end + assign OVERFLOW = &{PATTERNDETECTPAST, ~PATTERNBDETECT, ~PATTERNDETECT}; + assign UNDERFLOW = &{PATTERNBDETECTPAST, ~PATTERNBDETECT, ~PATTERNDETECT}; + end else begin + always @* begin + PATTERNDETECT = PATTERNDETECTd; + PATTERNBDETECT = PATTERNBDETECTd; + end + assign OVERFLOW = 1'bx, UNDERFLOW = 1'bx; + end + endgenerate + endmodule diff --git a/techlibs/xilinx/tests/test_dsp_model.sh b/techlibs/xilinx/tests/test_dsp_model.sh index 2acd97eb4..ae925c402 100644 --- a/techlibs/xilinx/tests/test_dsp_model.sh +++ b/techlibs/xilinx/tests/test_dsp_model.sh @@ -4,10 +4,10 @@ sed 's/DSP48E1/DSP48E1_UUT/; /DSP48E1_UUT/,/endmodule/ p; d;' < ../cells_sim.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 fi -for tb in simd24_preadd_noreg_nocasc simd12_preadd_noreg_nocasc \ +for tb in macc_overflow_underflow \ + 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 \ - + 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 vvp -N ./test_dsp_model diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v index 04d5b26ab..db012f169 100644 --- a/techlibs/xilinx/tests/test_dsp_model.v +++ b/techlibs/xilinx/tests/test_dsp_model.v @@ -81,6 +81,26 @@ module testbench; errcount = errcount + 1; ERROR_FLAG = 1; end + if (REF_PATTERNDETECT !== PATTERNDETECT) begin + $display("ERROR at %1t: REF_PATTERNDETECT=%b UUT_PATTERNDETECT=%b DIFF=%b REF_P=%b P=%b", $time, REF_PATTERNDETECT, PATTERNDETECT, REF_PATTERNDETECT ^ PATTERNDETECT, REF_P, P); + errcount = errcount + 1; + ERROR_FLAG = 1; + end + if (REF_PATTERNBDETECT !== PATTERNBDETECT) begin + $display("ERROR at %1t: REF_PATTERNBDETECT=%b UUT_PATTERNBDETECT=%b DIFF=%b", $time, REF_PATTERNBDETECT, PATTERNBDETECT, REF_PATTERNBDETECT ^ PATTERNBDETECT); + errcount = errcount + 1; + ERROR_FLAG = 1; + end + if (REF_OVERFLOW !== OVERFLOW) begin + $display("ERROR at %1t: REF_OVERFLOW=%b UUT_OVERFLOW=%b DIFF=%b", $time, REF_OVERFLOW, OVERFLOW, REF_OVERFLOW ^ OVERFLOW); + errcount = errcount + 1; + ERROR_FLAG = 1; + end + if (REF_UNDERFLOW !== UNDERFLOW) begin + $display("ERROR at %1t: REF_UNDERFLOW=%b UUT_UNDERFLOW=%b DIFF=%b", $time, REF_UNDERFLOW, UNDERFLOW, REF_UNDERFLOW ^ UNDERFLOW); + errcount = errcount + 1; + ERROR_FLAG = 1; + end #3; end endtask @@ -594,4 +614,39 @@ module simd24_preadd_noreg_nocasc; .IS_INMODE_INVERTED (5'b0), .IS_OPMODE_INVERTED (7'b0) ) testbench (); -endmodule \ No newline at end of file +endmodule + +module macc_overflow_underflow; + testbench #( + .ACASCREG (0), + .ADREG (0), + .ALUMODEREG (0), + .AREG (0), + .AUTORESET_PATDET ("NO_RESET"), + .A_INPUT ("DIRECT"), + .BCASCREG (0), + .BREG (0), + .B_INPUT ("DIRECT"), + .CARRYINREG (0), + .CARRYINSELREG (0), + .CREG (0), + .DREG (0), + .INMODEREG (0), + .MREG (0), + .OPMODEREG (0), + .PREG (1), + .SEL_MASK ("MASK"), + .SEL_PATTERN ("PATTERN"), + .USE_DPORT ("FALSE"), + .USE_MULT ("DYNAMIC"), + .USE_PATTERN_DETECT ("PATDET"), + .USE_SIMD ("ONE48"), + .MASK (48'h1FFFFFFFFFFF), + .PATTERN (48'h000000000000), + .IS_ALUMODE_INVERTED(4'b0), + .IS_CARRYIN_INVERTED(1'b0), + .IS_CLK_INVERTED (1'b0), + .IS_INMODE_INVERTED (5'b0), + .IS_OPMODE_INVERTED (7'b0) + ) testbench (); +endmodule From b77cf6ba48ec5f6bc7895ad52d4c9aa56b945e71 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Sep 2019 11:12:46 -0700 Subject: [PATCH 254/356] Mis-spell --- techlibs/xilinx/cells_sim.v | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 2f586e798..1a041aac7 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -597,10 +597,10 @@ module DSP48E1 ( else assign B_muxed = B; endgenerate - reg signed [29:0] Ar1 = 30'b0, Ar2 = 30'b0; - reg signed [24:0] Dr = 25'b0; - reg signed [17:0] Br1 = 18'b0, Br2 = 18'b0; - reg signed [47:0] Cr = 48'b0; + reg signed [29:0] Ar1, Ar2; + reg signed [24:0] Dr; + reg signed [17:0] Br1, Br2; + reg signed [47:0] Cr; reg [4:0] INMODEr = 5'b0; reg [6:0] OPMODEr = 7'b0; reg [3:0] ALUMODEr = 4'b0; @@ -609,6 +609,8 @@ module DSP48E1 ( generate // Configurable A register if (AREG == 2) begin + initial Ar1 = 30'b0; + initial Ar2 = 30'b0; always @(posedge CLK) if (RSTA) begin Ar1 <= 30'b0; @@ -618,6 +620,8 @@ module DSP48E1 ( if (CEA2) Ar2 <= Ar1; end end else if (AREG == 1) begin + //initial Ar1 = 30'b0; + initial Ar2 = 30'b0; always @(posedge CLK) if (RSTA) begin Ar1 <= 30'b0; @@ -633,6 +637,8 @@ module DSP48E1 ( // Configurable B register if (BREG == 2) begin + initial Br1 = 25'b0; + initial Br2 = 25'b0; always @(posedge CLK) if (RSTB) begin Br1 <= 18'b0; @@ -642,6 +648,8 @@ module DSP48E1 ( if (CEB2) Br2 <= Br1; end end else if (BREG == 1) begin + //initial Br1 = 25'b0; + initial Br2 = 25'b0; always @(posedge CLK) if (RSTB) begin Br1 <= 18'b0; @@ -656,24 +664,30 @@ module DSP48E1 ( end // C and D registers + if (CREG == 1) initial Cr = 48'b0; if (CREG == 1) begin always @(posedge CLK) if (RSTC) Cr <= 48'b0; else if (CEC) Cr <= C; end else always @* Cr <= C; + if (CREG == 1) initial Dr = 25'b0; if (DREG == 1) begin always @(posedge CLK) if (RSTD) Dr <= 25'b0; else if (CED) Dr <= D; end else always @* Dr <= D; // Control registers + if (INMODEREG == 1) initial INMODEr = 5'b0; if (INMODEREG == 1) begin always @(posedge CLK) if (RSTINMODE) INMODEr <= 5'b0; else if (CEINMODE) INMODEr <= INMODE; end else always @* INMODEr <= INMODE; + if (OPMODEREG == 1) initial OPMODEr = 7'b0; if (OPMODEREG == 1) begin always @(posedge CLK) if (RSTCTRL) OPMODEr <= 7'b0; else if (CECTRL) OPMODEr <= OPMODE; end else always @* OPMODEr <= OPMODE; + if (ALUMODEREG == 1) initial ALUMODEr = 4'b0; if (ALUMODEREG == 1) begin always @(posedge CLK) if (RSTALUMODE) ALUMODEr <= 4'b0; else if (CEALUMODE) ALUMODEr <= ALUMODE; end else always @* ALUMODEr <= ALUMODE; + if (CARRYINSELREG == 1) initial CARRYINSELr = 3'b0; if (CARRYINSELREG == 1) begin always @(posedge CLK) if (RSTCTRL) CARRYINSELr <= 3'b0; else if (CECTRL) CARRYINSELr <= CARRYINSEL; end else always @* CARRYINSELr <= CARRYINSEL; endgenerate - // A and B cascsde + // A and B cascade generate if (ACASCREG == 1 && AREG == 2) assign ACOUT = Ar1; else assign ACOUT = Ar2; @@ -686,9 +700,10 @@ module DSP48E1 ( wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed; wire signed [24:0] Dr_gated = INMODEr[2] ? Dr : 25'b0; wire signed [24:0] AD_result = INMODEr[3] ? (Dr_gated - Ar12_gated) : (Dr_gated + Ar12_gated); - reg signed [24:0] ADr = 25'b0; + reg signed [24:0] ADr; generate + if (ADREG == 1) initial ADr = 25'b0; if (ADREG == 1) begin always @(posedge CLK) if (RSTD) ADr <= 25'b0; else if (CEAD) ADr <= AD_result; end else always @* ADr <= AD_result; endgenerate @@ -860,10 +875,6 @@ module DSP48E1 ( endgenerate wire signed [47:0] Pd = ALUMODEr[1] ? ~alu_sum : alu_sum; - initial P = 48'b0; - initial CARRYOUT = carryout_reset; - initial CARRYCASCOUT = 1'b0; - initial MULTSIGNOUT = 1'b0; wire [3:0] CARRYOUTd = (OPMODEr[3:0] == 4'b0101 || ALUMODEr[3:2] != 2'b00) ? 4'bxxxx : ((ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out); wire CARRYCASCOUTd = ext_carry_out[3]; @@ -871,6 +882,10 @@ module DSP48E1 ( generate if (PREG == 1) begin + initial P = 48'b0; + initial CARRYOUT = carryout_reset; + initial CARRYCASCOUT = 1'b0; + initial MULTSIGNOUT = 1'b0; always @(posedge CLK) if (RSTP) begin P <= 48'b0; From c3cba7ab93bb21f5fa713fd037c77b890544a95c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Sep 2019 12:07:25 -0700 Subject: [PATCH 255/356] Refine macc testcase --- tests/xilinx/macc.v | 21 +++++++++++++-------- tests/xilinx/macc.ys | 5 ++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/tests/xilinx/macc.v b/tests/xilinx/macc.v index 9d684477f..e36b2bab1 100644 --- a/tests/xilinx/macc.v +++ b/tests/xilinx/macc.v @@ -42,26 +42,29 @@ endmodule // Adapted variant of above module macc2 # (parameter SIZEIN = 16, SIZEOUT = 40) ( - input clk, ce, rst, + input clk, + input ce, + input rst, input signed [SIZEIN-1:0] a, b, - output signed [SIZEOUT-1:0] accum_out + output signed [SIZEOUT-1:0] accum_out, + output overflow ); // Declare registers for intermediate values reg signed [SIZEIN-1:0] a_reg, b_reg, a_reg2, b_reg2; -reg rst_reg; -reg signed [2*SIZEIN-1:0] mult_reg; -reg signed [SIZEOUT-1:0] adder_out, old_result; +reg signed [2*SIZEIN-1:0] mult_reg = 0; +reg signed [SIZEOUT:0] adder_out = 0; +reg overflow_reg; always @(posedge clk) begin - if (ce) + //if (ce) begin a_reg <= a; b_reg <= b; a_reg2 <= a_reg; b_reg2 <= b_reg; mult_reg <= a_reg2 * b_reg2; - rst_reg <= rst; // Store accumulation result into a register adder_out <= adder_out + mult_reg; + overflow_reg <= overflow; end if (rst) begin a_reg <= 0; @@ -70,10 +73,12 @@ always @(posedge clk) begin b_reg2 <= 0; mult_reg <= 0; adder_out <= 0; + overflow_reg <= 1'b0; end end +assign overflow = (adder_out >= 2**(SIZEOUT-1)) | overflow_reg; // Output accumulation result -assign accum_out = adder_out; +assign accum_out = overflow ? 2**(SIZEOUT-1)-1 : adder_out; endmodule diff --git a/tests/xilinx/macc.ys b/tests/xilinx/macc.ys index 294b83c69..417a3b21b 100644 --- a/tests/xilinx/macc.ys +++ b/tests/xilinx/macc.ys @@ -25,4 +25,7 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd macc2 # Constrain all select calls below inside the top module select -assert-count 1 t:BUFG select -assert-count 1 t:DSP48E1 -select -assert-none t:BUFG t:DSP48E1 %% t:* %D +select -assert-count 1 t:FDRE +select -assert-count 1 t:LUT2 +select -assert-count 41 t:LUT3 +select -assert-none t:BUFG t:DSP48E1 t:FDRE t:LUT2 t:LUT3 %% t:* %D From c9fe4d7992078ca0dec2cb7bcc6c58813e73189d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Sep 2019 12:11:33 -0700 Subject: [PATCH 256/356] Add .gitignore --- tests/xilinx/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/xilinx/.gitignore b/tests/xilinx/.gitignore index b48f808a1..54733fb71 100644 --- a/tests/xilinx/.gitignore +++ b/tests/xilinx/.gitignore @@ -1,3 +1,4 @@ /*.log /*.out /run-test.mk +/*_uut.v From 347cbf59bd45345663defa9c99c7fc6563404da6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Sep 2019 12:16:03 -0700 Subject: [PATCH 257/356] Check overflow condition is power of 2 without using int32 --- passes/pmgen/xilinx_dsp.cc | 16 +++++++++++++--- passes/pmgen/xilinx_dsp.pmg | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 786582cfa..8500a6072 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -337,10 +337,20 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) cell->setParam("\\SEL_MASK", Const("MASK")); if (st.overflow->type == "$ge") { - int B = st.overflow->getPort("\\B").as_int(); - log_assert((B & (B-1)) == 0); // Exact power of 2 + Const B = st.overflow->getPort("\\B").as_const(); + log_assert(std::count(B.bits.begin(), B.bits.end(), State::S1) == 1); + // Since B is an exact power of 2, subtract 1 + // by inverting all bits up until hitting + // that one hi bit + for (auto &b : B.bits) + if (b == State::S0) b = State::S1; + else if (b == State::S1) { + b = State::S0; + break; + } + B.extu(48); - cell->setParam("\\MASK", Const(B-1, 48)); + cell->setParam("\\MASK", B); cell->setParam("\\PATTERN", Const(0, 48)); cell->setPort("\\OVERFLOW", st.overflow->getPort("\\Y")); } diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index b93162a0e..08cb1f51b 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -361,8 +361,8 @@ match overflow select overflow->type.in($ge) select GetSize(port(overflow, \Y)) <= 48 select port(overflow, \B).is_fully_const() - // Check is exact power of 2 - select (port(overflow, \B).as_int() & (port(overflow, \B).as_int()-1)) == 0 + define B port(overflow, \B).as_const() + select std::count(B.bits.begin(), B.bits.end(), State::S1) == 1 index port(overflow, \A) === sigP optional endmatch From 25e0f0c3765060b7ce25a0c58bc926b90dba304d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Sep 2019 12:19:16 -0700 Subject: [PATCH 258/356] Fix copy-paste --- techlibs/xilinx/abc_map.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 31fd79861..1f369fc19 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -381,7 +381,7 @@ __CELL__ #( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) ); - `DSP48E1_INST(\$__ABC_DSP48E1_MULTD_PORT ) + `DSP48E1_INST(\$__ABC_DSP48E1_MULT_DPORT ) end else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin wire [29:0] iA; @@ -422,7 +422,7 @@ __CELL__ #( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) ); - `DSP48E1_INST(\$__ABC_DSP48E1_MULTD_PORT ) + `DSP48E1_INST(\$__ABC_DSP48E1 ) end else $error("Invalid DSP48E1 configuration"); From 44bf4ac35cf9f4fa81b8c9ae7f6e2f724e11934d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Sep 2019 12:35:24 -0700 Subject: [PATCH 259/356] Add doc on pattern detector for overflow --- passes/pmgen/xilinx_dsp.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 8500a6072..5af48e4d2 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -519,6 +520,10 @@ struct XilinxDspPass : public Pass { log("the add/subtract operator will cause those operations to be implemented using\n"); log("the 'SIMD' feature of DSPs.\n"); log("\n"); + log("Experimental feature: the presence of a `$ge' cell attached to the registered\n"); + log("P output implementing the operation \"(P >= )\" will be transformed\n"); + log("into using the DSP48E1's pattern detector feature for overflow detection.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { From c663a3680b13422c568e3dc438e7b971b81a71c3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 18 Sep 2019 12:44:34 -0700 Subject: [PATCH 260/356] Remove stat --- tests/xilinx/mul_unsigned.ys | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/xilinx/mul_unsigned.ys b/tests/xilinx/mul_unsigned.ys index 30c034afe..77990bd68 100644 --- a/tests/xilinx/mul_unsigned.ys +++ b/tests/xilinx/mul_unsigned.ys @@ -4,7 +4,6 @@ hierarchy -top mul_unsigned equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mul_unsigned # Constrain all select calls below inside the top module -stat select -assert-count 1 t:BUFG select -assert-count 1 t:DSP48E1 select -assert-count 30 t:FDRE From 29d446d7584b772a2dbac92a3088f93223ff7f86 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 10:39:00 -0700 Subject: [PATCH 261/356] Cleanup --- passes/pmgen/xilinx_dsp.pmg | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 08cb1f51b..31ab75f09 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -398,10 +398,8 @@ endmatch code argQ argD { - if (clock != SigBit()) { - if (port(ff, \CLK) != clock) - reject; - } + if (clock != SigBit() && port(ff, \CLK) != clock) + reject; SigSpec Q = port(ff, \Q); if (ffoffset + GetSize(argQ) > GetSize(Q)) @@ -580,10 +578,8 @@ endmatch code argQ if (ff) { - if (clock != SigBit()) { - if (port(ff, \CLK) != clock) - reject; - } + if (clock != SigBit() && port(ff, \CLK) != clock) + reject; SigSpec D = port(ff, \D); if (ffoffset + GetSize(argD) > GetSize(D)) From 65fa8adf6c834cc3c73300a19d4fe96c31b8d361 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 11:02:14 -0700 Subject: [PATCH 262/356] Format macc.v --- tests/ice40/macc.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ice40/macc.v b/tests/ice40/macc.v index 6c3676c83..757c36a66 100644 --- a/tests/ice40/macc.v +++ b/tests/ice40/macc.v @@ -13,13 +13,13 @@ reg [(A_WIDTH + B_WIDTH - 1):0] reg_tmp_c; assign c = reg_tmp_c; always @(posedge clk) begin -if(set) -begin -reg_tmp_c <= 0; -end -else -begin -reg_tmp_c <= a * b + c; -end + if(set) + begin + reg_tmp_c <= 0; + end + else + begin + reg_tmp_c <= a * b + c; + end end endmodule From 0020a18929c30744eae4960ab97f6ebefc32a154 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 12:00:39 -0700 Subject: [PATCH 263/356] Add more entries --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 8d7dd3e19..8ee73771f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -41,6 +41,7 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "_TECHMAP_WIREINIT_*_" attribute and "_TECHMAP_REMOVEINIT_*_" wire for "techmap" pass - Added "-match-init" option to "dff2dffs" pass - Added +/mul2dsp.v for decomposing wide multipliers to custom-sized ones + - Added "ice40_dsp" for Lattice iCE40 DSP packing - Added "xilinx_dsp" for Xilinx DSP packing - "synth_xilinx" to now infer DSP blocks (-nodsp to disable) - "synth_ecp5" to now infer DSP blocks (-nodsp to disable, experimental) From c8310a6e768991f7499f250542eeda3503d3977c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 12:00:48 -0700 Subject: [PATCH 264/356] Refactor ice40_dsp.pmg --- passes/pmgen/ice40_dsp.cc | 51 ++-- passes/pmgen/ice40_dsp.pmg | 575 ++++++++++++++++++++++++++----------- 2 files changed, 429 insertions(+), 197 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 68fc29f31..4132857d6 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -31,12 +31,12 @@ void create_ice40_dsp(ice40_dsp_pm &pm) #if 1 log("\n"); - log("ffA: %s\n", log_id(st.ffA, "--")); - log("ffB: %s\n", log_id(st.ffB, "--")); + log("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAcemux, "--"), log_id(st.ffArstmux, "--")); + log("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBcemux, "--"), log_id(st.ffBrstmux, "--")); log("mul: %s\n", log_id(st.mul, "--")); - log("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); - log("addAB: %s\n", log_id(st.addAB, "--")); - log("muxAB: %s\n", log_id(st.muxAB, "--")); + log("ffFJKG: %s n/a %s\n", log_id(st.ffFJKG, "--"), log_id(st.ffFJKGrstmux, "--")); + log("add: %s\n", log_id(st.add, "--")); + log("mux: %s\n", log_id(st.mux, "--")); log("ffO: %s\n", log_id(st.ffO, "--")); #endif @@ -146,10 +146,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec O = st.sigO; int O_width = GetSize(O); if (O_width == 33) { - log_assert(st.addAB); + log_assert(st.add); // If we have a signed multiply-add, then perform sign extension // TODO: Need to check CD[31:16] is sign extension of CD[15:0]? - if (st.addAB->getParam("\\A_SIGNED").as_bool() && st.addAB->getParam("\\B_SIGNED").as_bool()) + if (st.add->getParam("\\A_SIGNED").as_bool() && st.add->getParam("\\B_SIGNED").as_bool()) pm.module->connect(O[32], O[31]); else cell->setPort("\\CO", O[32]); @@ -164,18 +164,14 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\O", O); bool accum = false; - if (st.addAB) { - if (st.addA) - accum = (st.ffO && st.addAB->getPort("\\B") == st.sigO); - else if (st.addB) - accum = (st.ffO && st.addAB->getPort("\\A") == st.sigO); - else log_abort(); + if (st.add) { + accum = (st.ffO && st.add->getPort(st.addAB == "\\A" ? "\\B" : "\\A") == st.sigO); if (accum) - log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + log(" accumulator %s (%s)\n", log_id(st.add), log_id(st.add->type)); else - log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); - cell->setPort("\\ADDSUBTOP", st.addAB->type == "$add" ? State::S0 : State::S1); - cell->setPort("\\ADDSUBBOT", st.addAB->type == "$add" ? State::S0 : State::S1); + log(" adder %s (%s)\n", log_id(st.add), log_id(st.add->type)); + cell->setPort("\\ADDSUBTOP", st.add->type == "$add" ? State::S0 : State::S1); + cell->setPort("\\ADDSUBBOT", st.add->type == "$add" ? State::S0 : State::S1); } else { cell->setPort("\\ADDSUBTOP", State::S0); cell->setPort("\\ADDSUBBOT", State::S0); @@ -188,10 +184,12 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\OHOLDBOT", State::S0); SigSpec acc_reset = State::S0; - if (st.muxA) - acc_reset = st.muxA->getPort("\\S"); - if (st.muxB) - acc_reset = pm.module->Not(NEW_ID, st.muxB->getPort("\\S")); + if (st.mux) { + if (st.muxAB == "\\A") + acc_reset = st.mux->getPort("\\S"); + else + acc_reset = pm.module->Not(NEW_ID, st.mux->getPort("\\S")); + } cell->setPort("\\OLOADTOP", acc_reset); cell->setPort("\\OLOADBOT", acc_reset); @@ -219,8 +217,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\B_SIGNED", st.mul->getParam("\\B_SIGNED").as_bool()); if (st.ffO) { - if (st.ffO_lo) - cell->setParam("\\TOPOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2)); + if (st.o_lo) + cell->setParam("\\TOPOUTPUT_SELECT", Const(st.add ? 0 : 3, 2)); else cell->setParam("\\TOPOUTPUT_SELECT", Const(1, 2)); @@ -228,8 +226,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\BOTOUTPUT_SELECT", Const(1, 2)); } else { - cell->setParam("\\TOPOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2)); - cell->setParam("\\BOTOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2)); + cell->setParam("\\TOPOUTPUT_SELECT", Const(st.add ? 0 : 3, 2)); + cell->setParam("\\BOTOUTPUT_SELECT", Const(st.add ? 0 : 3, 2)); } if (cell != st.mul) @@ -237,7 +235,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) else pm.blacklist(st.mul); pm.autoremove(st.ffFJKG); - pm.autoremove(st.addAB); + pm.autoremove(st.add); } struct Ice40DspPass : public Pass { @@ -249,6 +247,7 @@ struct Ice40DspPass : public Pass { log(" ice40_dsp [options] [selection]\n"); log("\n"); log("Map multipliers and multiply-accumulate blocks to iCE40 DSP resources.\n"); + log("Currently, only the 16x16 multiply mode is supported and not the 2 x 8x8 mode.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index fbf498109..22267aea7 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,9 +1,25 @@ pattern ice40_dsp state clock -state clock_pol cd_signed +state clock_pol cd_signed o_lo state sigA sigB sigCD sigH sigO -state addAB muxAB +state add mux +state addAB muxAB + +state ffAcepol ffBcepol ffCDcepol ffOcepol +state ffArstpol ffBrstpol ffCDrstpol ffFJKGrstpol ffOrstpol + +state ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux ffCDrstmux +state ffFJKG ffFJKGrstmux ffO ffOcemux ffOrstmux + +// subpattern +state argQ argD +state ffcepol ffrstpol +state ffoffset +udata dffD dffQ +udata dffclock +udata dff dffcemux dffrstmux +udata dffcepol dffrstpol dffclock_pol match mul select mul->type.in($mul, \SB_MAC16) @@ -47,122 +63,108 @@ code sigA sigB sigH log_assert(nusers(O.extract_end(i)) <= 1); endcode -match ffA - if mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool() - select ffA->type.in($dff) - filter GetSize(port(ffA, \Q)) >= GetSize(sigA) - slice offset GetSize(port(ffA, \Q)) - filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) && port(ffA, \Q).extract(offset, GetSize(sigA)) == sigA - optional -endmatch - -code sigA clock clock_pol - if (ffA) { - for (auto b : port(ffA, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - clock = port(ffA, \CLK).as_bit(); - clock_pol = param(ffA, \CLK_POLARITY).as_bool(); - - sigA.replace(port(ffA, \Q), port(ffA, \D)); +code argQ ffA ffAcemux ffArstmux ffAcepol ffArstpol sigA clock clock_pol + if (mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool()) { + argQ = sigA; + subpattern(in_dffe); + if (dff) { + ffA = dff; + clock = dffclock; + clock_pol = dffclock_pol; + if (dffrstmux) { + ffArstmux = dffrstmux; + ffArstpol = dffrstpol; + } + if (dffcemux) { + ffAcemux = dffcemux; + ffAcepol = dffcepol; + } + sigA = dffD; + } } endcode -match ffB - if mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool() - select ffB->type.in($dff) - filter GetSize(port(ffB, \Q)) >= GetSize(sigB) - slice offset GetSize(port(ffB, \Q)) - filter offset+GetSize(sigB) <= GetSize(port(ffB, \Q)) && port(ffB, \Q).extract(offset, GetSize(sigB)) == sigB - optional -endmatch - -code sigB clock clock_pol - if (ffB) { - for (auto b : port(ffB, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffB, \CLK).as_bit(); - bool cp = param(ffB, \CLK_POLARITY).as_bool(); - - if (clock != SigBit() && (c != clock || cp != clock_pol)) - reject; - - clock = c; - clock_pol = cp; - - sigB.replace(port(ffB, \Q), port(ffB, \D)); +code argQ ffB ffBcemux ffBrstmux ffBcepol ffBrstpol sigB clock clock_pol + if (mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool()) { + argQ = sigB; + subpattern(in_dffe); + if (dff) { + ffB = dff; + clock = dffclock; + clock_pol = dffclock_pol; + if (dffrstmux) { + ffBrstmux = dffrstmux; + ffBrstpol = dffrstpol; + } + if (dffcemux) { + ffBcemux = dffcemux; + ffBcepol = dffcepol; + } + sigB = dffD; + } } endcode -match ffFJKG - // Ensure pipeline register is not already used - if mul->type != \SB_MAC16 || (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool()) - select ffFJKG->type.in($dff) - select nusers(port(ffFJKG, \D)) == 2 - index port(ffFJKG, \D) === sigH - optional -endmatch - -code sigH sigO clock clock_pol - if (ffFJKG) { - sigH = port(ffFJKG, \Q); - for (auto b : sigH) - if (b.wire->get_bool_attribute(\keep)) +code argD ffFJKG ffFJKGrstmux ffFJKGrstpol sigH sigO clock clock_pol + if (nusers(sigH) == 2 && + (mul->type != \SB_MAC16 || + (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool()))) { + argD = sigH; + subpattern(out_dffe); + if (dff) { + ffFJKG = dff; + clock = dffclock; + clock_pol = dffclock_pol; + if (dffrstmux) { + ffFJKGrstmux = dffrstmux; + ffFJKGrstpol = dffrstpol; + } + // F/J/K/G do not have a CE-like (hold) input + if (dffcemux) reject; - SigBit c = port(ffFJKG, \CLK).as_bit(); - bool cp = param(ffFJKG, \CLK_POLARITY).as_bool(); + // Reset signal of F/J (IRSTTOP) and K/G (IRSTBOT) + // shared with A and B + if ((ffArstmux != NULL) != (ffFJKGrstmux != NULL)) + reject; + if ((ffBrstmux != NULL) != (ffFJKGrstmux != NULL)) + reject; + if (ffArstmux) { + if (port(ffArstmux, \S) != port(ffFJKGrstmux, \S)) + reject; + if (ffArstpol != ffFJKGrstpol) + reject; + } + if (ffBrstmux) { + if (port(ffBrstmux, \S) != port(ffFJKGrstmux, \S)) + reject; + if (ffBrstpol != ffFJKGrstpol) + reject; + } - if (clock != SigBit() && (c != clock || cp != clock_pol)) - reject; - - clock = c; - clock_pol = cp; + sigH = dffQ; + } } sigO = sigH; endcode -match addA - select addA->type.in($add) - select nusers(port(addA, \A)) == 2 - filter param(addA, \A_WIDTH).as_int() <= GetSize(sigH) - //index port(addA, \A) === sigH.extract(0, param(addA, \A_WIDTH).as_int()) - filter port(addA, \A) == sigH.extract(0, param(addA, \A_WIDTH).as_int()) +match add + if mul->type != \SB_MAC16 || (param(mul, \TOPOUTPUT_SELECT).as_int() == 3 && param(mul, \BOTOUTPUT_SELECT).as_int() == 3) + select add->type.in($add) + choice AB {\A, \B} + select nusers(port(add, AB)) == 2 + index port(add, AB)[0] === sigH[0] + filter GetSize(port(add, AB)) <= GetSize(sigH) + filter port(add, AB) == sigH.extract(0, GetSize(port(add, AB))) + set addAB AB optional endmatch -match addB - if !addA - select addB->type.in($add, $sub) - select nusers(port(addB, \B)) == 2 - filter param(addB, \B_WIDTH).as_int() <= GetSize(sigH) - //index port(addB, \B) === sigH.extract(0, param(addB, \B_WIDTH).as_int()) - filter port(addB, \B) == sigH.extract(0, param(addB, \B_WIDTH).as_int()) - optional -endmatch - -code addAB sigCD sigO cd_signed - if (addA) { - addAB = addA; - sigCD = port(addAB, \B); - cd_signed = param(addAB, \B_SIGNED).as_bool(); - } - else if (addB) { - addAB = addB; - sigCD = port(addAB, \A); - cd_signed = param(addAB, \A_SIGNED).as_bool(); - } - if (addAB) { - if (mul->type == \SB_MAC16) { - // Ensure that adder is not used - if (param(mul, \TOPOUTPUT_SELECT).as_int() != 3 || - param(mul, \BOTOUTPUT_SELECT).as_int() != 3) - reject; - } +code sigCD sigO cd_signed + if (add) { + sigCD = port(add, addAB == \A ? \B : \A); + cd_signed = param(add, addAB == \A ? \B_SIGNED : \A_SIGNED).as_bool(); int natural_mul_width = GetSize(sigA) + GetSize(sigB); int actual_mul_width = GetSize(sigH); @@ -171,97 +173,75 @@ code addAB sigCD sigO cd_signed if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) reject; // If accumulator, check adder width and signedness - if (sigCD == sigH && (actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) + if (sigCD == sigH && (actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(add, \A_SIGNED).as_bool())) reject; - sigO = port(addAB, \Y); + sigO = port(add, \Y); } endcode -match muxA - select muxA->type.in($mux) - index nusers(port(muxA, \A)) === 2 - index port(muxA, \A) === sigO +match mux + select mux->type == $mux + choice AB {\A, \B} + index nusers(port(mux, AB)) === 2 + index port(mux, AB) === sigO + set muxAB AB optional endmatch -match muxB - if !muxA - select muxB->type.in($mux) - index nusers(port(muxB, \B)) === 2 - index port(muxB, \B) === sigO - optional -endmatch - -code muxAB sigO - if (muxA) - muxAB = muxA; - else if (muxB) - muxAB = muxB; - if (muxAB) - sigO = port(muxAB, \Y); +code sigO + if (mux) + sigO = port(mux, \Y); endcode -match ffO - // Ensure that register is not already used - if mul->type != \SB_MAC16 || (mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) - // Ensure that OLOADTOP/OLOADBOT is unused or zero - if mul->type != \SB_MAC16 || (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero()) - if nusers(sigO) == 2 - select ffO->type.in($dff) - filter GetSize(port(ffO, \D)) >= GetSize(sigO) - slice offset GetSize(port(ffO, \D)) - filter offset+GetSize(sigO) <= GetSize(port(ffO, \D)) && port(ffO, \D).extract(offset, GetSize(sigO)) == sigO - optional -endmatch +code argD ffO ffOcemux ffOrstmux ffOcepol ffOrstpol sigO sigCD clock clock_pol cd_signed o_lo + if (mul->type != \SB_MAC16 || + // Ensure that register is not already used + ((mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) && + // Ensure that OLOADTOP/OLOADBOT is unused or zero + (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero()))) { -match ffO_lo - if !ffO && GetSize(sigO) > 16 - // Ensure that register is not already used - if mul->type != \SB_MAC16 || (mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) - // Ensure that OLOADTOP/OLOADBOT is unused or zero - if mul->type != \SB_MAC16 || (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero()) - if nusers(sigO.extract(0, 16)) == 2 - select ffO_lo->type.in($dff) - filter GetSize(port(ffO_lo, \D)) >= 16 - slice offset GetSize(port(ffO_lo, \D)) - filter offset+GetSize(sigO) <= GetSize(port(ffO_lo, \D)) && port(ffO_lo, \D).extract(offset, 16) == sigO.extract(0, 16) - optional -endmatch + dff = nullptr; -code ffO clock clock_pol sigO sigCD cd_signed - if (ffO_lo) { - log_assert(!ffO); - ffO = ffO_lo; - } - if (ffO) { - for (auto b : port(ffO, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; + // First try entire sigO + if (nusers(sigO) == 2) { + argD = sigO; + subpattern(out_dffe); + } - SigBit c = port(ffO, \CLK).as_bit(); - bool cp = param(ffO, \CLK_POLARITY).as_bool(); + // Otherwise try just its least significant 16 bits + if (!dff && GetSize(sigO) > 16) { + argD = sigO.extract(0, 16); + if (nusers(argD) == 2) { + subpattern(out_dffe); + o_lo = dff; + } + } - if (clock != SigBit() && (c != clock || cp != clock_pol)) - reject; + if (dff) { + ffO = dff; + clock = dffclock; + clock_pol = dffclock_pol; + if (dffrstmux) { + ffOrstmux = dffrstmux; + ffOrstpol = dffrstpol; + } + if (dffcemux) { + ffOcemux = dffcemux; + ffOcepol = dffcepol; + } - clock = c; - clock_pol = cp; - - sigO.replace(port(ffO, \D), port(ffO, \Q)); + sigO.replace(sigO.extract(0, GetSize(dffQ)), dffQ); + } // Loading value into output register is not // supported unless using accumulator - if (muxAB) { + if (mux) { if (sigCD != sigO) reject; - if (muxA) - sigCD = port(muxAB, \B); - else if (muxB) - sigCD = port(muxAB, \A); - else log_abort(); + sigCD = port(mux, muxAB == \B ? \A : \B); - cd_signed = addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool(); + cd_signed = add && param(add, \A_SIGNED).as_bool() && param(add, \B_SIGNED).as_bool(); } } sigCD.extend_u0(32, cd_signed); @@ -270,3 +250,256 @@ endcode code accept; endcode + +// ####################### + +subpattern in_dffe +arg argD argQ clock clock_pol + +code + dff = nullptr; + for (auto c : argQ.chunks()) { + if (!c.wire) + reject; + if (c.wire->get_bool_attribute(\keep)) + reject; + } +endcode + +match ff + select ff->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ff, \CLK_POLARITY).as_bool() + + slice offset GetSize(port(ff, \D)) + index port(ff, \Q)[offset] === argQ[0] + + // Check that the rest of argQ is present + filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ) + filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ + + set ffoffset offset +endmatch + +code argQ argD +{ + if (clock != SigBit()) { + if (port(ff, \CLK) != clock) + reject; + if (param(ff, \CLK_POLARITY).as_bool() != clock_pol) + reject; + } + + SigSpec Q = port(ff, \Q); + dff = ff; + dffclock = port(ff, \CLK); + dffclock_pol = param(ff, \CLK_POLARITY).as_bool(); + dffD = argQ; + argD = port(ff, \D); + argQ = Q; + dffD.replace(argQ, argD); + // Only search for ffrstmux if dffD only + // has two (ff, ffrstmux) users + if (nusers(dffD) > 2) + argD = SigSpec(); +} +endcode + +match ffrstmux + if !argD.empty() + select ffrstmux->type.in($mux) + index port(ffrstmux, \Y) === argD + + choice BA {\B, \A} + // DSP48E1 only supports reset to zero + select port(ffrstmux, BA).is_fully_zero() + + define pol (BA == \B) + set ffrstpol pol + semioptional +endmatch + +code argD + if (ffrstmux) { + dffrstmux = ffrstmux; + dffrstpol = ffrstpol; + argD = port(ffrstmux, ffrstpol ? \A : \B); + dffD.replace(port(ffrstmux, \Y), argD); + + // Only search for ffcemux if argQ has at + // least 3 users (ff, , ffrstmux) and + // dffD only has two (ff, ffrstmux) + if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) + argD = SigSpec(); + } + else + dffrstmux = nullptr; +endcode + +match ffcemux + if !argD.empty() + select ffcemux->type.in($mux) + index port(ffcemux, \Y) === argD + choice AB {\A, \B} + index port(ffcemux, AB) === argQ + define pol (AB == \A) + set ffcepol pol + semioptional +endmatch + +code argD + if (ffcemux) { + dffcemux = ffcemux; + dffcepol = ffcepol; + argD = port(ffcemux, ffcepol ? \B : \A); + dffD.replace(port(ffcemux, \Y), argD); + } + else + dffcemux = nullptr; +endcode + +// ####################### + +subpattern out_dffe +arg argD argQ clock clock_pol + +code + dff = nullptr; +endcode + +match ffcemux + select ffcemux->type.in($mux) + // ffcemux output must have two users: ffcemux and ff.D + select nusers(port(ffcemux, \Y)) == 2 + + choice AB {\A, \B} + // keep-last-value net must have at least three users: ffcemux, ff, downstream sink(s) + select nusers(port(ffcemux, AB)) >= 3 + + slice offset GetSize(port(ffcemux, \Y)) + define BA (AB == \A ? \B : \A) + index port(ffcemux, BA)[offset] === argD[0] + + // Check that the rest of argD is present + filter GetSize(BA) >= offset + GetSize(argD) + filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD + + set ffoffset offset + define pol (BA == \B) + set ffcepol pol + + semioptional +endmatch + +code argD argQ + dffcemux = ffcemux; + if (ffcemux) { + SigSpec BA = port(ffcemux, ffcepol ? \B : \A); + if (ffoffset + GetSize(argD) > GetSize(BA)) + reject; + for (int i = 1; i < GetSize(argD); i++) + if (BA[ffoffset+i] != argD[i]) + reject; + + SigSpec Y = port(ffcemux, \Y); + argQ = argD; + argD.replace(BA, Y); + argQ.replace(BA, port(ffcemux, ffcepol ? \A : \B)); + + dffcemux = ffcemux; + dffcepol = ffcepol; + } +endcode + +match ffrstmux + select ffrstmux->type.in($mux) + // ffrstmux output must have two users: ffrstmux and ff.D + select nusers(port(ffrstmux, \Y)) == 2 + + choice BA {\B, \A} + // DSP48E1 only supports reset to zero + select port(ffrstmux, BA).is_fully_zero() + + slice offset GetSize(port(ffrstmux, \Y)) + define AB (BA == \B ? \A : \B) + index port(ffrstmux, AB)[offset] === argD[0] + + // Check that offset is consistent + filter !ffcemux || ffoffset == offset + // Check that the rest of argD is present + filter GetSize(AB) >= offset + GetSize(argD) + filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD + + set ffoffset offset + define pol (AB == \A) + set ffrstpol pol + + semioptional +endmatch + +code argD argQ + dffrstmux = ffrstmux; + if (ffrstmux) { + SigSpec AB = port(ffrstmux, ffrstpol ? \A : \B); + SigSpec Y = port(ffrstmux, \Y); + argD.replace(AB, Y); + + dffrstmux = ffrstmux; + dffrstpol = ffrstpol; + } +endcode + +match ff + select ff->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ff, \CLK_POLARITY).as_bool() + + slice offset GetSize(port(ff, \D)) + index port(ff, \D)[offset] === argD[0] + + // Check that offset is consistent + filter (!ffcemux && !ffrstmux) || ffoffset == offset + // Check that the rest of argD is present + filter GetSize(port(ff, \D)) >= offset + GetSize(argD) + filter port(ff, \D).extract(offset, GetSize(argD)) == argD + // Check that FF.Q is connected to CE-mux + filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ + + set ffoffset offset + + semioptional +endmatch + +code argQ + if (ff) { + if (clock != SigBit()) { + if (port(ff, \CLK) != clock) + reject; + if (param(ff, \CLK_POLARITY).as_bool() != clock_pol) + reject; + } + + SigSpec D = port(ff, \D); + SigSpec Q = port(ff, \Q); + if (!ffcemux) { + argQ = argD; + argQ.replace(D, Q); + } + + for (auto c : argQ.chunks()) { + if (c.wire->get_bool_attribute(\keep)) + reject; + Const init = c.wire->attributes.at(\init, State::Sx); + if (!init.is_fully_undef() && !init.is_fully_zero()) + reject; + } + + dff = ff; + dffQ = argQ; + dffclock = port(ff, \CLK); + dffclock_pol = param(ff, \CLK_POLARITY).as_bool(); + } + // No enable/reset mux possible without flop + else if (dffcemux || dffrstmux) + reject; +endcode From 2766465a2bf73fcd490a160a124b6167851f2d10 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 12:14:33 -0700 Subject: [PATCH 265/356] Add support for SB_MAC16 CD and H registers --- passes/pmgen/ice40_dsp.cc | 15 +++++--- passes/pmgen/ice40_dsp.pmg | 71 +++++++++++++++++++++++++++++++++----- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 4132857d6..7592593a6 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -33,8 +33,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log("\n"); log("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAcemux, "--"), log_id(st.ffArstmux, "--")); log("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBcemux, "--"), log_id(st.ffBrstmux, "--")); + log("ffCD: %s %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDcemux, "--"), log_id(st.ffCDrstmux, "--")); log("mul: %s\n", log_id(st.mul, "--")); log("ffFJKG: %s n/a %s\n", log_id(st.ffFJKG, "--"), log_id(st.ffFJKGrstmux, "--")); + log("ffH: %s n/a %s\n", log_id(st.ffH, "--"), log_id(st.ffHrstmux, "--")); log("add: %s\n", log_id(st.add, "--")); log("mux: %s\n", log_id(st.mux, "--")); log("ffO: %s\n", log_id(st.ffO, "--")); @@ -93,6 +95,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\A_REG", st.ffA ? State::S1 : State::S0); cell->setParam("\\B_REG", st.ffB ? State::S1 : State::S0); + cell->setParam("\\C_REG", st.ffCD ? State::S1 : State::S0); + cell->setParam("\\D_REG", st.ffCD ? State::S1 : State::S0); cell->setPort("\\AHOLD", State::S0); cell->setPort("\\BHOLD", State::S0); @@ -116,9 +120,15 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (st.ffB) log(" ffB:%s", log_id(st.ffB)); + if (st.ffCD) + log(" ffCD:%s", log_id(st.ffCD)); + if (st.ffFJKG) log(" ffFJKG:%s", log_id(st.ffFJKG)); + if (st.ffH) + log(" ffH:%s", log_id(st.ffH)); + if (st.ffO) log(" ffO:%s", log_id(st.ffO)); @@ -196,13 +206,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Remaining Parameters - cell->setParam("\\C_REG", State::S0); - cell->setParam("\\D_REG", State::S0); - cell->setParam("\\TOP_8x8_MULT_REG", st.ffFJKG ? State::S1 : State::S0); cell->setParam("\\BOT_8x8_MULT_REG", st.ffFJKG ? State::S1 : State::S0); cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffFJKG ? State::S1 : State::S0); - cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0); + cell->setParam("\\PIPELINE_16x16_MULT_REG2", st.ffH ? State::S1 : State::S0); cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2)); cell->setParam("\\TOPADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 22267aea7..532995da7 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -7,10 +7,10 @@ state add mux state addAB muxAB state ffAcepol ffBcepol ffCDcepol ffOcepol -state ffArstpol ffBrstpol ffCDrstpol ffFJKGrstpol ffOrstpol +state ffArstpol ffBrstpol ffCDrstpol ffOrstpol state ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux ffCDrstmux -state ffFJKG ffFJKGrstmux ffO ffOcemux ffOrstmux +state ffFJKG ffFJKGrstmux ffH ffHrstmux ffO ffOcemux ffOrstmux // subpattern state argQ argD @@ -105,20 +105,18 @@ code argQ ffB ffBcemux ffBrstmux ffBcepol ffBrstpol sigB clock clock_pol } endcode -code argD ffFJKG ffFJKGrstmux ffFJKGrstpol sigH sigO clock clock_pol +code argD ffFJKG ffFJKGrstmux sigH sigO clock clock_pol if (nusers(sigH) == 2 && (mul->type != \SB_MAC16 || - (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool()))) { + (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool()))) { argD = sigH; subpattern(out_dffe); if (dff) { ffFJKG = dff; clock = dffclock; clock_pol = dffclock_pol; - if (dffrstmux) { + if (dffrstmux) ffFJKGrstmux = dffrstmux; - ffFJKGrstpol = dffrstpol; - } // F/J/K/G do not have a CE-like (hold) input if (dffcemux) reject; @@ -132,13 +130,43 @@ code argD ffFJKG ffFJKGrstmux ffFJKGrstpol sigH sigO clock clock_pol if (ffArstmux) { if (port(ffArstmux, \S) != port(ffFJKGrstmux, \S)) reject; - if (ffArstpol != ffFJKGrstpol) + if (ffArstpol != dffrstpol) reject; } if (ffBrstmux) { if (port(ffBrstmux, \S) != port(ffFJKGrstmux, \S)) reject; - if (ffBrstpol != ffFJKGrstpol) + if (ffBrstpol != dffrstpol) + reject; + } + + sigH = dffQ; + } + } +endcode + +code argD ffH ffHrstmux sigH sigO clock clock_pol + if (nusers(sigH) == 2 && + (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) { + argD = sigH; + subpattern(out_dffe); + if (dff) { + ffH = dff; + clock = dffclock; + clock_pol = dffclock_pol; + if (dffrstmux) + ffHrstmux = dffrstmux; + // H does not have a CE-like (hold) input + if (dffcemux) + reject; + + // Reset signal of H (IRSTBOT) shared with B + if ((ffBrstmux != NULL) != (ffHrstmux != NULL)) + reject; + if (ffBrstmux) { + if (port(ffBrstmux, \S) != port(ffHrstmux, \S)) + reject; + if (ffBrstpol != dffrstpol) reject; } @@ -244,6 +272,31 @@ code argD ffO ffOcemux ffOrstmux ffOcepol ffOrstpol sigO sigCD clock clock_pol c cd_signed = add && param(add, \A_SIGNED).as_bool() && param(add, \B_SIGNED).as_bool(); } } +endcode + +code argQ ffCD ffCDcemux ffCDrstmux ffCDcepol ffCDrstpol sigCD clock clock_pol + if (!sigCD.empty() && + (mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) { + argQ = sigCD; + subpattern(in_dffe); + if (dff) { + ffCD = dff; + clock = dffclock; + clock_pol = dffclock_pol; + if (dffrstmux) { + ffCDrstmux = dffrstmux; + ffCDrstpol = dffrstpol; + } + if (dffcemux) { + ffCDcemux = dffcemux; + ffCDcepol = dffcepol; + } + sigCD = dffD; + } + } +endcode + +code sigCD sigCD.extend_u0(32, cd_signed); endcode From 429c9852cee3bd7f133944044c74c26b8f6a4209 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 14:02:55 -0700 Subject: [PATCH 266/356] Add HOLD/RST support for SB_MAC16 --- passes/pmgen/ice40_dsp.cc | 61 ++++++++++++----- passes/pmgen/ice40_dsp.pmg | 132 +++++++++++++++++++++---------------- 2 files changed, 120 insertions(+), 73 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 7592593a6..f3cc83699 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -33,13 +33,13 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log("\n"); log("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAcemux, "--"), log_id(st.ffArstmux, "--")); log("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBcemux, "--"), log_id(st.ffBrstmux, "--")); - log("ffCD: %s %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDcemux, "--"), log_id(st.ffCDrstmux, "--")); + log("ffCD: %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDcemux, "--")); log("mul: %s\n", log_id(st.mul, "--")); - log("ffFJKG: %s n/a %s\n", log_id(st.ffFJKG, "--"), log_id(st.ffFJKGrstmux, "--")); - log("ffH: %s n/a %s\n", log_id(st.ffH, "--"), log_id(st.ffHrstmux, "--")); + log("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); + log("ffH: %s\n", log_id(st.ffH, "--")); log("add: %s\n", log_id(st.add, "--")); log("mux: %s\n", log_id(st.mux, "--")); - log("ffO: %s\n", log_id(st.ffO, "--")); + log("ffO: %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOcemux, "--"), log_id(st.ffOrstmux, "--")); #endif log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); @@ -98,13 +98,35 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\C_REG", st.ffCD ? State::S1 : State::S0); cell->setParam("\\D_REG", st.ffCD ? State::S1 : State::S0); - cell->setPort("\\AHOLD", State::S0); - cell->setPort("\\BHOLD", State::S0); - cell->setPort("\\CHOLD", State::S0); - cell->setPort("\\DHOLD", State::S0); + SigSpec AHOLD, BHOLD, CDHOLD; + if (st.ffAcemux) + AHOLD = st.ffAcepol ? pm.module->Not(NEW_ID, st.ffAcemux->getPort("\\S")) : st.ffAcemux->getPort("\\S"); + else + AHOLD = State::S0; + if (st.ffBcemux) + BHOLD = st.ffBcepol ? pm.module->Not(NEW_ID, st.ffBcemux->getPort("\\S")) : st.ffBcemux->getPort("\\S"); + else + BHOLD = State::S0; + if (st.ffCDcemux) + CDHOLD = st.ffCDcepol ? pm.module->Not(NEW_ID, st.ffCDcemux->getPort("\\S")) : st.ffCDcemux->getPort("\\S"); + else + CDHOLD = State::S0; + cell->setPort("\\AHOLD", AHOLD); + cell->setPort("\\BHOLD", BHOLD); + cell->setPort("\\CHOLD", CDHOLD); + cell->setPort("\\DHOLD", CDHOLD); - cell->setPort("\\IRSTTOP", State::S0); - cell->setPort("\\IRSTBOT", State::S0); + SigSpec IRSTTOP, IRSTBOT; + if (st.ffArstmux) + IRSTTOP = st.ffArstpol ? st.ffArstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffArstmux->getPort("\\S")); + else + IRSTTOP = State::S0; + if (st.ffBrstmux) + IRSTBOT = st.ffBrstpol ? st.ffBrstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffBrstmux->getPort("\\S")); + else + IRSTBOT = State::S0; + cell->setPort("\\IRSTTOP", IRSTTOP); + cell->setPort("\\IRSTBOT", IRSTBOT); if (st.clock != SigBit()) { @@ -187,11 +209,21 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\ADDSUBBOT", State::S0); } - cell->setPort("\\ORSTTOP", State::S0); - cell->setPort("\\ORSTBOT", State::S0); + SigSpec OHOLD; + if (st.ffOcemux) + OHOLD = st.ffOcemux ? pm.module->Not(NEW_ID, st.ffOcemux->getPort("\\S")) : st.ffOcemux->getPort("\\S"); + else + OHOLD = State::S0; + cell->setPort("\\OHOLDTOP", OHOLD); + cell->setPort("\\OHOLDBOT", OHOLD); - cell->setPort("\\OHOLDTOP", State::S0); - cell->setPort("\\OHOLDBOT", State::S0); + SigSpec ORST; + if (st.ffOrstmux) + ORST = st.ffOrstmux ? st.ffOrstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffOrstmux->getPort("\\S")); + else + ORST = State::S0; + cell->setPort("\\ORSTTOP", ORST); + cell->setPort("\\ORSTBOT", ORST); SigSpec acc_reset = State::S0; if (st.mux) { @@ -200,7 +232,6 @@ void create_ice40_dsp(ice40_dsp_pm &pm) else acc_reset = pm.module->Not(NEW_ID, st.mux->getPort("\\S")); } - cell->setPort("\\OLOADTOP", acc_reset); cell->setPort("\\OLOADBOT", acc_reset); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 532995da7..01e344767 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -9,8 +9,8 @@ state addAB muxAB state ffAcepol ffBcepol ffCDcepol ffOcepol state ffArstpol ffBrstpol ffCDrstpol ffOrstpol -state ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux ffCDrstmux -state ffFJKG ffFJKGrstmux ffH ffHrstmux ffO ffOcemux ffOrstmux +state ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux +state ffFJKG ffH ffO ffOcemux ffOrstmux // subpattern state argQ argD @@ -105,75 +105,79 @@ code argQ ffB ffBcemux ffBrstmux ffBcepol ffBrstpol sigB clock clock_pol } endcode -code argD ffFJKG ffFJKGrstmux sigH sigO clock clock_pol +code argD ffFJKG sigH sigO clock clock_pol if (nusers(sigH) == 2 && (mul->type != \SB_MAC16 || (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool()))) { argD = sigH; subpattern(out_dffe); if (dff) { - ffFJKG = dff; - clock = dffclock; - clock_pol = dffclock_pol; - if (dffrstmux) - ffFJKGrstmux = dffrstmux; // F/J/K/G do not have a CE-like (hold) input if (dffcemux) - reject; + goto reject_ffFJKG; // Reset signal of F/J (IRSTTOP) and K/G (IRSTBOT) // shared with A and B - if ((ffArstmux != NULL) != (ffFJKGrstmux != NULL)) - reject; - if ((ffBrstmux != NULL) != (ffFJKGrstmux != NULL)) - reject; + if ((ffArstmux != NULL) != (dffrstmux != NULL)) + goto reject_ffFJKG; + if ((ffBrstmux != NULL) != (dffrstmux != NULL)) + goto reject_ffFJKG; if (ffArstmux) { - if (port(ffArstmux, \S) != port(ffFJKGrstmux, \S)) - reject; + if (port(ffArstmux, \S) != port(dffrstmux, \S)) + goto reject_ffFJKG; if (ffArstpol != dffrstpol) - reject; + goto reject_ffFJKG; } if (ffBrstmux) { - if (port(ffBrstmux, \S) != port(ffFJKGrstmux, \S)) - reject; + if (port(ffBrstmux, \S) != port(dffrstmux, \S)) + goto reject_ffFJKG; if (ffBrstpol != dffrstpol) - reject; + goto reject_ffFJKG; } + ffFJKG = dff; + clock = dffclock; + clock_pol = dffclock_pol; sigH = dffQ; } } + + if (0) { +reject_ffFJKG: ; + } endcode -code argD ffH ffHrstmux sigH sigO clock clock_pol - if (nusers(sigH) == 2 && +code argD ffH sigH sigO clock clock_pol + if (ffFJKG && nusers(sigH) == 2 && (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) { argD = sigH; subpattern(out_dffe); if (dff) { + // H does not have a CE-like (hold) input + if (dffcemux) + goto reject_ffH; + + // Reset signal of H (IRSTBOT) shared with B + if ((ffBrstmux != NULL) != (dffrstmux != NULL)) + goto reject_ffH; + if (ffBrstmux) { + if (port(ffBrstmux, \S) != port(dffrstmux, \S)) + goto reject_ffH; + if (ffBrstpol != dffrstpol) + goto reject_ffH; + } + ffH = dff; clock = dffclock; clock_pol = dffclock_pol; - if (dffrstmux) - ffHrstmux = dffrstmux; - // H does not have a CE-like (hold) input - if (dffcemux) - reject; - - // Reset signal of H (IRSTBOT) shared with B - if ((ffBrstmux != NULL) != (ffHrstmux != NULL)) - reject; - if (ffBrstmux) { - if (port(ffBrstmux, \S) != port(ffHrstmux, \S)) - reject; - if (ffBrstpol != dffrstpol) - reject; - } - sigH = dffQ; } } + if (0) { +reject_ffH: ; + } + sigO = sigH; endcode @@ -274,26 +278,46 @@ code argD ffO ffOcemux ffOrstmux ffOcepol ffOrstpol sigO sigCD clock clock_pol c } endcode -code argQ ffCD ffCDcemux ffCDrstmux ffCDcepol ffCDrstpol sigCD clock clock_pol +code argQ ffCD ffCDcemux ffCDcepol ffCDrstpol sigCD clock clock_pol if (!sigCD.empty() && (mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) { argQ = sigCD; subpattern(in_dffe); if (dff) { - ffCD = dff; - clock = dffclock; - clock_pol = dffclock_pol; - if (dffrstmux) { - ffCDrstmux = dffrstmux; - ffCDrstpol = dffrstpol; - } if (dffcemux) { ffCDcemux = dffcemux; ffCDcepol = dffcepol; } + + // Reset signal of C (IRSTTOP) and D (IRSTBOT) + // shared with A and B + if ((ffArstmux != NULL) != (dffrstmux != NULL)) + goto reject_ffCD; + if ((ffBrstmux != NULL) != (dffrstmux != NULL)) + goto reject_ffCD; + if (ffArstmux) { + if (port(ffArstmux, \S) != port(dffrstmux, \S)) + goto reject_ffCD; + if (ffArstpol != dffrstpol) + goto reject_ffCD; + } + if (ffBrstmux) { + if (port(ffBrstmux, \S) != port(dffrstmux, \S)) + goto reject_ffCD; + if (ffBrstpol != dffrstpol) + goto reject_ffCD; + } + + ffCD = dff; + clock = dffclock; + clock_pol = dffclock_pol; sigCD = dffD; } } + + if (0) { +reject_ffCD: ; + } endcode code sigCD @@ -418,6 +442,9 @@ arg argD argQ clock clock_pol code dff = nullptr; + for (auto c : argD.chunks()) + if (c.wire->get_bool_attribute(\keep)) + reject; endcode match ffcemux @@ -434,7 +461,7 @@ match ffcemux index port(ffcemux, BA)[offset] === argD[0] // Check that the rest of argD is present - filter GetSize(BA) >= offset + GetSize(argD) + filter GetSize(port(ffcemux, BA)) >= offset + GetSize(argD) filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD set ffoffset offset @@ -448,12 +475,6 @@ code argD argQ dffcemux = ffcemux; if (ffcemux) { SigSpec BA = port(ffcemux, ffcepol ? \B : \A); - if (ffoffset + GetSize(argD) > GetSize(BA)) - reject; - for (int i = 1; i < GetSize(argD); i++) - if (BA[ffoffset+i] != argD[i]) - reject; - SigSpec Y = port(ffcemux, \Y); argQ = argD; argD.replace(BA, Y); @@ -480,7 +501,7 @@ match ffrstmux // Check that offset is consistent filter !ffcemux || ffoffset == offset // Check that the rest of argD is present - filter GetSize(AB) >= offset + GetSize(argD) + filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD) filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD set ffoffset offset @@ -519,8 +540,6 @@ match ff filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ set ffoffset offset - - semioptional endmatch code argQ @@ -531,7 +550,6 @@ code argQ if (param(ff, \CLK_POLARITY).as_bool() != clock_pol) reject; } - SigSpec D = port(ff, \D); SigSpec Q = port(ff, \Q); if (!ffcemux) { @@ -540,8 +558,6 @@ code argQ } for (auto c : argQ.chunks()) { - if (c.wire->get_bool_attribute(\keep)) - reject; Const init = c.wire->attributes.at(\init, State::Sx); if (!init.is_fully_undef() && !init.is_fully_zero()) reject; From 1a0f7ed09c5c14242aa89d572f617ad96ed42fa1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 14:27:25 -0700 Subject: [PATCH 267/356] Refactor ce{mux,pol} -> hold{mux,pol} --- passes/pmgen/ice40_dsp.cc | 26 ++++---- passes/pmgen/ice40_dsp.pmg | 128 ++++++++++++++++++------------------- 2 files changed, 77 insertions(+), 77 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index f3cc83699..b119b6b7c 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -31,15 +31,15 @@ void create_ice40_dsp(ice40_dsp_pm &pm) #if 1 log("\n"); - log("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAcemux, "--"), log_id(st.ffArstmux, "--")); - log("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBcemux, "--"), log_id(st.ffBrstmux, "--")); - log("ffCD: %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDcemux, "--")); + log("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAholdmux, "--"), log_id(st.ffArstmux, "--")); + log("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBholdmux, "--"), log_id(st.ffBrstmux, "--")); + log("ffCD: %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDholdmux, "--")); log("mul: %s\n", log_id(st.mul, "--")); log("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); log("ffH: %s\n", log_id(st.ffH, "--")); log("add: %s\n", log_id(st.add, "--")); log("mux: %s\n", log_id(st.mux, "--")); - log("ffO: %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOcemux, "--"), log_id(st.ffOrstmux, "--")); + log("ffO: %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOholdmux, "--"), log_id(st.ffOrstmux, "--")); #endif log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); @@ -99,16 +99,16 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\D_REG", st.ffCD ? State::S1 : State::S0); SigSpec AHOLD, BHOLD, CDHOLD; - if (st.ffAcemux) - AHOLD = st.ffAcepol ? pm.module->Not(NEW_ID, st.ffAcemux->getPort("\\S")) : st.ffAcemux->getPort("\\S"); + if (st.ffAholdmux) + AHOLD = st.ffAholdpol ? st.ffAholdmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffAholdmux->getPort("\\S")); else AHOLD = State::S0; - if (st.ffBcemux) - BHOLD = st.ffBcepol ? pm.module->Not(NEW_ID, st.ffBcemux->getPort("\\S")) : st.ffBcemux->getPort("\\S"); + if (st.ffBholdmux) + BHOLD = st.ffBholdpol ? st.ffBholdmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffBholdmux->getPort("\\S")); else BHOLD = State::S0; - if (st.ffCDcemux) - CDHOLD = st.ffCDcepol ? pm.module->Not(NEW_ID, st.ffCDcemux->getPort("\\S")) : st.ffCDcemux->getPort("\\S"); + if (st.ffCDholdmux) + CDHOLD = st.ffCDholdpol ? st.ffCDholdmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffCDholdmux->getPort("\\S")); else CDHOLD = State::S0; cell->setPort("\\AHOLD", AHOLD); @@ -210,8 +210,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) } SigSpec OHOLD; - if (st.ffOcemux) - OHOLD = st.ffOcemux ? pm.module->Not(NEW_ID, st.ffOcemux->getPort("\\S")) : st.ffOcemux->getPort("\\S"); + if (st.ffOholdmux) + OHOLD = st.ffOholdpol ? st.ffOholdmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffOholdmux->getPort("\\S")); else OHOLD = State::S0; cell->setPort("\\OHOLDTOP", OHOLD); @@ -219,7 +219,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec ORST; if (st.ffOrstmux) - ORST = st.ffOrstmux ? st.ffOrstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffOrstmux->getPort("\\S")); + ORST = st.ffOrstpol ? st.ffOrstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffOrstmux->getPort("\\S")); else ORST = State::S0; cell->setPort("\\ORSTTOP", ORST); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 01e344767..aa081241d 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -6,20 +6,20 @@ state sigA sigB sigCD sigH sigO state add mux state addAB muxAB -state ffAcepol ffBcepol ffCDcepol ffOcepol +state ffAholdpol ffBholdpol ffCDholdpol ffOholdpol state ffArstpol ffBrstpol ffCDrstpol ffOrstpol -state ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux -state ffFJKG ffH ffO ffOcemux ffOrstmux +state ffA ffAholdmux ffArstmux ffB ffBholdmux ffBrstmux ffCD ffCDholdmux +state ffFJKG ffH ffO ffOholdmux ffOrstmux // subpattern state argQ argD -state ffcepol ffrstpol +state ffholdpol ffrstpol state ffoffset udata dffD dffQ udata dffclock -udata dff dffcemux dffrstmux -udata dffcepol dffrstpol dffclock_pol +udata dff dffholdmux dffrstmux +udata dffholdpol dffrstpol dffclock_pol match mul select mul->type.in($mul, \SB_MAC16) @@ -63,7 +63,7 @@ code sigA sigB sigH log_assert(nusers(O.extract_end(i)) <= 1); endcode -code argQ ffA ffAcemux ffArstmux ffAcepol ffArstpol sigA clock clock_pol +code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol if (mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool()) { argQ = sigA; subpattern(in_dffe); @@ -75,16 +75,16 @@ code argQ ffA ffAcemux ffArstmux ffAcepol ffArstpol sigA clock clock_pol ffArstmux = dffrstmux; ffArstpol = dffrstpol; } - if (dffcemux) { - ffAcemux = dffcemux; - ffAcepol = dffcepol; + if (dffholdmux) { + ffAholdmux = dffholdmux; + ffAholdpol = dffholdpol; } sigA = dffD; } } endcode -code argQ ffB ffBcemux ffBrstmux ffBcepol ffBrstpol sigB clock clock_pol +code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol if (mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool()) { argQ = sigB; subpattern(in_dffe); @@ -96,9 +96,9 @@ code argQ ffB ffBcemux ffBrstmux ffBcepol ffBrstpol sigB clock clock_pol ffBrstmux = dffrstmux; ffBrstpol = dffrstpol; } - if (dffcemux) { - ffBcemux = dffcemux; - ffBcepol = dffcepol; + if (dffholdmux) { + ffBholdmux = dffholdmux; + ffBholdpol = dffholdpol; } sigB = dffD; } @@ -113,7 +113,7 @@ code argD ffFJKG sigH sigO clock clock_pol subpattern(out_dffe); if (dff) { // F/J/K/G do not have a CE-like (hold) input - if (dffcemux) + if (dffholdmux) goto reject_ffFJKG; // Reset signal of F/J (IRSTTOP) and K/G (IRSTBOT) @@ -154,7 +154,7 @@ code argD ffH sigH sigO clock clock_pol subpattern(out_dffe); if (dff) { // H does not have a CE-like (hold) input - if (dffcemux) + if (dffholdmux) goto reject_ffH; // Reset signal of H (IRSTBOT) shared with B @@ -226,7 +226,7 @@ code sigO sigO = port(mux, \Y); endcode -code argD ffO ffOcemux ffOrstmux ffOcepol ffOrstpol sigO sigCD clock clock_pol cd_signed o_lo +code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_pol cd_signed o_lo if (mul->type != \SB_MAC16 || // Ensure that register is not already used ((mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) && @@ -258,9 +258,9 @@ code argD ffO ffOcemux ffOrstmux ffOcepol ffOrstpol sigO sigCD clock clock_pol c ffOrstmux = dffrstmux; ffOrstpol = dffrstpol; } - if (dffcemux) { - ffOcemux = dffcemux; - ffOcepol = dffcepol; + if (dffholdmux) { + ffOholdmux = dffholdmux; + ffOholdpol = dffholdpol; } sigO.replace(sigO.extract(0, GetSize(dffQ)), dffQ); @@ -278,15 +278,15 @@ code argD ffO ffOcemux ffOrstmux ffOcepol ffOrstpol sigO sigCD clock clock_pol c } endcode -code argQ ffCD ffCDcemux ffCDcepol ffCDrstpol sigCD clock clock_pol +code argQ ffCD ffCDholdmux ffCDholdpol ffCDrstpol sigCD clock clock_pol if (!sigCD.empty() && (mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) { argQ = sigCD; subpattern(in_dffe); if (dff) { - if (dffcemux) { - ffCDcemux = dffcemux; - ffCDcepol = dffcepol; + if (dffholdmux) { + ffCDholdmux = dffholdmux; + ffCDholdpol = dffholdpol; } // Reset signal of C (IRSTTOP) and D (IRSTBOT) @@ -403,7 +403,7 @@ code argD argD = port(ffrstmux, ffrstpol ? \A : \B); dffD.replace(port(ffrstmux, \Y), argD); - // Only search for ffcemux if argQ has at + // Only search for ffholdmux if argQ has at // least 3 users (ff, , ffrstmux) and // dffD only has two (ff, ffrstmux) if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) @@ -413,26 +413,26 @@ code argD dffrstmux = nullptr; endcode -match ffcemux +match ffholdmux if !argD.empty() - select ffcemux->type.in($mux) - index port(ffcemux, \Y) === argD - choice AB {\A, \B} - index port(ffcemux, AB) === argQ - define pol (AB == \A) - set ffcepol pol + select ffholdmux->type.in($mux) + index port(ffholdmux, \Y) === argD + choice BA {\B, \A} + index port(ffholdmux, BA) === argQ + define pol (BA == \B) + set ffholdpol pol semioptional endmatch code argD - if (ffcemux) { - dffcemux = ffcemux; - dffcepol = ffcepol; - argD = port(ffcemux, ffcepol ? \B : \A); - dffD.replace(port(ffcemux, \Y), argD); + if (ffholdmux) { + dffholdmux = ffholdmux; + dffholdpol = ffholdpol; + argD = port(ffholdmux, ffholdpol ? \A : \B); + dffD.replace(port(ffholdmux, \Y), argD); } else - dffcemux = nullptr; + dffholdmux = nullptr; endcode // ####################### @@ -447,41 +447,41 @@ code reject; endcode -match ffcemux - select ffcemux->type.in($mux) - // ffcemux output must have two users: ffcemux and ff.D - select nusers(port(ffcemux, \Y)) == 2 +match ffholdmux + select ffholdmux->type.in($mux) + // ffholdmux output must have two users: ffholdmux and ff.D + select nusers(port(ffholdmux, \Y)) == 2 - choice AB {\A, \B} - // keep-last-value net must have at least three users: ffcemux, ff, downstream sink(s) - select nusers(port(ffcemux, AB)) >= 3 + choice BA {\B, \A} + // keep-last-value net must have at least three users: ffholdmux, ff, downstream sink(s) + select nusers(port(ffholdmux, BA)) >= 3 - slice offset GetSize(port(ffcemux, \Y)) - define BA (AB == \A ? \B : \A) - index port(ffcemux, BA)[offset] === argD[0] + slice offset GetSize(port(ffholdmux, \Y)) + define AB (BA == \B ? \A : \B) + index port(ffholdmux, AB)[offset] === argD[0] // Check that the rest of argD is present - filter GetSize(port(ffcemux, BA)) >= offset + GetSize(argD) - filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD + filter GetSize(port(ffholdmux, AB)) >= offset + GetSize(argD) + filter port(ffholdmux, AB).extract(offset, GetSize(argD)) == argD set ffoffset offset define pol (BA == \B) - set ffcepol pol + set ffholdpol pol semioptional endmatch code argD argQ - dffcemux = ffcemux; - if (ffcemux) { - SigSpec BA = port(ffcemux, ffcepol ? \B : \A); - SigSpec Y = port(ffcemux, \Y); + dffholdmux = ffholdmux; + if (ffholdmux) { + SigSpec AB = port(ffholdmux, ffholdpol ? \A : \B); + SigSpec Y = port(ffholdmux, \Y); argQ = argD; - argD.replace(BA, Y); - argQ.replace(BA, port(ffcemux, ffcepol ? \A : \B)); + argD.replace(AB, Y); + argQ.replace(AB, port(ffholdmux, ffholdpol ? \B : \A)); - dffcemux = ffcemux; - dffcepol = ffcepol; + dffholdmux = ffholdmux; + dffholdpol = ffholdpol; } endcode @@ -499,7 +499,7 @@ match ffrstmux index port(ffrstmux, AB)[offset] === argD[0] // Check that offset is consistent - filter !ffcemux || ffoffset == offset + filter !ffholdmux || ffoffset == offset // Check that the rest of argD is present filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD) filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD @@ -532,12 +532,12 @@ match ff index port(ff, \D)[offset] === argD[0] // Check that offset is consistent - filter (!ffcemux && !ffrstmux) || ffoffset == offset + filter (!ffholdmux && !ffrstmux) || ffoffset == offset // Check that the rest of argD is present filter GetSize(port(ff, \D)) >= offset + GetSize(argD) filter port(ff, \D).extract(offset, GetSize(argD)) == argD // Check that FF.Q is connected to CE-mux - filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ + filter !ffholdmux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ set ffoffset offset endmatch @@ -552,7 +552,7 @@ code argQ } SigSpec D = port(ff, \D); SigSpec Q = port(ff, \Q); - if (!ffcemux) { + if (!ffholdmux) { argQ = argD; argQ.replace(D, Q); } @@ -569,6 +569,6 @@ code argQ dffclock_pol = param(ff, \CLK_POLARITY).as_bool(); } // No enable/reset mux possible without flop - else if (dffcemux || dffrstmux) + else if (dffholdmux || dffrstmux) reject; endcode From ea5e5a212eeabc5e93d8636c92e92cb5881369ee Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 14:34:06 -0700 Subject: [PATCH 268/356] Cleanup xilinx_dsp too --- passes/pmgen/xilinx_dsp.pmg | 65 ++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 31ab75f09..c6120695a 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -393,6 +393,11 @@ match ff slice offset GetSize(port(ff, \D)) index port(ff, \Q)[offset] === argQ[0] + + // Check that the rest of argQ is present + filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ) + filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ + set ffoffset offset endmatch @@ -402,12 +407,6 @@ code argQ argD reject; SigSpec Q = port(ff, \Q); - if (ffoffset + GetSize(argQ) > GetSize(Q)) - reject; - for (int i = 1; i < GetSize(argQ); i++) - if (Q[ffoffset+i] != argQ[i]) - reject; - dff = ff; dffclock = port(ff, \CLK); dffD = argQ; @@ -481,6 +480,9 @@ arg argD argQ clock code dff = nullptr; + for (auto c : argD.chunks()) + if (c.wire->get_bool_attribute(\keep)) + reject; endcode match ffcemux @@ -495,8 +497,13 @@ match ffcemux slice offset GetSize(port(ffcemux, \Y)) define BA (AB == \A ? \B : \A) index port(ffcemux, BA)[offset] === argD[0] + + // Check that the rest of argD is present + filter GetSize(port(ffcemux, BA)) >= offset + GetSize(argD) + filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD + set ffoffset offset - define pol (BA == \B) + define pol (AB == \A) set ffcepol pol semioptional @@ -506,12 +513,6 @@ code argD argQ dffcemux = ffcemux; if (ffcemux) { SigSpec BA = port(ffcemux, ffcepol ? \B : \A); - if (ffoffset + GetSize(argD) > GetSize(BA)) - reject; - for (int i = 1; i < GetSize(argD); i++) - if (BA[ffoffset+i] != argD[i]) - reject; - SigSpec Y = port(ffcemux, \Y); argQ = argD; argD.replace(BA, Y); @@ -535,7 +536,12 @@ match ffrstmux define AB (BA == \B ? \A : \B) index port(ffrstmux, AB)[offset] === argD[0] + // Check that offset is consistent filter !ffcemux || ffoffset == offset + // Check that the rest of argD is present + filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD) + filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD + set ffoffset offset define pol (AB == \A) set ffrstpol pol @@ -547,13 +553,6 @@ code argD argQ dffrstmux = ffrstmux; if (ffrstmux) { SigSpec AB = port(ffrstmux, ffrstpol ? \A : \B); - if (ffoffset + GetSize(argD) > GetSize(AB)) - reject; - - for (int i = 1; i < GetSize(argD); i++) - if (AB[ffoffset+i] != argD[i]) - reject; - SigSpec Y = port(ffrstmux, \Y); argD.replace(AB, Y); @@ -570,10 +569,15 @@ match ff slice offset GetSize(port(ff, \D)) index port(ff, \D)[offset] === argD[0] + // Check that offset is consistent filter (!ffcemux && !ffrstmux) || ffoffset == offset - set ffoffset offset + // Check that the rest of argD is present + filter GetSize(port(ff, \D)) >= offset + GetSize(argD) + filter port(ff, \D).extract(offset, GetSize(argD)) == argD + // Check that FF.Q is connected to CE-mux + filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ - semioptional + set ffoffset offset endmatch code argQ @@ -582,26 +586,13 @@ code argQ reject; SigSpec D = port(ff, \D); - if (ffoffset + GetSize(argD) > GetSize(D)) - reject; - for (int i = 1; i < GetSize(argD); i++) - if (D[ffoffset+i] != argD[i]) - reject; - SigSpec Q = port(ff, \Q); - if (ffcemux) { - for (int i = 0; i < GetSize(argQ); i++) - if (Q[ffoffset+i] != argQ[i]) - reject; - } - else { + if (!ffcemux) { argQ = argD; argQ.replace(D, Q); } for (auto c : argQ.chunks()) { - if (c.wire->get_bool_attribute(\keep)) - reject; Const init = c.wire->attributes.at(\init, State::Sx); if (!init.is_fully_undef() && !init.is_fully_zero()) reject; @@ -609,7 +600,7 @@ code argQ dff = ff; dffQ = argQ; - dffclock = port(dff, \CLK); + dffclock = port(ff, \CLK); } // No enable/reset mux possible without flop else if (dffcemux || dffrstmux) From 307b2dc8e58447acae3b56b869fc3783b58ed734 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 14:46:53 -0700 Subject: [PATCH 269/356] Revert index to select --- passes/pmgen/ice40_dsp.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index aa081241d..73e92031e 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -215,7 +215,7 @@ endcode match mux select mux->type == $mux choice AB {\A, \B} - index nusers(port(mux, AB)) === 2 + select nusers(port(mux, AB)) == 2 index port(mux, AB) === sigO set muxAB AB optional From 517ca49963a8f186b9f7b54b63e576b4ffb5b847 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 14:49:47 -0700 Subject: [PATCH 270/356] Remove TODO as check should not be necessary --- passes/pmgen/ice40_dsp.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index b119b6b7c..01a0869cc 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -180,7 +180,6 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (O_width == 33) { log_assert(st.add); // If we have a signed multiply-add, then perform sign extension - // TODO: Need to check CD[31:16] is sign extension of CD[15:0]? if (st.add->getParam("\\A_SIGNED").as_bool() && st.add->getParam("\\B_SIGNED").as_bool()) pm.module->connect(O[32], O[31]); else From 64a72ed51e9d21cf5f30e3ff87856c808cf53a29 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 14:50:11 -0700 Subject: [PATCH 271/356] Do not perform width-checks for DSP48E1 which is much more complicated --- passes/pmgen/xilinx_dsp.pmg | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index c6120695a..f0537670f 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -278,17 +278,6 @@ endmatch code sigC sigP if (postAdd) { sigC = port(postAdd, postAddAB == \A ? \B : \A); - - // TODO for DSP48E1, which will have sign extended inputs/outputs - //int natural_mul_width = GetSize(port(dsp, \A)) + GetSize(port(dsp, \B)); - //int actual_mul_width = GetSize(sigP); - //int actual_acc_width = GetSize(sigC); - - //if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) - // reject; - //if ((actual_acc_width != actual_mul_width) && (param(dsp, \A_SIGNED).as_bool() != param(postAdd, \A_SIGNED).as_bool())) - // reject; - sigP = port(postAdd, \Y); } endcode From 3b9b0fcd0630133092b23a18453eb420534b2369 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 14:57:38 -0700 Subject: [PATCH 272/356] Tidy up synth_ice40, only restrict DSP_B_MINWIDTH=2 --- techlibs/ice40/synth_ice40.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 55aa72aa7..284bc90d0 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -273,7 +273,9 @@ struct SynthIce40Pass : public ScriptPass run("opt_expr"); run("opt_clean"); if (help_mode || dsp) { - run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 -D DSP_NAME=$__MUL16X16", "(if -dsp)"); + run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " + "-D DSP_A_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " + "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); run("opt_expr -fine", " (if -dsp)"); run("wreduce", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); From 95db2489bdb515a2e9d3a995574adc8c1071d3c0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 14:58:06 -0700 Subject: [PATCH 273/356] synth_xilinx to infer DSPs for Y_WIDTH >= 9 and [AB]_WIDTH >= 2 --- techlibs/xilinx/synth_xilinx.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 2ac254a1f..b55c40764 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -342,7 +342,10 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_dsp"), "(skip if '-nodsp')") { if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only - run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); + run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 " + "-D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller + "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); run("xilinx_dsp"); run("chtype -set $mul t:$__soft_mul"); } From 37b0fc17e32d84698b6fa4ccbcff40155351e290 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 15:40:17 -0700 Subject: [PATCH 274/356] Re-enable sign extension for C input --- passes/pmgen/xilinx_dsp.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 5af48e4d2..ce75be0e9 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -322,10 +322,10 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) opmode[5] = State::S1; if (opmode[4] != State::S0) { - //if (st.postAddMuxAB == "\\A") - // st.sigC.extend_u0(48, st.postAdd->getParam("\\B_SIGNED").as_bool()); - //else - // st.sigC.extend_u0(48, st.postAdd->getParam("\\A_SIGNED").as_bool()); + if (st.postAddMuxAB == "\\A") + st.sigC.extend_u0(48, st.postAdd->getParam("\\B_SIGNED").as_bool()); + else + st.sigC.extend_u0(48, st.postAdd->getParam("\\A_SIGNED").as_bool()); cell->setPort("\\C", st.sigC); } From 2d9484c12cd1fd96eca5253c876ad545ed209f40 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 15:40:28 -0700 Subject: [PATCH 275/356] When two boxes connect to each other, need not be a (* keep *) --- backends/aiger/xaiger.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index fa6ba0aca..cbce4c83b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -405,12 +405,7 @@ struct XAigerWriter if (O != b) alias_map[O] = b; undriven_bits.erase(O); - - auto jt = input_bits.find(b); - if (jt != input_bits.end()) { - log_assert(keep_bits.count(O)); - input_bits.erase(b); - } + input_bits.erase(b); } } } From c15a35db8487a31592046bfe8422740e196407d1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 15:55:49 -0700 Subject: [PATCH 276/356] D is 25 bits not 24 bits wide --- techlibs/xilinx/dsp_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v index 8901b215b..a4256eb92 100644 --- a/techlibs/xilinx/dsp_map.v +++ b/techlibs/xilinx/dsp_map.v @@ -32,7 +32,7 @@ module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); .A({{5{A[24]}}, A}), .B(B), .C(48'b0), - .D(24'b0), + .D(25'b0), .P(P_48), .INMODE(5'b00000), From 595fb611a5179f280452b5af356f652648eb3e2d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 15:58:01 -0700 Subject: [PATCH 277/356] Use (* techmap_autopurge *) to suppress techmap warnings --- techlibs/xilinx/abc_map.v | 110 ++++++++++++++++++------------------ techlibs/xilinx/abc_unmap.v | 83 ++++++++++++++------------- 2 files changed, 99 insertions(+), 94 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 1f369fc19..f23ec6463 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -22,11 +22,11 @@ module RAM32X1D ( output DPO, SPO, - input D, - input WCLK, - input WE, - input A0, A1, A2, A3, A4, - input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 + (* techmap_autopurge *) input D, + (* techmap_autopurge *) input WCLK, + (* techmap_autopurge *) input WE, + (* techmap_autopurge *) input A0, A1, A2, A3, A4, + (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 ); parameter INIT = 32'h0; parameter IS_WCLK_INVERTED = 1'b0; @@ -45,11 +45,11 @@ endmodule module RAM64X1D ( output DPO, SPO, - input D, - input WCLK, - input WE, - input A0, A1, A2, A3, A4, A5, - input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 + (* techmap_autopurge *) input D, + (* techmap_autopurge *) input WCLK, + (* techmap_autopurge *) input WE, + (* techmap_autopurge *) input A0, A1, A2, A3, A4, A5, + (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 ); parameter INIT = 64'h0; parameter IS_WCLK_INVERTED = 1'b0; @@ -68,10 +68,10 @@ endmodule module RAM128X1D ( output DPO, SPO, - input D, - input WCLK, - input WE, - input [6:0] A, DPRA + (* techmap_autopurge *) input D, + (* techmap_autopurge *) input WCLK, + (* techmap_autopurge *) input WE, + (* techmap_autopurge *) input [6:0] A, DPRA ); parameter INIT = 128'h0; parameter IS_WCLK_INVERTED = 1'b0; @@ -90,7 +90,7 @@ endmodule module SRL16E ( output Q, - input A0, A1, A2, A3, CE, CLK, D + (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D ); parameter [15:0] INIT = 16'h0000; parameter [0:0] IS_CLK_INVERTED = 1'b0; @@ -107,8 +107,8 @@ endmodule module SRLC32E ( output Q, output Q31, - input [4:0] A, - input CE, CLK, D + (* techmap_autopurge *) input [4:0] A, + (* techmap_autopurge *) input CE, CLK, D ); parameter [31:0] INIT = 32'h00000000; parameter [0:0] IS_CLK_INVERTED = 1'b0; @@ -134,44 +134,44 @@ module DSP48E1 ( output PATTERNDETECT, output [47:0] PCOUT, output UNDERFLOW, - input signed [29:0] A, - input [29:0] ACIN, - input [3:0] ALUMODE, - input signed [17:0] B, - input [17:0] BCIN, - input [47:0] C, - input CARRYCASCIN, - input CARRYIN, - input [2:0] CARRYINSEL, - input CEA1, - input CEA2, - input CEAD, - input CEALUMODE, - input CEB1, - input CEB2, - input CEC, - input CECARRYIN, - input CECTRL, - input CED, - input CEINMODE, - input CEM, - input CEP, - input CLK, - input [24:0] D, - input [4:0] INMODE, - input MULTSIGNIN, - input [6:0] OPMODE, - input [47:0] PCIN, - input RSTA, - input RSTALLCARRYIN, - input RSTALUMODE, - input RSTB, - input RSTC, - input RSTCTRL, - input RSTD, - input RSTINMODE, - input RSTM, - input RSTP + (* techmap_autopurge *) input signed [29:0] A, + (* techmap_autopurge *) input [29:0] ACIN, + (* techmap_autopurge *) input [3:0] ALUMODE, + (* techmap_autopurge *) input signed [17:0] B, + (* techmap_autopurge *) input [17:0] BCIN, + (* techmap_autopurge *) input [47:0] C, + (* techmap_autopurge *) input CARRYCASCIN, + (* techmap_autopurge *) input CARRYIN, + (* techmap_autopurge *) input [2:0] CARRYINSEL, + (* techmap_autopurge *) input CEA1, + (* techmap_autopurge *) input CEA2, + (* techmap_autopurge *) input CEAD, + (* techmap_autopurge *) input CEALUMODE, + (* techmap_autopurge *) input CEB1, + (* techmap_autopurge *) input CEB2, + (* techmap_autopurge *) input CEC, + (* techmap_autopurge *) input CECARRYIN, + (* techmap_autopurge *) input CECTRL, + (* techmap_autopurge *) input CED, + (* techmap_autopurge *) input CEINMODE, + (* techmap_autopurge *) input CEM, + (* techmap_autopurge *) input CEP, + (* techmap_autopurge *) input CLK, + (* techmap_autopurge *) input [24:0] D, + (* techmap_autopurge *) input [4:0] INMODE, + (* techmap_autopurge *) input MULTSIGNIN, + (* techmap_autopurge *) input [6:0] OPMODE, + (* techmap_autopurge *) input [47:0] PCIN, + (* techmap_autopurge *) input RSTA, + (* techmap_autopurge *) input RSTALLCARRYIN, + (* techmap_autopurge *) input RSTALUMODE, + (* techmap_autopurge *) input RSTB, + (* techmap_autopurge *) input RSTC, + (* techmap_autopurge *) input RSTCTRL, + (* techmap_autopurge *) input RSTD, + (* techmap_autopurge *) input RSTINMODE, + (* techmap_autopurge *) input RSTM, + (* techmap_autopurge *) input RSTP ); parameter integer ACASCREG = 1; parameter integer ADREG = 1; diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index 2ef507bf2..010041b73 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -31,7 +31,12 @@ module \$__ABC_DSP48E1_REG (input [47:0] I, output [47:0] O, output Q); assign O = I; endmodule (* techmap_celltype = "$__ABC_DSP48E1_MULT_P_MUX $__ABC_DSP48E1_MULT_PCOUT_MUX $__ABC_DSP48E1_MULT_DPORT_P_MUX $__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX $__ABC_DSP48E1_P_MUX $__ABC_DSP48E1_PCOUT_MUX" *) -module \$__ABC_DSP48E1_MUX (input Aq, Bq, Cq, Dq, ADq, Mq, input [47:0] P, input Pq, output [47:0] O); +module \$__ABC_DSP48E1_MUX ( + input Aq, Bq, Cq, Dq, ADq, Mq, + input [47:0] P, + input Pq, + output [47:0] O +); assign O = P; endmodule @@ -48,44 +53,44 @@ module \$__ABC_DSP48E1 ( output PATTERNDETECT, output [47:0] PCOUT, output UNDERFLOW, - input signed [29:0] A, - input [29:0] ACIN, - input [3:0] ALUMODE, - input signed [17:0] B, - input [17:0] BCIN, - input [47:0] C, - input CARRYCASCIN, - input CARRYIN, - input [2:0] CARRYINSEL, - input CEA1, - input CEA2, - input CEAD, - input CEALUMODE, - input CEB1, - input CEB2, - input CEC, - input CECARRYIN, - input CECTRL, - input CED, - input CEINMODE, - input CEM, - input CEP, - input CLK, - input [24:0] D, - input [4:0] INMODE, - input MULTSIGNIN, - input [6:0] OPMODE, - input [47:0] PCIN, - input RSTA, - input RSTALLCARRYIN, - input RSTALUMODE, - input RSTB, - input RSTC, - input RSTCTRL, - input RSTD, - input RSTINMODE, - input RSTM, - input RSTP + (* techmap_autopurge *) input signed [29:0] A, + (* techmap_autopurge *) input [29:0] ACIN, + (* techmap_autopurge *) input [3:0] ALUMODE, + (* techmap_autopurge *) input signed [17:0] B, + (* techmap_autopurge *) input [17:0] BCIN, + (* techmap_autopurge *) input [47:0] C, + (* techmap_autopurge *) input CARRYCASCIN, + (* techmap_autopurge *) input CARRYIN, + (* techmap_autopurge *) input [2:0] CARRYINSEL, + (* techmap_autopurge *) input CEA1, + (* techmap_autopurge *) input CEA2, + (* techmap_autopurge *) input CEAD, + (* techmap_autopurge *) input CEALUMODE, + (* techmap_autopurge *) input CEB1, + (* techmap_autopurge *) input CEB2, + (* techmap_autopurge *) input CEC, + (* techmap_autopurge *) input CECARRYIN, + (* techmap_autopurge *) input CECTRL, + (* techmap_autopurge *) input CED, + (* techmap_autopurge *) input CEINMODE, + (* techmap_autopurge *) input CEM, + (* techmap_autopurge *) input CEP, + (* techmap_autopurge *) input CLK, + (* techmap_autopurge *) input [24:0] D, + (* techmap_autopurge *) input [4:0] INMODE, + (* techmap_autopurge *) input MULTSIGNIN, + (* techmap_autopurge *) input [6:0] OPMODE, + (* techmap_autopurge *) input [47:0] PCIN, + (* techmap_autopurge *) input RSTA, + (* techmap_autopurge *) input RSTALLCARRYIN, + (* techmap_autopurge *) input RSTALUMODE, + (* techmap_autopurge *) input RSTB, + (* techmap_autopurge *) input RSTC, + (* techmap_autopurge *) input RSTCTRL, + (* techmap_autopurge *) input RSTD, + (* techmap_autopurge *) input RSTINMODE, + (* techmap_autopurge *) input RSTM, + (* techmap_autopurge *) input RSTP ); parameter integer ACASCREG = 1; parameter integer ADREG = 1; From a8bc46080548550e020155d1436470e0d3651eca Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 16:13:22 -0700 Subject: [PATCH 278/356] Use ID() macro --- passes/pmgen/ice40_dsp.cc | 148 ++++++++++---------- passes/pmgen/xilinx_dsp.cc | 270 ++++++++++++++++++------------------- 2 files changed, 209 insertions(+), 209 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 01a0869cc..ed3577400 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -65,21 +65,21 @@ void create_ice40_dsp(ice40_dsp_pm &pm) } Cell *cell = st.mul; - if (cell->type == "$mul") { + if (cell->type == ID($mul)) { log(" replacing %s with SB_MAC16 cell.\n", log_id(st.mul->type)); - cell = pm.module->addCell(NEW_ID, "\\SB_MAC16"); + cell = pm.module->addCell(NEW_ID, ID(SB_MAC16)); pm.module->swap_names(cell, st.mul); } - else log_assert(cell->type == "\\SB_MAC16"); + else log_assert(cell->type == ID(SB_MAC16)); // SB_MAC16 Input Interface SigSpec A = st.sigA; - A.extend_u0(16, st.mul->getParam("\\A_SIGNED").as_bool()); + A.extend_u0(16, st.mul->getParam(ID(A_SIGNED)).as_bool()); log_assert(GetSize(A) == 16); SigSpec B = st.sigB; - B.extend_u0(16, st.mul->getParam("\\B_SIGNED").as_bool()); + B.extend_u0(16, st.mul->getParam(ID(B_SIGNED)).as_bool()); log_assert(GetSize(B) == 16); SigSpec CD = st.sigCD; @@ -88,51 +88,51 @@ void create_ice40_dsp(ice40_dsp_pm &pm) else log_assert(GetSize(CD) == 32); - cell->setPort("\\A", A); - cell->setPort("\\B", B); - cell->setPort("\\C", CD.extract(16, 16)); - cell->setPort("\\D", CD.extract(0, 16)); + cell->setPort(ID::A, A); + cell->setPort(ID::B, B); + cell->setPort(ID(C), CD.extract(16, 16)); + cell->setPort(ID(D), CD.extract(0, 16)); - cell->setParam("\\A_REG", st.ffA ? State::S1 : State::S0); - cell->setParam("\\B_REG", st.ffB ? State::S1 : State::S0); - cell->setParam("\\C_REG", st.ffCD ? State::S1 : State::S0); - cell->setParam("\\D_REG", st.ffCD ? State::S1 : State::S0); + cell->setParam(ID(A_REG), st.ffA ? State::S1 : State::S0); + cell->setParam(ID(B_REG), st.ffB ? State::S1 : State::S0); + cell->setParam(ID(C_REG), st.ffCD ? State::S1 : State::S0); + cell->setParam(ID(D_REG), st.ffCD ? State::S1 : State::S0); SigSpec AHOLD, BHOLD, CDHOLD; if (st.ffAholdmux) - AHOLD = st.ffAholdpol ? st.ffAholdmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffAholdmux->getPort("\\S")); + AHOLD = st.ffAholdpol ? st.ffAholdmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffAholdmux->getPort(ID(S))); else AHOLD = State::S0; if (st.ffBholdmux) - BHOLD = st.ffBholdpol ? st.ffBholdmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffBholdmux->getPort("\\S")); + BHOLD = st.ffBholdpol ? st.ffBholdmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffBholdmux->getPort(ID(S))); else BHOLD = State::S0; if (st.ffCDholdmux) - CDHOLD = st.ffCDholdpol ? st.ffCDholdmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffCDholdmux->getPort("\\S")); + CDHOLD = st.ffCDholdpol ? st.ffCDholdmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffCDholdmux->getPort(ID(S))); else CDHOLD = State::S0; - cell->setPort("\\AHOLD", AHOLD); - cell->setPort("\\BHOLD", BHOLD); - cell->setPort("\\CHOLD", CDHOLD); - cell->setPort("\\DHOLD", CDHOLD); + cell->setPort(ID(AHOLD), AHOLD); + cell->setPort(ID(BHOLD), BHOLD); + cell->setPort(ID(CHOLD), CDHOLD); + cell->setPort(ID(DHOLD), CDHOLD); SigSpec IRSTTOP, IRSTBOT; if (st.ffArstmux) - IRSTTOP = st.ffArstpol ? st.ffArstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffArstmux->getPort("\\S")); + IRSTTOP = st.ffArstpol ? st.ffArstmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffArstmux->getPort(ID(S))); else IRSTTOP = State::S0; if (st.ffBrstmux) - IRSTBOT = st.ffBrstpol ? st.ffBrstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffBrstmux->getPort("\\S")); + IRSTBOT = st.ffBrstpol ? st.ffBrstmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffBrstmux->getPort(ID(S))); else IRSTBOT = State::S0; - cell->setPort("\\IRSTTOP", IRSTTOP); - cell->setPort("\\IRSTBOT", IRSTBOT); + cell->setPort(ID(IRSTTOP), IRSTTOP); + cell->setPort(ID(IRSTBOT), IRSTBOT); if (st.clock != SigBit()) { - cell->setPort("\\CLK", st.clock); - cell->setPort("\\CE", State::S1); - cell->setParam("\\NEG_TRIGGER", st.clock_pol ? State::S0 : State::S1); + cell->setPort(ID(CLK), st.clock); + cell->setPort(ID(CE), State::S1); + cell->setParam(ID(NEG_TRIGGER), st.clock_pol ? State::S0 : State::S1); log(" clock: %s (%s)", log_signal(st.clock), st.clock_pol ? "posedge" : "negedge"); @@ -158,20 +158,20 @@ void create_ice40_dsp(ice40_dsp_pm &pm) } else { - cell->setPort("\\CLK", State::S0); - cell->setPort("\\CE", State::S0); - cell->setParam("\\NEG_TRIGGER", State::S0); + cell->setPort(ID(CLK), State::S0); + cell->setPort(ID(CE), State::S0); + cell->setParam(ID(NEG_TRIGGER), State::S0); } // SB_MAC16 Cascade Interface - cell->setPort("\\SIGNEXTIN", State::Sx); - cell->setPort("\\SIGNEXTOUT", pm.module->addWire(NEW_ID)); + cell->setPort(ID(SIGNEXTIN), State::Sx); + cell->setPort(ID(SIGNEXTOUT), pm.module->addWire(NEW_ID)); - cell->setPort("\\CI", State::Sx); + cell->setPort(ID(CI), State::Sx); - cell->setPort("\\ACCUMCI", State::Sx); - cell->setPort("\\ACCUMCO", pm.module->addWire(NEW_ID)); + cell->setPort(ID(ACCUMCI), State::Sx); + cell->setPort(ID(ACCUMCO), pm.module->addWire(NEW_ID)); // SB_MAC16 Output Interface @@ -180,91 +180,91 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (O_width == 33) { log_assert(st.add); // If we have a signed multiply-add, then perform sign extension - if (st.add->getParam("\\A_SIGNED").as_bool() && st.add->getParam("\\B_SIGNED").as_bool()) + if (st.add->getParam(ID(A_SIGNED)).as_bool() && st.add->getParam(ID(B_SIGNED)).as_bool()) pm.module->connect(O[32], O[31]); else - cell->setPort("\\CO", O[32]); + cell->setPort(ID(CO), O[32]); O.remove(O_width-1); } else - cell->setPort("\\CO", pm.module->addWire(NEW_ID)); + cell->setPort(ID(CO), pm.module->addWire(NEW_ID)); log_assert(GetSize(O) <= 32); if (GetSize(O) < 32) O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); - cell->setPort("\\O", O); + cell->setPort(ID(O), O); bool accum = false; if (st.add) { - accum = (st.ffO && st.add->getPort(st.addAB == "\\A" ? "\\B" : "\\A") == st.sigO); + accum = (st.ffO && st.add->getPort(st.addAB == ID::A ? ID::B : ID::A) == st.sigO); if (accum) log(" accumulator %s (%s)\n", log_id(st.add), log_id(st.add->type)); else log(" adder %s (%s)\n", log_id(st.add), log_id(st.add->type)); - cell->setPort("\\ADDSUBTOP", st.add->type == "$add" ? State::S0 : State::S1); - cell->setPort("\\ADDSUBBOT", st.add->type == "$add" ? State::S0 : State::S1); + cell->setPort(ID(ADDSUBTOP), st.add->type == ID($add) ? State::S0 : State::S1); + cell->setPort(ID(ADDSUBBOT), st.add->type == ID($add) ? State::S0 : State::S1); } else { - cell->setPort("\\ADDSUBTOP", State::S0); - cell->setPort("\\ADDSUBBOT", State::S0); + cell->setPort(ID(ADDSUBTOP), State::S0); + cell->setPort(ID(ADDSUBBOT), State::S0); } SigSpec OHOLD; if (st.ffOholdmux) - OHOLD = st.ffOholdpol ? st.ffOholdmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffOholdmux->getPort("\\S")); + OHOLD = st.ffOholdpol ? st.ffOholdmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffOholdmux->getPort(ID(S))); else OHOLD = State::S0; - cell->setPort("\\OHOLDTOP", OHOLD); - cell->setPort("\\OHOLDBOT", OHOLD); + cell->setPort(ID(OHOLDTOP), OHOLD); + cell->setPort(ID(OHOLDBOT), OHOLD); SigSpec ORST; if (st.ffOrstmux) - ORST = st.ffOrstpol ? st.ffOrstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffOrstmux->getPort("\\S")); + ORST = st.ffOrstpol ? st.ffOrstmux->getPort(ID(S)) : pm.module->Not(NEW_ID, st.ffOrstmux->getPort(ID(S))); else ORST = State::S0; - cell->setPort("\\ORSTTOP", ORST); - cell->setPort("\\ORSTBOT", ORST); + cell->setPort(ID(ORSTTOP), ORST); + cell->setPort(ID(ORSTBOT), ORST); SigSpec acc_reset = State::S0; if (st.mux) { - if (st.muxAB == "\\A") - acc_reset = st.mux->getPort("\\S"); + if (st.muxAB == ID::A) + acc_reset = st.mux->getPort(ID(S)); else - acc_reset = pm.module->Not(NEW_ID, st.mux->getPort("\\S")); + acc_reset = pm.module->Not(NEW_ID, st.mux->getPort(ID(S))); } - cell->setPort("\\OLOADTOP", acc_reset); - cell->setPort("\\OLOADBOT", acc_reset); + cell->setPort(ID(OLOADTOP), acc_reset); + cell->setPort(ID(OLOADBOT), acc_reset); // SB_MAC16 Remaining Parameters - cell->setParam("\\TOP_8x8_MULT_REG", st.ffFJKG ? State::S1 : State::S0); - cell->setParam("\\BOT_8x8_MULT_REG", st.ffFJKG ? State::S1 : State::S0); - cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffFJKG ? State::S1 : State::S0); - cell->setParam("\\PIPELINE_16x16_MULT_REG2", st.ffH ? State::S1 : State::S0); + cell->setParam(ID(TOP_8x8_MULT_REG), st.ffFJKG ? State::S1 : State::S0); + cell->setParam(ID(BOT_8x8_MULT_REG), st.ffFJKG ? State::S1 : State::S0); + cell->setParam(ID(PIPELINE_16x16_MULT_REG1), st.ffFJKG ? State::S1 : State::S0); + cell->setParam(ID(PIPELINE_16x16_MULT_REG2), st.ffH ? State::S1 : State::S0); - cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2)); - cell->setParam("\\TOPADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); - cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2)); + cell->setParam(ID(TOPADDSUB_LOWERINPUT), Const(2, 2)); + cell->setParam(ID(TOPADDSUB_UPPERINPUT), accum ? State::S0 : State::S1); + cell->setParam(ID(TOPADDSUB_CARRYSELECT), Const(3, 2)); - cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2)); - cell->setParam("\\BOTADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); - cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2)); + cell->setParam(ID(BOTADDSUB_LOWERINPUT), Const(2, 2)); + cell->setParam(ID(BOTADDSUB_UPPERINPUT), accum ? State::S0 : State::S1); + cell->setParam(ID(BOTADDSUB_CARRYSELECT), Const(0, 2)); - cell->setParam("\\MODE_8x8", State::S0); - cell->setParam("\\A_SIGNED", st.mul->getParam("\\A_SIGNED").as_bool()); - cell->setParam("\\B_SIGNED", st.mul->getParam("\\B_SIGNED").as_bool()); + cell->setParam(ID(MODE_8x8), State::S0); + cell->setParam(ID(A_SIGNED), st.mul->getParam(ID(A_SIGNED)).as_bool()); + cell->setParam(ID(B_SIGNED), st.mul->getParam(ID(B_SIGNED)).as_bool()); if (st.ffO) { if (st.o_lo) - cell->setParam("\\TOPOUTPUT_SELECT", Const(st.add ? 0 : 3, 2)); + cell->setParam(ID(TOPOUTPUT_SELECT), Const(st.add ? 0 : 3, 2)); else - cell->setParam("\\TOPOUTPUT_SELECT", Const(1, 2)); + cell->setParam(ID(TOPOUTPUT_SELECT), Const(1, 2)); - st.ffO->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O))); - cell->setParam("\\BOTOUTPUT_SELECT", Const(1, 2)); + st.ffO->connections_.at(ID(Q)).replace(O, pm.module->addWire(NEW_ID, GetSize(O))); + cell->setParam(ID(BOTOUTPUT_SELECT), Const(1, 2)); } else { - cell->setParam("\\TOPOUTPUT_SELECT", Const(st.add ? 0 : 3, 2)); - cell->setParam("\\BOTOUTPUT_SELECT", Const(st.add ? 0 : 3, 2)); + cell->setParam(ID(TOPOUTPUT_SELECT), Const(st.add ? 0 : 3, 2)); + cell->setParam(ID(BOTOUTPUT_SELECT), Const(st.add ? 0 : 3, 2)); } if (cell != st.mul) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index ce75be0e9..3cfaa9371 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -27,36 +27,36 @@ PRIVATE_NAMESPACE_BEGIN #include "passes/pmgen/xilinx_dsp_pm.h" static Cell* addDsp(Module *module) { - Cell *cell = module->addCell(NEW_ID, "\\DSP48E1"); - cell->setParam("\\ACASCREG", 0); - cell->setParam("\\ADREG", 0); - cell->setParam("\\A_INPUT", Const("DIRECT")); - cell->setParam("\\ALUMODEREG", 0); - cell->setParam("\\AREG", 0); - cell->setParam("\\BCASCREG", 0); - cell->setParam("\\B_INPUT", Const("DIRECT")); - cell->setParam("\\BREG", 0); - cell->setParam("\\CARRYINREG", 0); - cell->setParam("\\CARRYINSELREG", 0); - cell->setParam("\\CREG", 0); - cell->setParam("\\DREG", 0); - cell->setParam("\\INMODEREG", 0); - cell->setParam("\\MREG", 0); - cell->setParam("\\OPMODEREG", 0); - cell->setParam("\\PREG", 0); - cell->setParam("\\USE_MULT", Const("NONE")); - cell->setParam("\\USE_SIMD", Const("ONE48")); - cell->setParam("\\USE_DPORT", Const("FALSE")); + Cell *cell = module->addCell(NEW_ID, ID(DSP48E1)); + cell->setParam(ID(ACASCREG), 0); + cell->setParam(ID(ADREG), 0); + cell->setParam(ID(A_INPUT), Const("DIRECT")); + cell->setParam(ID(ALUMODEREG), 0); + cell->setParam(ID(AREG), 0); + cell->setParam(ID(BCASCREG), 0); + cell->setParam(ID(B_INPUT), Const("DIRECT")); + cell->setParam(ID(BREG), 0); + cell->setParam(ID(CARRYINREG), 0); + cell->setParam(ID(CARRYINSELREG), 0); + cell->setParam(ID(CREG), 0); + cell->setParam(ID(DREG), 0); + cell->setParam(ID(INMODEREG), 0); + cell->setParam(ID(MREG), 0); + cell->setParam(ID(OPMODEREG), 0); + cell->setParam(ID(PREG), 0); + cell->setParam(ID(USE_MULT), Const("NONE")); + cell->setParam(ID(USE_SIMD), Const("ONE48")); + cell->setParam(ID(USE_DPORT), Const("FALSE")); - cell->setPort("\\D", Const(0, 24)); - cell->setPort("\\INMODE", Const(0, 5)); - cell->setPort("\\ALUMODE", Const(0, 4)); - cell->setPort("\\OPMODE", Const(0, 7)); - cell->setPort("\\CARRYINSEL", Const(0, 3)); - cell->setPort("\\ACIN", Const(0, 30)); - cell->setPort("\\BCIN", Const(0, 18)); - cell->setPort("\\PCIN", Const(0, 48)); - cell->setPort("\\CARRYIN", Const(0, 1)); + cell->setPort(ID(D), Const(0, 24)); + cell->setPort(ID(INMODE), Const(0, 5)); + cell->setPort(ID(ALUMODE), Const(0, 4)); + cell->setPort(ID(OPMODE), Const(0, 7)); + cell->setPort(ID(CARRYINSEL), Const(0, 3)); + cell->setPort(ID(ACIN), Const(0, 30)); + cell->setPort(ID(BCIN), Const(0, 18)); + cell->setPort(ID(PCIN), Const(0, 48)); + cell->setPort(ID(CARRYIN), Const(0, 1)); return cell; } @@ -66,25 +66,25 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) std::deque simd24_add, simd24_sub; for (auto cell : selected_cells) { - if (!cell->type.in("$add", "$sub")) + if (!cell->type.in(ID($add), ID($sub))) continue; - SigSpec Y = cell->getPort("\\Y"); + SigSpec Y = cell->getPort(ID(Y)); if (!Y.is_chunk()) continue; - if (!Y.as_chunk().wire->get_strpool_attribute("\\use_dsp").count("simd")) + if (!Y.as_chunk().wire->get_strpool_attribute(ID(use_dsp)).count("simd")) continue; if (GetSize(Y) > 25) continue; - SigSpec A = cell->getPort("\\A"); - SigSpec B = cell->getPort("\\B"); + SigSpec A = cell->getPort(ID(A)); + SigSpec B = cell->getPort(ID(B)); if (GetSize(Y) <= 13) { if (GetSize(A) > 12) continue; if (GetSize(B) > 12) continue; - if (cell->type == "$add") + if (cell->type == ID($add)) simd12_add.push_back(cell); - else if (cell->type == "$sub") + else if (cell->type == ID($sub)) simd12_sub.push_back(cell); } else if (GetSize(Y) <= 25) { @@ -92,9 +92,9 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) continue; if (GetSize(B) > 24) continue; - if (cell->type == "$add") + if (cell->type == ID($add)) simd24_add.push_back(cell); - else if (cell->type == "$sub") + else if (cell->type == ID($sub)) simd24_sub.push_back(cell); } else @@ -102,11 +102,11 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) } auto f12 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) { - SigSpec A = lane->getPort("\\A"); - SigSpec B = lane->getPort("\\B"); - SigSpec Y = lane->getPort("\\Y"); - A.extend_u0(12, lane->getParam("\\A_SIGNED").as_bool()); - B.extend_u0(12, lane->getParam("\\B_SIGNED").as_bool()); + SigSpec A = lane->getPort(ID(A)); + SigSpec B = lane->getPort(ID(B)); + SigSpec Y = lane->getPort(ID(Y)); + A.extend_u0(12, lane->getParam(ID(A_SIGNED)).as_bool()); + B.extend_u0(12, lane->getParam(ID(B_SIGNED)).as_bool()); AB.append(A); C.append(B); if (GetSize(Y) < 13) @@ -139,11 +139,11 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1)); Cell *cell = addDsp(module); - cell->setParam("\\USE_SIMD", Const("FOUR12")); + cell->setParam(ID(USE_SIMD), Const("FOUR12")); // X = A:B // Y = 0 // Z = C - cell->setPort("\\OPMODE", Const::from_string("0110011")); + cell->setPort(ID(OPMODE), Const::from_string("0110011")); log_assert(lane1); log_assert(lane2); @@ -170,13 +170,13 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) log_assert(GetSize(C) == 48); log_assert(GetSize(P) == 48); log_assert(GetSize(CARRYOUT) == 4); - cell->setPort("\\A", AB.extract(18, 30)); - cell->setPort("\\B", AB.extract(0, 18)); - cell->setPort("\\C", C); - cell->setPort("\\P", P); - cell->setPort("\\CARRYOUT", CARRYOUT); - if (lane1->type == "$sub") - cell->setPort("\\ALUMODE", Const::from_string("0011")); + cell->setPort(ID(A), AB.extract(18, 30)); + cell->setPort(ID(B), AB.extract(0, 18)); + cell->setPort(ID(C), C); + cell->setPort(ID(P), P); + cell->setPort(ID(CARRYOUT), CARRYOUT); + if (lane1->type == ID($sub)) + cell->setPort(ID(ALUMODE), Const::from_string("0011")); module->remove(lane1); module->remove(lane2); @@ -190,11 +190,11 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) g12(simd12_sub); auto f24 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) { - SigSpec A = lane->getPort("\\A"); - SigSpec B = lane->getPort("\\B"); - SigSpec Y = lane->getPort("\\Y"); - A.extend_u0(24, lane->getParam("\\A_SIGNED").as_bool()); - B.extend_u0(24, lane->getParam("\\B_SIGNED").as_bool()); + SigSpec A = lane->getPort(ID(A)); + SigSpec B = lane->getPort(ID(B)); + SigSpec Y = lane->getPort(ID(Y)); + A.extend_u0(24, lane->getParam(ID(A_SIGNED)).as_bool()); + B.extend_u0(24, lane->getParam(ID(B_SIGNED)).as_bool()); C.append(A); AB.append(B); if (GetSize(Y) < 25) @@ -220,11 +220,11 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1)); Cell *cell = addDsp(module); - cell->setParam("\\USE_SIMD", Const("TWO24")); + cell->setParam(ID(USE_SIMD), Const("TWO24")); // X = A:B // Y = 0 // Z = C - cell->setPort("\\OPMODE", Const::from_string("0110011")); + cell->setPort(ID(OPMODE), Const::from_string("0110011")); log_assert(lane1); log_assert(lane2); @@ -234,13 +234,13 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) log_assert(GetSize(C) == 48); log_assert(GetSize(P) == 48); log_assert(GetSize(CARRYOUT) == 4); - cell->setPort("\\A", AB.extract(18, 30)); - cell->setPort("\\B", AB.extract(0, 18)); - cell->setPort("\\C", C); - cell->setPort("\\P", P); - cell->setPort("\\CARRYOUT", CARRYOUT); - if (lane1->type == "$sub") - cell->setPort("\\ALUMODE", Const::from_string("0011")); + cell->setPort(ID(A), AB.extract(18, 30)); + cell->setPort(ID(B), AB.extract(0, 18)); + cell->setPort(ID(C), C); + cell->setPort(ID(P), P); + cell->setPort(ID(CARRYOUT), CARRYOUT); + if (lane1->type == ID($sub)) + cell->setPort(ID(ALUMODE), Const::from_string("0011")); module->remove(lane1); module->remove(lane2); @@ -281,37 +281,37 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.preAdd) { log(" preadder %s (%s)\n", log_id(st.preAdd), log_id(st.preAdd->type)); - bool A_SIGNED = st.preAdd->getParam("\\A_SIGNED").as_bool(); - bool D_SIGNED = st.preAdd->getParam("\\B_SIGNED").as_bool(); - if (st.sigA == st.preAdd->getPort("\\B")) + bool A_SIGNED = st.preAdd->getParam(ID(A_SIGNED)).as_bool(); + bool D_SIGNED = st.preAdd->getParam(ID(B_SIGNED)).as_bool(); + if (st.sigA == st.preAdd->getPort(ID(B))) std::swap(A_SIGNED, D_SIGNED); st.sigA.extend_u0(30, A_SIGNED); st.sigD.extend_u0(25, D_SIGNED); - cell->setPort("\\A", st.sigA); - cell->setPort("\\D", st.sigD); - cell->connections_.at("\\INMODE") = Const::from_string("00100"); + cell->setPort(ID(A), st.sigA); + cell->setPort(ID(D), st.sigD); + cell->connections_.at(ID(INMODE)) = Const::from_string("00100"); if (st.ffAD) { if (st.ffADcemux) { - SigSpec S = st.ffADcemux->getPort("\\S"); - cell->setPort("\\CEAD", st.ffADcepol ? S : pm.module->Not(NEW_ID, S)); + SigSpec S = st.ffADcemux->getPort(ID(S)); + cell->setPort(ID(CEAD), st.ffADcepol ? S : pm.module->Not(NEW_ID, S)); } else - cell->setPort("\\CEAD", State::S1); - cell->setParam("\\ADREG", 1); + cell->setPort(ID(CEAD), State::S1); + cell->setParam(ID(ADREG), 1); } - cell->setParam("\\USE_DPORT", Const("TRUE")); + cell->setParam(ID(USE_DPORT), Const("TRUE")); pm.autoremove(st.preAdd); } if (st.postAdd) { log(" postadder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); - SigSpec &opmode = cell->connections_.at("\\OPMODE"); + SigSpec &opmode = cell->connections_.at(ID(OPMODE)); if (st.postAddMux) { log_assert(st.ffP); - opmode[4] = st.postAddMux->getPort("\\S"); + opmode[4] = st.postAddMux->getPort(ID(S)); pm.autoremove(st.postAddMux); } else if (st.ffP && st.sigC == st.sigP) @@ -322,23 +322,23 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) opmode[5] = State::S1; if (opmode[4] != State::S0) { - if (st.postAddMuxAB == "\\A") - st.sigC.extend_u0(48, st.postAdd->getParam("\\B_SIGNED").as_bool()); + if (st.postAddMuxAB == ID(A)) + st.sigC.extend_u0(48, st.postAdd->getParam(ID(B_SIGNED)).as_bool()); else - st.sigC.extend_u0(48, st.postAdd->getParam("\\A_SIGNED").as_bool()); - cell->setPort("\\C", st.sigC); + st.sigC.extend_u0(48, st.postAdd->getParam(ID(A_SIGNED)).as_bool()); + cell->setPort(ID(C), st.sigC); } pm.autoremove(st.postAdd); } if (st.overflow) { log(" overflow %s (%s)\n", log_id(st.overflow), log_id(st.overflow->type)); - cell->setParam("\\USE_PATTERN_DETECT", Const("PATDET")); - cell->setParam("\\SEL_PATTERN", Const("PATTERN")); - cell->setParam("\\SEL_MASK", Const("MASK")); + cell->setParam(ID(USE_PATTERN_DETECT), Const("PATDET")); + cell->setParam(ID(SEL_PATTERN), Const("PATTERN")); + cell->setParam(ID(SEL_MASK), Const("MASK")); - if (st.overflow->type == "$ge") { - Const B = st.overflow->getPort("\\B").as_const(); + if (st.overflow->type == ID($ge)) { + Const B = st.overflow->getPort(ID(B)).as_const(); log_assert(std::count(B.bits.begin(), B.bits.end(), State::S1) == 1); // Since B is an exact power of 2, subtract 1 // by inverting all bits up until hitting @@ -351,9 +351,9 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) } B.extu(48); - cell->setParam("\\MASK", B); - cell->setParam("\\PATTERN", Const(0, 48)); - cell->setPort("\\OVERFLOW", st.overflow->getPort("\\Y")); + cell->setParam(ID(MASK), B); + cell->setParam(ID(PATTERN), Const(0, 48)); + cell->setPort(ID(OVERFLOW), st.overflow->getPort(ID(Y))); } else log_abort(); @@ -362,29 +362,29 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) if (st.clock != SigBit()) { - cell->setPort("\\CLK", st.clock); + cell->setPort(ID(CLK), st.clock); auto f = [&pm,cell](SigSpec &A, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) { - SigSpec D = ff->getPort("\\D"); - SigSpec Q = pm.sigmap(ff->getPort("\\Q")); + SigSpec D = ff->getPort(ID(D)); + SigSpec Q = pm.sigmap(ff->getPort(ID(Q))); if (!A.empty()) A.replace(Q, D); if (rstmux) { - SigSpec Y = rstmux->getPort("\\Y"); - SigSpec AB = rstmux->getPort(rstpol ? "\\A" : "\\B"); + SigSpec Y = rstmux->getPort(ID(Y)); + SigSpec AB = rstmux->getPort(rstpol ? ID(A) : ID(B)); if (!A.empty()) A.replace(Y, AB); if (rstport != IdString()) { - SigSpec S = rstmux->getPort("\\S"); + SigSpec S = rstmux->getPort(ID(S)); cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S)); } } else if (rstport != IdString()) cell->setPort(rstport, State::S0); if (cemux) { - SigSpec Y = cemux->getPort("\\Y"); - SigSpec BA = cemux->getPort(cepol ? "\\B" : "\\A"); - SigSpec S = cemux->getPort("\\S"); + SigSpec Y = cemux->getPort(ID(Y)); + SigSpec BA = cemux->getPort(cepol ? ID(B) : ID(A)); + SigSpec S = cemux->getPort(ID(S)); if (!A.empty()) A.replace(Y, BA); cell->setPort(ceport, cepol ? S : pm.module->Not(NEW_ID, S)); @@ -393,7 +393,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) cell->setPort(ceport, State::S1); for (auto c : Q.chunks()) { - auto it = c.wire->attributes.find("\\init"); + auto it = c.wire->attributes.find(ID(init)); if (it == c.wire->attributes.end()) continue; for (int i = c.offset; i < c.offset+c.width; i++) { @@ -404,50 +404,50 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) }; if (st.ffA2) { - SigSpec &A = cell->connections_.at("\\A"); - f(A, st.ffA2, st.ffA2cemux, st.ffA2cepol, "\\CEA2", st.ffA2rstmux, st.ffArstpol, "\\RSTA"); + SigSpec &A = cell->connections_.at(ID(A)); + f(A, st.ffA2, st.ffA2cemux, st.ffA2cepol, ID(CEA2), st.ffA2rstmux, st.ffArstpol, ID(RSTA)); pm.add_siguser(A, cell); if (st.ffA1) { - f(A, st.ffA1, st.ffA1cemux, st.ffA1cepol, "\\CEA1", st.ffA1rstmux, st.ffArstpol, IdString()); - cell->setParam("\\AREG", 2); + f(A, st.ffA1, st.ffA1cemux, st.ffA1cepol, ID(CEA1), st.ffA1rstmux, st.ffArstpol, IdString()); + cell->setParam(ID(AREG), 2); } else - cell->setParam("\\AREG", 1); + cell->setParam(ID(AREG), 1); } if (st.ffB2) { - SigSpec &B = cell->connections_.at("\\B"); - f(B, st.ffB2, st.ffB2cemux, st.ffB2cepol, "\\CEB2", st.ffB2rstmux, st.ffBrstpol, "\\RSTB"); + SigSpec &B = cell->connections_.at(ID(B)); + f(B, st.ffB2, st.ffB2cemux, st.ffB2cepol, ID(CEB2), st.ffB2rstmux, st.ffBrstpol, ID(RSTB)); pm.add_siguser(B, cell); if (st.ffB1) { - f(B, st.ffB1, st.ffB1cemux, st.ffB1cepol, "\\CEB1", st.ffB1rstmux, st.ffBrstpol, IdString()); - cell->setParam("\\BREG", 2); + f(B, st.ffB1, st.ffB1cemux, st.ffB1cepol, ID(CEB1), st.ffB1rstmux, st.ffBrstpol, IdString()); + cell->setParam(ID(BREG), 2); } else - cell->setParam("\\BREG", 1); + cell->setParam(ID(BREG), 1); } if (st.ffC) { - SigSpec &C = cell->connections_.at("\\C"); - f(C, st.ffC, st.ffCcemux, st.ffCcepol, "\\CEC", st.ffCrstmux, st.ffCrstpol, "\\RSTC"); + SigSpec &C = cell->connections_.at(ID(C)); + f(C, st.ffC, st.ffCcemux, st.ffCcepol, ID(CEC), st.ffCrstmux, st.ffCrstpol, ID(RSTC)); pm.add_siguser(C, cell); - cell->setParam("\\CREG", 1); + cell->setParam(ID(CREG), 1); } if (st.ffD) { - SigSpec &D = cell->connections_.at("\\D"); - f(D, st.ffD, st.ffDcemux, st.ffDcepol, "\\CED", st.ffDrstmux, st.ffDrstpol, "\\RSTD"); + SigSpec &D = cell->connections_.at(ID(D)); + f(D, st.ffD, st.ffDcemux, st.ffDcepol, ID(CED), st.ffDrstmux, st.ffDrstpol, ID(RSTD)); pm.add_siguser(D, cell); - cell->setParam("\\DREG", 1); + cell->setParam(ID(DREG), 1); } if (st.ffM) { SigSpec M; // unused - f(M, st.ffM, st.ffMcemux, st.ffMcepol, "\\CEM", st.ffMrstmux, st.ffMrstpol, "\\RSTM"); - st.ffM->connections_.at("\\Q").replace(st.sigM, pm.module->addWire(NEW_ID, GetSize(st.sigM))); - cell->setParam("\\MREG", State::S1); + f(M, st.ffM, st.ffMcemux, st.ffMcepol, ID(CEM), st.ffMrstmux, st.ffMrstpol, ID(RSTM)); + st.ffM->connections_.at(ID(Q)).replace(st.sigM, pm.module->addWire(NEW_ID, GetSize(st.sigM))); + cell->setParam(ID(MREG), State::S1); } if (st.ffP) { SigSpec P; // unused - f(P, st.ffP, st.ffPcemux, st.ffPcepol, "\\CEP", st.ffPrstmux, st.ffPrstpol, "\\RSTP"); - st.ffP->connections_.at("\\Q").replace(st.sigP, pm.module->addWire(NEW_ID, GetSize(st.sigP))); - cell->setParam("\\PREG", State::S1); + f(P, st.ffP, st.ffPcemux, st.ffPcepol, ID(CEP), st.ffPrstmux, st.ffPrstpol, ID(RSTP)); + st.ffP->connections_.at(ID(Q)).replace(st.sigP, pm.module->addWire(NEW_ID, GetSize(st.sigP))); + cell->setParam(ID(PREG), State::S1); } log(" clock: %s (%s)", log_signal(st.clock), "posedge"); @@ -485,7 +485,7 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) SigSpec P = st.sigP; if (GetSize(P) < 48) P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); - cell->setPort("\\P", P); + cell->setPort(ID(P), P); bit_to_driver.insert(std::make_pair(P[0], cell)); bit_to_driver.insert(std::make_pair(P[17], cell)); @@ -553,14 +553,14 @@ struct XilinxDspPass : public Pass { // NB: Needs to be done after pattern matcher has folded all // $add cells into the DSP for (auto cell : module->cells()) { - if (cell->type != "\\DSP48E1") + if (cell->type != ID(DSP48E1)) continue; - if (cell->parameters.at("\\CREG", State::S1).as_bool()) + if (cell->parameters.at(ID(CREG), State::S1).as_bool()) continue; - SigSpec &opmode = cell->connections_.at("\\OPMODE"); + SigSpec &opmode = cell->connections_.at(ID(OPMODE)); if (opmode.extract(4,3) != Const::from_string("011")) continue; - SigSpec C = unextend(pm.sigmap(cell->getPort("\\C"))); + SigSpec C = unextend(pm.sigmap(cell->getPort(ID(C)))); if (!C[0].wire) continue; auto it = bit_to_driver.find(C[0]); @@ -568,22 +568,22 @@ struct XilinxDspPass : public Pass { continue; auto driver = it->second; - SigSpec P = driver->getPort("\\P"); + SigSpec P = driver->getPort(ID(P)); if (GetSize(P) >= GetSize(C) && P.extract(0, GetSize(C)) == C) { - cell->setPort("\\C", Const(0, 48)); + cell->setPort(ID(C), Const(0, 48)); Wire *cascade = module->addWire(NEW_ID, 48); - driver->setPort("\\PCOUT", cascade); - cell->setPort("\\PCIN", cascade); + driver->setPort(ID(PCOUT), cascade); + cell->setPort(ID(PCIN), cascade); opmode[6] = State::S0; opmode[5] = State::S0; opmode[4] = State::S1; bit_to_driver.erase(it); } else if (GetSize(P) >= GetSize(C)+17 && P.extract(17, GetSize(C)) == C) { - cell->setPort("\\C", Const(0, 48)); + cell->setPort(ID(C), Const(0, 48)); Wire *cascade = module->addWire(NEW_ID, 48); - driver->setPort("\\PCOUT", cascade); - cell->setPort("\\PCIN", cascade); + driver->setPort(ID(PCOUT), cascade); + cell->setPort(ID(PCIN), cascade); opmode[6] = State::S1; opmode[5] = State::S0; opmode[4] = State::S1; From 5ca25b0c59d47e26c7bf119c47b4e73054fafbc8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 16:27:14 -0700 Subject: [PATCH 279/356] Suppress $anyseq warnings --- techlibs/xilinx/abc_map.v | 47 ++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index f23ec6463..1b7900af8 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -305,29 +305,36 @@ __CELL__ #( // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && MREG == 0 && PREG == 0) - assign iA = A; + assign iA = A, pA = 1'bx; else \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && MREG == 0 && PREG == 0) - assign iB = B; + assign iB = B, pB = 1'bx; else \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) - assign iC = C; + assign iC = C, pC = 1'bx; else \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0) assign iD = D; else if (techmap_guard) $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + assign pD = 1'bx; if (ADREG == 1 && techmap_guard) - $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); + $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); + assign pAD = 1'bx; if (PREG == 0) begin + assign pP = 1'bx; if (MREG == 1) \$__ABC_DSP48E1_REG rM (.Q(pM)); + else + assign pM = 1'bx; end - else + else begin \$__ABC_DSP48E1_REG rP (.Q(pP)); + assign pM = 1'bx; + end \$__ABC_DSP48E1_MULT_P_MUX muxP ( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) @@ -350,26 +357,31 @@ __CELL__ #( // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0) - assign iA = A; + assign iA = A, pA = 1'bx; else \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && MREG == 0 && PREG == 0) - assign iB = B; + assign iB = B, pB = 1'bx; else \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) - assign iC = C; + assign iC = C, pC = 1'bx; else \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0 && ADREG == 0) - assign iD = D; + assign iD = D, pD = 1'bx; else \$__ABC_DSP48E1_REG rD (.I(D), .O(iD), .Q(pD)); if (PREG == 0) begin if (MREG == 1) \$__ABC_DSP48E1_REG rM (.Q(pM)); - else if (ADREG == 1) - \$__ABC_DSP48E1_REG rAD (.Q(pAD)); + else begin + assign pM = 1'bx; + if (ADREG == 1) + \$__ABC_DSP48E1_REG rAD (.Q(pAD)); + else + assign pAD = 1'bx; + end end else \$__ABC_DSP48E1_REG rP (.Q(pP)); @@ -395,25 +407,30 @@ __CELL__ #( // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && PREG == 0) - assign iA = A; + assign iA = A, pA = 1'bx; else \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && PREG == 0) - assign iB = B; + assign iB = B, pB = 1'bx; else \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) - assign iC = C; + assign iC = C, pC = 1'bx; else \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); if (MREG == 1 && techmap_guard) - $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\""); + $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\""); + assign pM = 1'bx; if (DREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + assign pD = 1'bx; if (ADREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); + assign pAD = 1'bx; if (PREG == 1) \$__ABC_DSP48E1_REG rP (.Q(pP)); + else + assign pP = 1'bx; \$__ABC_DSP48E1_P_MUX muxP ( .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) From 2f98f9deee063de1e6a57437f1fe885d42916e19 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 18:08:16 -0700 Subject: [PATCH 280/356] Add mac.sh and macc_tb.v for testing --- tests/xilinx/macc.sh | 3 ++ tests/xilinx/macc_tb.v | 96 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 tests/xilinx/macc.sh create mode 100644 tests/xilinx/macc_tb.v diff --git a/tests/xilinx/macc.sh b/tests/xilinx/macc.sh new file mode 100644 index 000000000..86e4c2bb6 --- /dev/null +++ b/tests/xilinx/macc.sh @@ -0,0 +1,3 @@ +../../yosys -qp "synth_xilinx -top macc2; rename -top macc2_uut" macc.v -o macc_uut.v +iverilog -o test_macc macc_tb.v macc_uut.v macc.v ../../techlibs/xilinx/cells_sim.v +vvp -N ./test_macc diff --git a/tests/xilinx/macc_tb.v b/tests/xilinx/macc_tb.v new file mode 100644 index 000000000..64aed05c4 --- /dev/null +++ b/tests/xilinx/macc_tb.v @@ -0,0 +1,96 @@ +`timescale 1ns / 1ps + +module testbench; + + parameter SIZEIN = 16, SIZEOUT = 40; + reg clk, ce, rst; + reg signed [SIZEIN-1:0] a, b; + output signed [SIZEOUT-1:0] REF_accum_out, accum_out; + output REF_overflow, overflow; + + integer errcount = 0; + + reg ERROR_FLAG = 0; + + task clkcycle; + begin + #5; + clk = ~clk; + #10; + clk = ~clk; + #2; + ERROR_FLAG = 0; + if (REF_accum_out !== accum_out) begin + $display("ERROR at %1t: REF_accum_out=%b UUT_accum_out=%b DIFF=%b", $time, REF_accum_out, accum_out, REF_accum_out ^ accum_out); + errcount = errcount + 1; + ERROR_FLAG = 1; + end + if (REF_overflow !== overflow) begin + $display("ERROR at %1t: REF_overflow=%b UUT_overflow=%b DIFF=%b", $time, REF_overflow, overflow, REF_overflow ^ overflow); + errcount = errcount + 1; + ERROR_FLAG = 1; + end + #3; + end + endtask + + initial begin + //$dumpfile("test_macc.vcd"); + //$dumpvars(0, testbench); + + #2; + clk = 1'b0; + ce = 1'b0; + a = 0; + b = 0; + + rst = 1'b1; + repeat (10) begin + #10; + clk = 1'b1; + #10; + clk = 1'b0; + #10; + clk = 1'b1; + #10; + clk = 1'b0; + end + rst = 1'b0; + + repeat (10000) begin + clkcycle; + ce = 1; //$urandom & $urandom; + //rst = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom; + a = $urandom & ~(1 << (SIZEIN-1)); + b = $urandom & ~(1 << (SIZEIN-1)); + end + + if (errcount == 0) begin + $display("All tests passed."); + $finish; + end else begin + $display("Caught %1d errors.", errcount); + $stop; + end + end + + macc2 ref ( + .clk(clk), + .ce(ce), + .rst(rst), + .a(a), + .b(b), + .accum_out(REF_accum_out), + .overflow(REF_overflow) + ); + + macc2_uut uut ( + .clk(clk), + .ce(ce), + .rst(rst), + .a(a), + .b(b), + .accum_out(accum_out), + .overflow(overflow) + ); +endmodule From c83a66755553f47f40c591110e6bdcd722360d6c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 18:08:46 -0700 Subject: [PATCH 281/356] Fix width of D --- passes/pmgen/xilinx_dsp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 3cfaa9371..adc09a6e4 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -48,7 +48,7 @@ static Cell* addDsp(Module *module) { cell->setParam(ID(USE_SIMD), Const("ONE48")); cell->setParam(ID(USE_DPORT), Const("FALSE")); - cell->setPort(ID(D), Const(0, 24)); + cell->setPort(ID(D), Const(0, 25)); cell->setPort(ID(INMODE), Const(0, 5)); cell->setPort(ID(ALUMODE), Const(0, 4)); cell->setPort(ID(OPMODE), Const(0, 7)); From 41256f48a5f3231e231cbdf9380a26128f272044 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 18:33:29 -0700 Subject: [PATCH 282/356] Different approach to timing --- techlibs/xilinx/abc_map.v | 147 ++++++++------- techlibs/xilinx/abc_model.v | 105 ++++++----- techlibs/xilinx/abc_unmap.v | 4 +- techlibs/xilinx/abc_xc7.box | 350 ++++++------------------------------ 4 files changed, 198 insertions(+), 408 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 1b7900af8..124ce6d8f 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -299,49 +299,60 @@ __CELL__ #( wire [47:0] iC; wire [24:0] iD; - wire pA, pB, pC, pD, pAD, pM, pP; + wire pAP, pBP, pCP, pDP, pADP, pMP, pPP; + wire pAPCOUT, pBPCOUT, pCPCOUT, pDPCOUT, pADPCOUT, pMPCOUT, pPPCOUT; wire [47:0] oP, oPCOUT; - // Disconnect the A-input if MREG is enabled, since - // combinatorial path is broken + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken if (AREG == 0 && MREG == 0 && PREG == 0) - assign iA = A, pA = 1'bx; + assign iA = A, pAP = 1'bx, pAPCOUT = 1'bx; else - \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); + \$__ABC_DSP48E1_MULT_AREG rA (.I(A), .O(iA), .P(pAP), .PCOUT(pAPCOUT)); if (BREG == 0 && MREG == 0 && PREG == 0) - assign iB = B, pB = 1'bx; + assign iB = B, pBP = 1'bx, pBPCOUT = 1'bx; else - \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); + \$__ABC_DSP48E1_MULT_BREG rB (.I(B), .O(iB), .P(pBP), .PCOUT(pBPCOUT)); if (CREG == 0 && PREG == 0) - assign iC = C, pC = 1'bx; + assign iC = C, pCP = 1'bx, pCPCOUT = 1'bx; else - \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); + \$__ABC_DSP48E1_MULT_CREG rC (.I(C), .O(iC), .P(pCP), .PCOUT(pCPCOUT)); if (DREG == 0) assign iD = D; else if (techmap_guard) - $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); - assign pD = 1'bx; + $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + assign pDP = 1'bx, pDPCOUT = 1'bx; if (ADREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); - assign pAD = 1'bx; + assign pADP = 1'bx, pADPCOUT = 1'bx; if (PREG == 0) begin - assign pP = 1'bx; if (MREG == 1) - \$__ABC_DSP48E1_REG rM (.Q(pM)); + \$__ABC_DSP48E1_MULT_MREG rM (.P(pMP), .PCOUT(pMPCOUT)); else - assign pM = 1'bx; + assign pMP = 1'bx, pMPCOUT = 1'bx; + assign pPP = 1'bx, pPPCOUT = 1'bx; end else begin - \$__ABC_DSP48E1_REG rP (.Q(pP)); - assign pM = 1'bx; + assign pMP = 1'bx, pMPCOUT = 1'bx; + \$__ABC_DSP48E1_MULT_PREG rP (.P(pPP), .PCOUT(pPPCOUT)); end - \$__ABC_DSP48E1_MULT_P_MUX muxP ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) - ); - \$__ABC_DSP48E1_MULT_PCOUT_MUX muxPCOUT ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) - ); + if (MREG == 0 && PREG == 0) begin + \$__ABC_DSP48E1_MUX muxP ( + .Aq(pAP), .Bq(pBP), .Cq(pCP), .Dq(pDP), .ADq(pADP), .Mq(pMP), .P(oP), .Pq(pPP), .O(P) + ); + \$__ABC_DSP48E1_MUX muxPCOUT ( + .Aq(pAPCOUT), .Bq(pBPCOUT), .Cq(pCPCOUT), .Dq(pDPCOUT), .ADq(pADPCOUT), .Mq(pMPCOUT), .P(oPCOUT), .Pq(pPPCOUT), .O(PCOUT) + ); + end + else begin + \$__ABC_DSP48E1_MUX muxP ( + .Aq(pAP), .Bq(pBP), .Cq(pCP), .Dq(pDP), .ADq(pADP), .Mq(pMP), .P(1'bx), .Pq(pPP), .O(P) + ); + \$__ABC_DSP48E1_MUX muxPCOUT ( + .Aq(pAPCOUT), .Bq(pBPCOUT), .Cq(pCPCOUT), .Dq(pDPCOUT), .ADq(pADPCOUT), .Mq(pMPCOUT), .P(1'bx), .Pq(pPPCOUT), .O(PCOUT) + ); + end `DSP48E1_INST(\$__ABC_DSP48E1_MULT ) end @@ -351,46 +362,53 @@ __CELL__ #( wire [47:0] iC; wire [24:0] iD; - wire pA, pB, pC, pD, pAD, pM, pP; + wire pAP, pBP, pCP, pDP, pADP, pMP, pPP; + wire pAPCOUT, pBPCOUT, pCPCOUT, pDPCOUT, pADPCOUT, pMPCOUT, pPPCOUT; wire [47:0] oP, oPCOUT; // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0) - assign iA = A, pA = 1'bx; + assign iA = A, pAP = 1'bx, pAPCOUT = 1'bx; else - \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); + \$__ABC_DSP48E1_MULT_DPORT_AREG rA (.I(A), .O(iA), .P(pAP), .PCOUT(pAPCOUT)); if (BREG == 0 && MREG == 0 && PREG == 0) - assign iB = B, pB = 1'bx; + assign iB = B, pBP = 1'bx, pBPCOUT = 1'bx; else - \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); + \$__ABC_DSP48E1_MULT_DPORT_BREG rB (.I(B), .O(iB), .P(pBP), .PCOUT(pBPCOUT)); if (CREG == 0 && PREG == 0) - assign iC = C, pC = 1'bx; + assign iC = C, pCP = 1'bx, pCPCOUT = 1'bx; else - \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); + \$__ABC_DSP48E1_MULT_DPORT_CREG rC (.I(C), .O(iC), .P(pCP), .PCOUT(pCPCOUT)); if (DREG == 0 && ADREG == 0) - assign iD = D, pD = 1'bx; + assign iD = D, pDP = 1'bx, pDPCOUT = 1'bx; else - \$__ABC_DSP48E1_REG rD (.I(D), .O(iD), .Q(pD)); + \$__ABC_DSP48E1_MULT_DPORT_DREG rD (.I(D), .O(iD), .P(pDP), .PCOUT(pDPCOUT)); if (PREG == 0) begin - if (MREG == 1) - \$__ABC_DSP48E1_REG rM (.Q(pM)); - else begin - assign pM = 1'bx; - if (ADREG == 1) - \$__ABC_DSP48E1_REG rAD (.Q(pAD)); - else - assign pAD = 1'bx; + if (MREG == 1) begin + assign pADP = 1'bx, pADPCOUT = 1'bx; + \$__ABC_DSP48E1_MULT_DPORT_MREG rM (.P(pMP), .PCOUT(pMPCOUT)); end + else begin + if (ADREG == 1) + \$__ABC_DSP48E1_MULT_DPORT_ADPREG rAD (.P(pADP), .PCOUT(pADPCOUT)); + else + assign pADP = 1'bx, pADPCOUT = 1'bx; + assign pMP = 1'bx, pMPCOUT = 1'bx; + end + assign pPP = 1'bx, pPPCOUT = 1'bx; end - else - \$__ABC_DSP48E1_REG rP (.Q(pP)); + else begin + assign pADP = 1'bx, pADPCOUT = 1'bx; + assign pMP = 1'bx, pMPCOUT = 1'bx; + \$__ABC_DSP48E1_MULT_DPORT_PREG rP (.P(pPP), .PCOUT(pPPCOUT)); + end - \$__ABC_DSP48E1_MULT_DPORT_P_MUX muxP ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) + \$__ABC_DSP48E1_MUX muxP ( + .Aq(pAP), .Bq(pBP), .Cq(pCP), .Dq(pDP), .ADq(pADP), .Mq(pMP), .P(oP), .Pq(pPP), .O(P) ); - \$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) + \$__ABC_DSP48E1_MUX muxPCOUT ( + .Aq(pAPCOUT), .Bq(pBPCOUT), .Cq(pCPCOUT), .Dq(pDPCOUT), .ADq(pADPCOUT), .Mq(pMPCOUT), .P(oPCOUT), .Pq(pPPCOUT), .O(PCOUT) ); `DSP48E1_INST(\$__ABC_DSP48E1_MULT_DPORT ) @@ -401,42 +419,43 @@ __CELL__ #( wire [47:0] iC; wire [24:0] iD; - wire pA, pB, pC, pD, pAD, pM, pP; + wire pAP, pBP, pCP, pDP, pADP, pMP, pPP; + wire pAPCOUT, pBPCOUT, pCPCOUT, pDPCOUT, pADPCOUT, pMPCOUT, pPPCOUT; wire [47:0] oP, oPCOUT; // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && PREG == 0) - assign iA = A, pA = 1'bx; + assign iA = A, pAP = 1'bx, pAPCOUT = 1'bx; else - \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); + \$__ABC_DSP48E1_AREG rA (.I(A), .O(iA), .P(pAP), .PCOUT(pAPCOUT)); if (BREG == 0 && PREG == 0) - assign iB = B, pB = 1'bx; + assign iB = B, pBP = 1'bx, pBPCOUT = 1'bx; else - \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); + \$__ABC_DSP48E1_BREG rB (.I(B), .O(iB), .P(pB), .PCOUT(pBPCOUT)); if (CREG == 0 && PREG == 0) - assign iC = C, pC = 1'bx; + assign iC = C, pCP = 1'bx, pCPCOUT = 1'bx; else - \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); - if (MREG == 1 && techmap_guard) - $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\""); - assign pM = 1'bx; + \$__ABC_DSP48E1_CREG rC (.I(C), .O(iC), .P(pC), .PCOUT(pCPCOUT)); if (DREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); - assign pD = 1'bx; + assign iD = 25'bx, pDP = 1'bx, pDPCOUT = 1'bx; if (ADREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); - assign pAD = 1'bx; + assign pADP = 1'bx, pADPCOUT = 1'bx; + if (MREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\""); + assign pMP = 1'bx, pMPCOUT = 1'bx; if (PREG == 1) - \$__ABC_DSP48E1_REG rP (.Q(pP)); + \$__ABC_DSP48E1_PREG rP (.P(pPP), .P(pPCOUT)); else - assign pP = 1'bx; + assign pPP = 1'bx, pPPCOUT = 1'bx; - \$__ABC_DSP48E1_P_MUX muxP ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) + \$__ABC_DSP48E1_MUX muxP ( + .Aq(pAP), .Bq(pBP), .Cq(pCP), .Dq(pDP), .ADq(pADP), .Mq(pMP), .P(oP), .Pq(pPP), .O(P) ); - \$__ABC_DSP48E1_PCOUT_MUX muxPCOUT ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) + \$__ABC_DSP48E1_MUX muxPCOUT ( + .Aq(pAPCOUT), .Bq(pBPCOUT), .Cq(pCPCOUT), .Dq(pDPCOUT), .ADq(pADPCOUT), .Mq(pMPCOUT), .P(oPCOUT), .Pq(pPPCOUT), .O(PCOUT) ); `DSP48E1_INST(\$__ABC_DSP48E1 ) diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index a8f6deafc..79cca6b7b 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -44,48 +44,6 @@ endmodule module \$__ABC_LUT7 (input A, input [6:0] S, output Y); endmodule -// Boxes used to represent the comb/seq behaviour of DSP48E1 -// With abc_map.v responsible for disconnecting inputs to -// the combinatorial DSP48E1 model by a register (e.g. -// disconnecting A when AREG, MREG or PREG is enabled) -// this blackbox captures the existence of a replacement -// path between AREG/BREG/CREG/etc. and P/PCOUT. -// Since the Aq/ADq/Bq/etc. inputs are assumed to arrive at -// the box at zero time, the combinatorial delay through -// these boxes thus represents the clock-to-q delay -// (arrival time) at P/PCOUT. -// Doing so should means that ABC is able to analyse the -// worst-case delay through to P, regardless of if it was -// through any combinatorial paths (e.g. B, below) or an -// internal register (A2REG). -// However, the true value of being as complete as this is -// questionable since if AREG=1 and BREG=0 (as below) -// then the worse-case path would very likely be through B -// and very unlikely to be through AREG.Q...? -// -// In graphical form: -// -// NEW "PI" >>---+ -// for AREG.Q | -// | -// +---------+ | __ -// A >>--X X-| | +--| \ -// | DSP48E1 |P | |--->> P -// | AREG=1 |-------|__/ -// B >>------| | -// +---------+ -// -`define ABC_DSP48E1_MUX(__NAME__) """ -module __NAME__ (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); -endmodule -""" -(* abc_box_id=2100 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_P_MUX ) -(* abc_box_id=2101 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_PCOUT_MUX ) -(* abc_box_id=2102 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_DPORT_P_MUX ) -(* abc_box_id=2103 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX ) -(* abc_box_id=2104 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_P_MUX ) -(* abc_box_id=2105 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_PCOUT_MUX ) - `define ABC_DSP48E1(__NAME__) """ module \$__ABC_DSP48E1_MULT ( output [29:0] ACOUT, @@ -173,3 +131,66 @@ endmodule (* abc_box_id=3000 *) `ABC_DSP48E1(\$__ABC_DSP48E1_MULT ) (* abc_box_id=3001 *) `ABC_DSP48E1(\$__ABC_DSP48E1_MULT_DPORT ) (* abc_box_id=3002 *) `ABC_DSP48E1(\$__ABC_DSP48E1 ) + + +// Modules used to model the comb/seq behaviour of DSP48E1 +// With abc_map.v responsible for splicing the below modules +// into between the combinatorial DSP48E1 box (e.g. disconnecting +// A when AREG, MREG or PREG is enabled and splicing in the +// "$__ABC_DSP48E1_MULT_AREG" blackbox as "REG" in the diagram +// below) this acts to first disables the combinatorial path +// (as there is no connectivity through REG), and secondly, +// since this is blackbox a new PI will be introduced, one which +// will have the relevant arrival time (corresponding to delay from +// AREG to P) attached. +// Note: Since these "$__ABC_DSP48E1*_*REG" modules are of a +// sequential nature, they are not passed as a box to ABC./ +// +// On the other hand, the "$__ABC_DSP48E1_MUX" is a combinatorial +// blackbox that is passed to ABC, with zero delay. +// +// Doing so should means that ABC is able to analyse the +// worst-case delay through to P, regardless of if it was +// through any combinatorial paths (e.g. B, below) or an +// internal register (A2REG). +// However, the true value of being as complete as this is +// questionable since if AREG=1 and BREG=0 (as below) +// then the worse-case path would very likely be through B +// and very unlikely to be through AREG.Q...? +// +// In graphical form: +// +// +-----+ +// +-------| REG |-----+ +// | +-----+ | +// | | +// | +---------+ | __ +// A >>-+X X-| | +--| \ +// | DSP48E1 |P | M |--->> P +// | AREG=1 |-------|__/ +// B >>------| | +// +---------+ +// + +(* abc_box_id=2100 *) +module \$__ABC_DSP48E1_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); +endmodule + +module $__ABC_DSP48E1_MULT_AREG (input [29:0] I, output [29:0] O, (* abc_arrival=2952 *) output P, (* abc_arrival=3098 *) output PCOUT); endmodule +module $__ABC_DSP48E1_MULT_BREG (input [17:0] I, output [17:0] O, (* abc_arrival=2813 *) output P, (* abc_arrival=2960 *) output PCOUT); endmodule +module $__ABC_DSP48E1_MULT_CREG (input [47:0] I, output [47:0] O, (* abc_arrival=1687 *) output P, (* abc_arrival=1835 *) output PCOUT); endmodule +module $__ABC_DSP48E1_MULT_MREG (input [47:0] I, output [47:0] O, (* abc_arrival=1671 *) output P, (* abc_arrival=1819 *) output PCOUT); endmodule +module $__ABC_DSP48E1_MULT_PREG (input [47:0] I, output [47:0] O, (* abc_arrival= 329 *) output P, (* abc_arrival= 435 *) output PCOUT); endmodule + +module $__ABC_DSP48E1_MULT_DPORT_AREG (input [29:0] I, output [29:0] O, (* abc_arrival=3935 *) output P, (* abc_arrival=4083 *) output PCOUT); endmodule +module $__ABC_DSP48E1_MULT_DPORT_BREG (input [17:0] I, output [17:0] O, (* abc_arrival=2813 *) output P, (* abc_arrival=2960 *) output PCOUT); endmodule +module $__ABC_DSP48E1_MULT_DPORT_CREG (input [47:0] I, output [47:0] O, (* abc_arrival=1687 *) output P, (* abc_arrival=1835 *) output PCOUT); endmodule +module $__ABC_DSP48E1_MULT_DPORT_DREG (input [47:0] I, output [47:0] O, (* abc_arrival=3908 *) output P, (* abc_arrival=4056 *) output PCOUT); endmodule +module $__ABC_DSP48E1_MULT_DPORT_ADREG (input [47:0] I, output [47:0] O, (* abc_arrival=2958 *) output P, (* abc_arrival=2859 *) output PCOUT); endmodule +module $__ABC_DSP48E1_MULT_DPORT_MREG (input [47:0] I, output [47:0] O, (* abc_arrival=1671 *) output P, (* abc_arrival=1819 *) output PCOUT); endmodule +module $__ABC_DSP48E1_MULT_DPORT_PREG (input [47:0] I, output [47:0] O, (* abc_arrival= 329 *) output P, (* abc_arrival= 435 *) output PCOUT); endmodule + +module $__ABC_DSP48E1_AREG (input [29:0] I, output [29:0] O, (* abc_arrival=1632 *) output P, (* abc_arrival=1780 *) output PCOUT); endmodule +module $__ABC_DSP48E1_BREG (input [17:0] I, output [17:0] O, (* abc_arrival=1616 *) output P, (* abc_arrival=1765 *) output PCOUT); endmodule +module $__ABC_DSP48E1_CREG (input [47:0] I, output [47:0] O, (* abc_arrival=1687 *) output P, (* abc_arrival=1835 *) output PCOUT); endmodule +module $__ABC_DSP48E1_PREG (input [47:0] I, output [47:0] O, (* abc_arrival= 329 *) output P, (* abc_arrival= 435 *) output PCOUT); endmodule diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index 010041b73..8700393ab 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -27,10 +27,10 @@ module \$__ABC_LUT7 (input A, input [6:0] S, output Y); assign Y = A; endmodule -module \$__ABC_DSP48E1_REG (input [47:0] I, output [47:0] O, output Q); +(* techmap_celltype = "$__ABC_DSP48E1_MULT_AREG $__ABC_DSP48E1_MULT_BREG $__ABC_DSP48E1_MULT_CREG $__ABC_DSP48E1_MULT_MREG $__ABC_DSP48E1_MULT_PREG $__ABC_DSP48E1_MULT_DPORT_AREG $__ABC_DSP48E1_MULT_DPORT_BREG $__ABC_DSP48E1_MULT_DPORT_CREG $__ABC_DSP48E1_MULT_DPORT_DREG $__ABC_DSP48E1_MULT_DPORT_ADREG $__ABC_DSP48E1_MULT_DPORT_MREG $__ABC_DSP48E1_MULT_DPORT_PREG " *) +module \$__ABC_DSP48E1_REG (input [47:0] I, output [47:0] O, output P, PCOUT); assign O = I; endmodule -(* techmap_celltype = "$__ABC_DSP48E1_MULT_P_MUX $__ABC_DSP48E1_MULT_PCOUT_MUX $__ABC_DSP48E1_MULT_DPORT_P_MUX $__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX $__ABC_DSP48E1_P_MUX $__ABC_DSP48E1_PCOUT_MUX" *) module \$__ABC_DSP48E1_MUX ( input Aq, Bq, Cq, Dq, ADq, Mq, input [47:0] P, diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 79b400d40..ff4f87a0a 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -70,306 +70,56 @@ $__ABC_LUT7 2001 0 8 1 # the mux at zero time, the combinatorial delay through # these muxes thus represents the clock-to-q delay at # P/PCOUT. -$__ABC_DSP48E1_MULT_P_MUX 2100 0 55 48 -# A AD B C D M P Pq -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -$__ABC_DSP48E1_MULT_PCOUT_MUX 2101 0 55 48 -# A AD B C D M P Pq -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -$__ABC_DSP48E1_MULT_DPORT_P_MUX 2102 0 55 48 -# A AD B C D M P Pq -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 55 48 -# A AD B C D M P Pq -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -$__ABC_DSP48E1_P_MUX 2104 0 55 48 -# A AD B C D M P Pq -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -$__ABC_DSP48E1_PCOUT_MUX 2105 0 55 48 -# A AD B C D M P Pq -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +$__ABC_DSP48E1_MUX 2100 0 55 48 +#A AD B C D M P Pq +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 $__ABC_DSP48E1_MULT 3000 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - From 362a803779ac1a8a3af1e4991b80b0c4c71e02ff Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 18:33:38 -0700 Subject: [PATCH 283/356] Revert "Different approach to timing" This reverts commit 41256f48a5f3231e231cbdf9380a26128f272044. --- techlibs/xilinx/abc_map.v | 145 +++++++-------- techlibs/xilinx/abc_model.v | 105 +++++------ techlibs/xilinx/abc_unmap.v | 4 +- techlibs/xilinx/abc_xc7.box | 350 ++++++++++++++++++++++++++++++------ 4 files changed, 407 insertions(+), 197 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 124ce6d8f..1b7900af8 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -299,60 +299,49 @@ __CELL__ #( wire [47:0] iC; wire [24:0] iD; - wire pAP, pBP, pCP, pDP, pADP, pMP, pPP; - wire pAPCOUT, pBPCOUT, pCPCOUT, pDPCOUT, pADPCOUT, pMPCOUT, pPPCOUT; + wire pA, pB, pC, pD, pAD, pM, pP; wire [47:0] oP, oPCOUT; - // Disconnect the A-input if MREG is enabled, since - // combinatorial path is broken + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken if (AREG == 0 && MREG == 0 && PREG == 0) - assign iA = A, pAP = 1'bx, pAPCOUT = 1'bx; + assign iA = A, pA = 1'bx; else - \$__ABC_DSP48E1_MULT_AREG rA (.I(A), .O(iA), .P(pAP), .PCOUT(pAPCOUT)); + \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && MREG == 0 && PREG == 0) - assign iB = B, pBP = 1'bx, pBPCOUT = 1'bx; + assign iB = B, pB = 1'bx; else - \$__ABC_DSP48E1_MULT_BREG rB (.I(B), .O(iB), .P(pBP), .PCOUT(pBPCOUT)); + \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) - assign iC = C, pCP = 1'bx, pCPCOUT = 1'bx; + assign iC = C, pC = 1'bx; else - \$__ABC_DSP48E1_MULT_CREG rC (.I(C), .O(iC), .P(pCP), .PCOUT(pCPCOUT)); + \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0) assign iD = D; else if (techmap_guard) - $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); - assign pDP = 1'bx, pDPCOUT = 1'bx; + $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + assign pD = 1'bx; if (ADREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); - assign pADP = 1'bx, pADPCOUT = 1'bx; + assign pAD = 1'bx; if (PREG == 0) begin + assign pP = 1'bx; if (MREG == 1) - \$__ABC_DSP48E1_MULT_MREG rM (.P(pMP), .PCOUT(pMPCOUT)); + \$__ABC_DSP48E1_REG rM (.Q(pM)); else - assign pMP = 1'bx, pMPCOUT = 1'bx; - assign pPP = 1'bx, pPPCOUT = 1'bx; + assign pM = 1'bx; end else begin - assign pMP = 1'bx, pMPCOUT = 1'bx; - \$__ABC_DSP48E1_MULT_PREG rP (.P(pPP), .PCOUT(pPPCOUT)); + \$__ABC_DSP48E1_REG rP (.Q(pP)); + assign pM = 1'bx; end - if (MREG == 0 && PREG == 0) begin - \$__ABC_DSP48E1_MUX muxP ( - .Aq(pAP), .Bq(pBP), .Cq(pCP), .Dq(pDP), .ADq(pADP), .Mq(pMP), .P(oP), .Pq(pPP), .O(P) - ); - \$__ABC_DSP48E1_MUX muxPCOUT ( - .Aq(pAPCOUT), .Bq(pBPCOUT), .Cq(pCPCOUT), .Dq(pDPCOUT), .ADq(pADPCOUT), .Mq(pMPCOUT), .P(oPCOUT), .Pq(pPPCOUT), .O(PCOUT) - ); - end - else begin - \$__ABC_DSP48E1_MUX muxP ( - .Aq(pAP), .Bq(pBP), .Cq(pCP), .Dq(pDP), .ADq(pADP), .Mq(pMP), .P(1'bx), .Pq(pPP), .O(P) - ); - \$__ABC_DSP48E1_MUX muxPCOUT ( - .Aq(pAPCOUT), .Bq(pBPCOUT), .Cq(pCPCOUT), .Dq(pDPCOUT), .ADq(pADPCOUT), .Mq(pMPCOUT), .P(1'bx), .Pq(pPPCOUT), .O(PCOUT) - ); - end + \$__ABC_DSP48E1_MULT_P_MUX muxP ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) + ); + \$__ABC_DSP48E1_MULT_PCOUT_MUX muxPCOUT ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) + ); `DSP48E1_INST(\$__ABC_DSP48E1_MULT ) end @@ -362,53 +351,46 @@ __CELL__ #( wire [47:0] iC; wire [24:0] iD; - wire pAP, pBP, pCP, pDP, pADP, pMP, pPP; - wire pAPCOUT, pBPCOUT, pCPCOUT, pDPCOUT, pADPCOUT, pMPCOUT, pPPCOUT; + wire pA, pB, pC, pD, pAD, pM, pP; wire [47:0] oP, oPCOUT; // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0) - assign iA = A, pAP = 1'bx, pAPCOUT = 1'bx; + assign iA = A, pA = 1'bx; else - \$__ABC_DSP48E1_MULT_DPORT_AREG rA (.I(A), .O(iA), .P(pAP), .PCOUT(pAPCOUT)); + \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && MREG == 0 && PREG == 0) - assign iB = B, pBP = 1'bx, pBPCOUT = 1'bx; + assign iB = B, pB = 1'bx; else - \$__ABC_DSP48E1_MULT_DPORT_BREG rB (.I(B), .O(iB), .P(pBP), .PCOUT(pBPCOUT)); + \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) - assign iC = C, pCP = 1'bx, pCPCOUT = 1'bx; + assign iC = C, pC = 1'bx; else - \$__ABC_DSP48E1_MULT_DPORT_CREG rC (.I(C), .O(iC), .P(pCP), .PCOUT(pCPCOUT)); + \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0 && ADREG == 0) - assign iD = D, pDP = 1'bx, pDPCOUT = 1'bx; + assign iD = D, pD = 1'bx; else - \$__ABC_DSP48E1_MULT_DPORT_DREG rD (.I(D), .O(iD), .P(pDP), .PCOUT(pDPCOUT)); + \$__ABC_DSP48E1_REG rD (.I(D), .O(iD), .Q(pD)); if (PREG == 0) begin - if (MREG == 1) begin - assign pADP = 1'bx, pADPCOUT = 1'bx; - \$__ABC_DSP48E1_MULT_DPORT_MREG rM (.P(pMP), .PCOUT(pMPCOUT)); - end + if (MREG == 1) + \$__ABC_DSP48E1_REG rM (.Q(pM)); else begin + assign pM = 1'bx; if (ADREG == 1) - \$__ABC_DSP48E1_MULT_DPORT_ADPREG rAD (.P(pADP), .PCOUT(pADPCOUT)); + \$__ABC_DSP48E1_REG rAD (.Q(pAD)); else - assign pADP = 1'bx, pADPCOUT = 1'bx; - assign pMP = 1'bx, pMPCOUT = 1'bx; + assign pAD = 1'bx; end - assign pPP = 1'bx, pPPCOUT = 1'bx; end - else begin - assign pADP = 1'bx, pADPCOUT = 1'bx; - assign pMP = 1'bx, pMPCOUT = 1'bx; - \$__ABC_DSP48E1_MULT_DPORT_PREG rP (.P(pPP), .PCOUT(pPPCOUT)); - end + else + \$__ABC_DSP48E1_REG rP (.Q(pP)); - \$__ABC_DSP48E1_MUX muxP ( - .Aq(pAP), .Bq(pBP), .Cq(pCP), .Dq(pDP), .ADq(pADP), .Mq(pMP), .P(oP), .Pq(pPP), .O(P) + \$__ABC_DSP48E1_MULT_DPORT_P_MUX muxP ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) ); - \$__ABC_DSP48E1_MUX muxPCOUT ( - .Aq(pAPCOUT), .Bq(pBPCOUT), .Cq(pCPCOUT), .Dq(pDPCOUT), .ADq(pADPCOUT), .Mq(pMPCOUT), .P(oPCOUT), .Pq(pPPCOUT), .O(PCOUT) + \$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) ); `DSP48E1_INST(\$__ABC_DSP48E1_MULT_DPORT ) @@ -419,43 +401,42 @@ __CELL__ #( wire [47:0] iC; wire [24:0] iD; - wire pAP, pBP, pCP, pDP, pADP, pMP, pPP; - wire pAPCOUT, pBPCOUT, pCPCOUT, pDPCOUT, pADPCOUT, pMPCOUT, pPPCOUT; + wire pA, pB, pC, pD, pAD, pM, pP; wire [47:0] oP, oPCOUT; // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && PREG == 0) - assign iA = A, pAP = 1'bx, pAPCOUT = 1'bx; + assign iA = A, pA = 1'bx; else - \$__ABC_DSP48E1_AREG rA (.I(A), .O(iA), .P(pAP), .PCOUT(pAPCOUT)); + \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && PREG == 0) - assign iB = B, pBP = 1'bx, pBPCOUT = 1'bx; + assign iB = B, pB = 1'bx; else - \$__ABC_DSP48E1_BREG rB (.I(B), .O(iB), .P(pB), .PCOUT(pBPCOUT)); + \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) - assign iC = C, pCP = 1'bx, pCPCOUT = 1'bx; + assign iC = C, pC = 1'bx; else - \$__ABC_DSP48E1_CREG rC (.I(C), .O(iC), .P(pC), .PCOUT(pCPCOUT)); - if (DREG == 1 && techmap_guard) - $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); - assign iD = 25'bx, pDP = 1'bx, pDPCOUT = 1'bx; - if (ADREG == 1 && techmap_guard) - $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); - assign pADP = 1'bx, pADPCOUT = 1'bx; + \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); if (MREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\""); - assign pMP = 1'bx, pMPCOUT = 1'bx; + assign pM = 1'bx; + if (DREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + assign pD = 1'bx; + if (ADREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); + assign pAD = 1'bx; if (PREG == 1) - \$__ABC_DSP48E1_PREG rP (.P(pPP), .P(pPCOUT)); + \$__ABC_DSP48E1_REG rP (.Q(pP)); else - assign pPP = 1'bx, pPPCOUT = 1'bx; + assign pP = 1'bx; - \$__ABC_DSP48E1_MUX muxP ( - .Aq(pAP), .Bq(pBP), .Cq(pCP), .Dq(pDP), .ADq(pADP), .Mq(pMP), .P(oP), .Pq(pPP), .O(P) + \$__ABC_DSP48E1_P_MUX muxP ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) ); - \$__ABC_DSP48E1_MUX muxPCOUT ( - .Aq(pAPCOUT), .Bq(pBPCOUT), .Cq(pCPCOUT), .Dq(pDPCOUT), .ADq(pADPCOUT), .Mq(pMPCOUT), .P(oPCOUT), .Pq(pPPCOUT), .O(PCOUT) + \$__ABC_DSP48E1_PCOUT_MUX muxPCOUT ( + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) ); `DSP48E1_INST(\$__ABC_DSP48E1 ) diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index 79cca6b7b..a8f6deafc 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -44,6 +44,48 @@ endmodule module \$__ABC_LUT7 (input A, input [6:0] S, output Y); endmodule +// Boxes used to represent the comb/seq behaviour of DSP48E1 +// With abc_map.v responsible for disconnecting inputs to +// the combinatorial DSP48E1 model by a register (e.g. +// disconnecting A when AREG, MREG or PREG is enabled) +// this blackbox captures the existence of a replacement +// path between AREG/BREG/CREG/etc. and P/PCOUT. +// Since the Aq/ADq/Bq/etc. inputs are assumed to arrive at +// the box at zero time, the combinatorial delay through +// these boxes thus represents the clock-to-q delay +// (arrival time) at P/PCOUT. +// Doing so should means that ABC is able to analyse the +// worst-case delay through to P, regardless of if it was +// through any combinatorial paths (e.g. B, below) or an +// internal register (A2REG). +// However, the true value of being as complete as this is +// questionable since if AREG=1 and BREG=0 (as below) +// then the worse-case path would very likely be through B +// and very unlikely to be through AREG.Q...? +// +// In graphical form: +// +// NEW "PI" >>---+ +// for AREG.Q | +// | +// +---------+ | __ +// A >>--X X-| | +--| \ +// | DSP48E1 |P | |--->> P +// | AREG=1 |-------|__/ +// B >>------| | +// +---------+ +// +`define ABC_DSP48E1_MUX(__NAME__) """ +module __NAME__ (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); +endmodule +""" +(* abc_box_id=2100 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_P_MUX ) +(* abc_box_id=2101 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_PCOUT_MUX ) +(* abc_box_id=2102 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_DPORT_P_MUX ) +(* abc_box_id=2103 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX ) +(* abc_box_id=2104 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_P_MUX ) +(* abc_box_id=2105 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_PCOUT_MUX ) + `define ABC_DSP48E1(__NAME__) """ module \$__ABC_DSP48E1_MULT ( output [29:0] ACOUT, @@ -131,66 +173,3 @@ endmodule (* abc_box_id=3000 *) `ABC_DSP48E1(\$__ABC_DSP48E1_MULT ) (* abc_box_id=3001 *) `ABC_DSP48E1(\$__ABC_DSP48E1_MULT_DPORT ) (* abc_box_id=3002 *) `ABC_DSP48E1(\$__ABC_DSP48E1 ) - - -// Modules used to model the comb/seq behaviour of DSP48E1 -// With abc_map.v responsible for splicing the below modules -// into between the combinatorial DSP48E1 box (e.g. disconnecting -// A when AREG, MREG or PREG is enabled and splicing in the -// "$__ABC_DSP48E1_MULT_AREG" blackbox as "REG" in the diagram -// below) this acts to first disables the combinatorial path -// (as there is no connectivity through REG), and secondly, -// since this is blackbox a new PI will be introduced, one which -// will have the relevant arrival time (corresponding to delay from -// AREG to P) attached. -// Note: Since these "$__ABC_DSP48E1*_*REG" modules are of a -// sequential nature, they are not passed as a box to ABC./ -// -// On the other hand, the "$__ABC_DSP48E1_MUX" is a combinatorial -// blackbox that is passed to ABC, with zero delay. -// -// Doing so should means that ABC is able to analyse the -// worst-case delay through to P, regardless of if it was -// through any combinatorial paths (e.g. B, below) or an -// internal register (A2REG). -// However, the true value of being as complete as this is -// questionable since if AREG=1 and BREG=0 (as below) -// then the worse-case path would very likely be through B -// and very unlikely to be through AREG.Q...? -// -// In graphical form: -// -// +-----+ -// +-------| REG |-----+ -// | +-----+ | -// | | -// | +---------+ | __ -// A >>-+X X-| | +--| \ -// | DSP48E1 |P | M |--->> P -// | AREG=1 |-------|__/ -// B >>------| | -// +---------+ -// - -(* abc_box_id=2100 *) -module \$__ABC_DSP48E1_MUX (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); -endmodule - -module $__ABC_DSP48E1_MULT_AREG (input [29:0] I, output [29:0] O, (* abc_arrival=2952 *) output P, (* abc_arrival=3098 *) output PCOUT); endmodule -module $__ABC_DSP48E1_MULT_BREG (input [17:0] I, output [17:0] O, (* abc_arrival=2813 *) output P, (* abc_arrival=2960 *) output PCOUT); endmodule -module $__ABC_DSP48E1_MULT_CREG (input [47:0] I, output [47:0] O, (* abc_arrival=1687 *) output P, (* abc_arrival=1835 *) output PCOUT); endmodule -module $__ABC_DSP48E1_MULT_MREG (input [47:0] I, output [47:0] O, (* abc_arrival=1671 *) output P, (* abc_arrival=1819 *) output PCOUT); endmodule -module $__ABC_DSP48E1_MULT_PREG (input [47:0] I, output [47:0] O, (* abc_arrival= 329 *) output P, (* abc_arrival= 435 *) output PCOUT); endmodule - -module $__ABC_DSP48E1_MULT_DPORT_AREG (input [29:0] I, output [29:0] O, (* abc_arrival=3935 *) output P, (* abc_arrival=4083 *) output PCOUT); endmodule -module $__ABC_DSP48E1_MULT_DPORT_BREG (input [17:0] I, output [17:0] O, (* abc_arrival=2813 *) output P, (* abc_arrival=2960 *) output PCOUT); endmodule -module $__ABC_DSP48E1_MULT_DPORT_CREG (input [47:0] I, output [47:0] O, (* abc_arrival=1687 *) output P, (* abc_arrival=1835 *) output PCOUT); endmodule -module $__ABC_DSP48E1_MULT_DPORT_DREG (input [47:0] I, output [47:0] O, (* abc_arrival=3908 *) output P, (* abc_arrival=4056 *) output PCOUT); endmodule -module $__ABC_DSP48E1_MULT_DPORT_ADREG (input [47:0] I, output [47:0] O, (* abc_arrival=2958 *) output P, (* abc_arrival=2859 *) output PCOUT); endmodule -module $__ABC_DSP48E1_MULT_DPORT_MREG (input [47:0] I, output [47:0] O, (* abc_arrival=1671 *) output P, (* abc_arrival=1819 *) output PCOUT); endmodule -module $__ABC_DSP48E1_MULT_DPORT_PREG (input [47:0] I, output [47:0] O, (* abc_arrival= 329 *) output P, (* abc_arrival= 435 *) output PCOUT); endmodule - -module $__ABC_DSP48E1_AREG (input [29:0] I, output [29:0] O, (* abc_arrival=1632 *) output P, (* abc_arrival=1780 *) output PCOUT); endmodule -module $__ABC_DSP48E1_BREG (input [17:0] I, output [17:0] O, (* abc_arrival=1616 *) output P, (* abc_arrival=1765 *) output PCOUT); endmodule -module $__ABC_DSP48E1_CREG (input [47:0] I, output [47:0] O, (* abc_arrival=1687 *) output P, (* abc_arrival=1835 *) output PCOUT); endmodule -module $__ABC_DSP48E1_PREG (input [47:0] I, output [47:0] O, (* abc_arrival= 329 *) output P, (* abc_arrival= 435 *) output PCOUT); endmodule diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index 8700393ab..010041b73 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -27,10 +27,10 @@ module \$__ABC_LUT7 (input A, input [6:0] S, output Y); assign Y = A; endmodule -(* techmap_celltype = "$__ABC_DSP48E1_MULT_AREG $__ABC_DSP48E1_MULT_BREG $__ABC_DSP48E1_MULT_CREG $__ABC_DSP48E1_MULT_MREG $__ABC_DSP48E1_MULT_PREG $__ABC_DSP48E1_MULT_DPORT_AREG $__ABC_DSP48E1_MULT_DPORT_BREG $__ABC_DSP48E1_MULT_DPORT_CREG $__ABC_DSP48E1_MULT_DPORT_DREG $__ABC_DSP48E1_MULT_DPORT_ADREG $__ABC_DSP48E1_MULT_DPORT_MREG $__ABC_DSP48E1_MULT_DPORT_PREG " *) -module \$__ABC_DSP48E1_REG (input [47:0] I, output [47:0] O, output P, PCOUT); +module \$__ABC_DSP48E1_REG (input [47:0] I, output [47:0] O, output Q); assign O = I; endmodule +(* techmap_celltype = "$__ABC_DSP48E1_MULT_P_MUX $__ABC_DSP48E1_MULT_PCOUT_MUX $__ABC_DSP48E1_MULT_DPORT_P_MUX $__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX $__ABC_DSP48E1_P_MUX $__ABC_DSP48E1_PCOUT_MUX" *) module \$__ABC_DSP48E1_MUX ( input Aq, Bq, Cq, Dq, ADq, Mq, input [47:0] P, diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index ff4f87a0a..79b400d40 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -70,56 +70,306 @@ $__ABC_LUT7 2001 0 8 1 # the mux at zero time, the combinatorial delay through # these muxes thus represents the clock-to-q delay at # P/PCOUT. -$__ABC_DSP48E1_MUX 2100 0 55 48 -#A AD B C D M P Pq -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +$__ABC_DSP48E1_MULT_P_MUX 2100 0 55 48 +# A AD B C D M P Pq +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC_DSP48E1_MULT_PCOUT_MUX 2101 0 55 48 +# A AD B C D M P Pq +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +$__ABC_DSP48E1_MULT_DPORT_P_MUX 2102 0 55 48 +# A AD B C D M P Pq +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 55 48 +# A AD B C D M P Pq +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +$__ABC_DSP48E1_P_MUX 2104 0 55 48 +# A AD B C D M P Pq +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC_DSP48E1_PCOUT_MUX 2105 0 55 48 +# A AD B C D M P Pq +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 $__ABC_DSP48E1_MULT 3000 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - From e09f80479e6d16cf95c26e406bf06d81b94231f4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 18:59:28 -0700 Subject: [PATCH 284/356] Fix DSP48E1 timing by breaking P path if MREG or PREG --- techlibs/xilinx/abc_map.v | 57 ++-- techlibs/xilinx/abc_model.v | 49 ++- techlibs/xilinx/abc_unmap.v | 6 +- techlibs/xilinx/abc_xc7.box | 600 ++++++++++++++++++------------------ 4 files changed, 363 insertions(+), 349 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 1b7900af8..01307fcf2 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -292,16 +292,17 @@ __CELL__ #( ); """ + wire [29:0] iA; + wire [17:0] iB; + wire [47:0] iC; + wire [24:0] iD; + + wire pA, pB, pC, pD, pAD, pM, pP; + wire [47:0] oP, mP; + wire [47:0] oPCOUT, mPCOUT; + generate if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin - wire [29:0] iA; - wire [17:0] iB; - wire [47:0] iC; - wire [24:0] iD; - - wire pA, pB, pC, pD, pAD, pM, pP; - wire [47:0] oP, oPCOUT; - // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && MREG == 0 && PREG == 0) @@ -336,24 +337,20 @@ __CELL__ #( assign pM = 1'bx; end + if (MREG == 0 && PREG == 0) + assign mP = oP, mPCOUT = oPCOUT; + else + assign mP = 1'bx, mPCOUT = 1'bx; \$__ABC_DSP48E1_MULT_P_MUX muxP ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P) ); \$__ABC_DSP48E1_MULT_PCOUT_MUX muxPCOUT ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT) ); `DSP48E1_INST(\$__ABC_DSP48E1_MULT ) end else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin - wire [29:0] iA; - wire [17:0] iB; - wire [47:0] iC; - wire [24:0] iD; - - wire pA, pB, pC, pD, pAD, pM, pP; - wire [47:0] oP, oPCOUT; - // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0) @@ -386,24 +383,20 @@ __CELL__ #( else \$__ABC_DSP48E1_REG rP (.Q(pP)); + if (MREG == 0 && PREG == 0) + assign mP = oP, mPCOUT = oPCOUT; + else + assign mP = 1'bx, mPCOUT = 1'bx; \$__ABC_DSP48E1_MULT_DPORT_P_MUX muxP ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P) ); \$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT) ); `DSP48E1_INST(\$__ABC_DSP48E1_MULT_DPORT ) end else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin - wire [29:0] iA; - wire [17:0] iB; - wire [47:0] iC; - wire [24:0] iD; - - wire pA, pB, pC, pD, pAD, pM, pP; - wire [47:0] oP, oPCOUT; - // Disconnect the A-input if MREG is enabled, since // combinatorial path is broken if (AREG == 0 && PREG == 0) @@ -432,11 +425,15 @@ __CELL__ #( else assign pP = 1'bx; + if (MREG == 0 && PREG == 0) + assign mP = oP, mPCOUT = oPCOUT; + else + assign mP = 1'bx, mPCOUT = 1'bx; \$__ABC_DSP48E1_P_MUX muxP ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P) + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P) ); \$__ABC_DSP48E1_PCOUT_MUX muxPCOUT ( - .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT) + .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT) ); `DSP48E1_INST(\$__ABC_DSP48E1 ) diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index a8f6deafc..1c69dd21c 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -44,16 +44,30 @@ endmodule module \$__ABC_LUT7 (input A, input [6:0] S, output Y); endmodule -// Boxes used to represent the comb/seq behaviour of DSP48E1 -// With abc_map.v responsible for disconnecting inputs to -// the combinatorial DSP48E1 model by a register (e.g. -// disconnecting A when AREG, MREG or PREG is enabled) -// this blackbox captures the existence of a replacement -// path between AREG/BREG/CREG/etc. and P/PCOUT. -// Since the Aq/ADq/Bq/etc. inputs are assumed to arrive at -// the box at zero time, the combinatorial delay through -// these boxes thus represents the clock-to-q delay -// (arrival time) at P/PCOUT. + +// Modules used to model the comb/seq behaviour of DSP48E1 +// With abc_map.v responsible for splicing the below modules +// into between the combinatorial DSP48E1 box (e.g. disconnecting +// A when AREG, MREG or PREG is enabled and splicing in the +// "$__ABC_DSP48E1_REG" blackbox as "REG" in the diagram below) +// this acts to first disables the combinatorial path (as there +// is no connectivity through REG), and secondly, since this is +// blackbox a new PI will be introduced with an arrival time of +// zero. +// Note: Since these "$__ABC_DSP48E1_REG" modules are of a +// sequential nature, they are not passed as a box to ABC and +// (desirably) represented as PO/PIs. +// +// At the DSP output, we place a blackbox mux ("M" in the diagram +// below) to capture the fact that the critical-path could come +// from any one of its inputs. +// In contrast to "REG", the "$__ABC_DSP48E1_*_MUX" modules are +// combinatorial blackboxes that do get passed to ABC. +// The propagation delay through this box (specified in the box +// file) captures the arrival time of the register (i.e. +// propagation from AREG to P after clock edge), or zero delay +// for the combinatorial path from the DSP. +// // Doing so should means that ABC is able to analyse the // worst-case delay through to P, regardless of if it was // through any combinatorial paths (e.g. B, below) or an @@ -65,18 +79,19 @@ endmodule // // In graphical form: // -// NEW "PI" >>---+ -// for AREG.Q | -// | -// +---------+ | __ -// A >>--X X-| | +--| \ -// | DSP48E1 |P | |--->> P +// +-----+ +// +------>> REG >>----+ +// | +-----+ | +// | | +// | +---------+ | __ +// A >>-+X X-| | +--| \ +// | DSP48E1 |P | M |--->> P // | AREG=1 |-------|__/ // B >>------| | // +---------+ // `define ABC_DSP48E1_MUX(__NAME__) """ -module __NAME__ (input Aq, ADq, Bq, Cq, Dq, Mq, input [47:0] P, input Pq, output [47:0] O); +module __NAME__ (input Aq, ADq, Bq, Cq, Dq, input [47:0] I, input Mq, input [47:0] P, input Pq, output [47:0] O); endmodule """ (* abc_box_id=2100 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_P_MUX ) diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index 010041b73..137829d65 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -32,12 +32,14 @@ module \$__ABC_DSP48E1_REG (input [47:0] I, output [47:0] O, output Q); endmodule (* techmap_celltype = "$__ABC_DSP48E1_MULT_P_MUX $__ABC_DSP48E1_MULT_PCOUT_MUX $__ABC_DSP48E1_MULT_DPORT_P_MUX $__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX $__ABC_DSP48E1_P_MUX $__ABC_DSP48E1_PCOUT_MUX" *) module \$__ABC_DSP48E1_MUX ( - input Aq, Bq, Cq, Dq, ADq, Mq, + input Aq, Bq, Cq, Dq, ADq, + input [47:0] I, + input Mq, input [47:0] P, input Pq, output [47:0] O ); - assign O = P; + assign O = I; endmodule (* techmap_celltype = "$__ABC_DSP48E1_MULT $__ABC_DSP48E1_MULT_DPORT $__ABC_DSP48E1" *) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 79b400d40..9b64b4907 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -70,306 +70,306 @@ $__ABC_LUT7 2001 0 8 1 # the mux at zero time, the combinatorial delay through # these muxes thus represents the clock-to-q delay at # P/PCOUT. -$__ABC_DSP48E1_MULT_P_MUX 2100 0 55 48 -# A AD B C D M P Pq -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -2952 - 2813 1687 - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -$__ABC_DSP48E1_MULT_PCOUT_MUX 2101 0 55 48 -# A AD B C D M P Pq -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -3098 - 2960 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -$__ABC_DSP48E1_MULT_DPORT_P_MUX 2102 0 55 48 -# A AD B C D M P Pq -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -3935 2958 2813 1687 3908 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 55 48 -# A AD B C D M P Pq -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -4083 2859 2960 1835 4056 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -$__ABC_DSP48E1_P_MUX 2104 0 55 48 -# A AD B C D M P Pq -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -1632 - 1616 1687 - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 -$__ABC_DSP48E1_PCOUT_MUX 2105 0 55 48 -# A AD B C D M P Pq -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 -1780 - 1765 1835 - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +$__ABC_DSP48E1_MULT_P_MUX 2100 0 103 48 +# A AD B C D I M P Pq +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC_DSP48E1_MULT_PCOUT_MUX 2101 0 103 48 +# A AD B C D I M P Pq +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +$__ABC_DSP48E1_MULT_DPORT_P_MUX 2102 0 103 48 +# A AD B C D I M P Pq +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 103 48 +# A AD B C D I M P Pq +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +$__ABC_DSP48E1_P_MUX 2104 0 103 48 +# A AD B C D I M P Pq +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329 +$__ABC_DSP48E1_PCOUT_MUX 2105 0 103 48 +# A AD B C D I M P Pq +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 +1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435 $__ABC_DSP48E1_MULT 3000 0 263 154 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 - From 1602516a8b2ebd432528e9ba39a00db4e6edc081 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 19:37:45 -0700 Subject: [PATCH 285/356] $__ABC_REG to have WIDTH parameter --- techlibs/xilinx/abc_map.v | 32 ++++++++++++++++---------------- techlibs/xilinx/abc_unmap.v | 3 ++- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 01307fcf2..423da3fdb 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -308,15 +308,15 @@ __CELL__ #( if (AREG == 0 && MREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else - \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); + \$__ABC_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && MREG == 0 && PREG == 0) assign iB = B, pB = 1'bx; else - \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); + \$__ABC_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) assign iC = C, pC = 1'bx; else - \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); + \$__ABC_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0) assign iD = D; else if (techmap_guard) @@ -328,12 +328,12 @@ __CELL__ #( if (PREG == 0) begin assign pP = 1'bx; if (MREG == 1) - \$__ABC_DSP48E1_REG rM (.Q(pM)); + \$__ABC_REG rM (.Q(pM)); else assign pM = 1'bx; end else begin - \$__ABC_DSP48E1_REG rP (.Q(pP)); + \$__ABC_REG rP (.Q(pP)); assign pM = 1'bx; end @@ -356,32 +356,32 @@ __CELL__ #( if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else - \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); + \$__ABC_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && MREG == 0 && PREG == 0) assign iB = B, pB = 1'bx; else - \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); + \$__ABC_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) assign iC = C, pC = 1'bx; else - \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); + \$__ABC_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); if (DREG == 0 && ADREG == 0) assign iD = D, pD = 1'bx; else - \$__ABC_DSP48E1_REG rD (.I(D), .O(iD), .Q(pD)); + \$__ABC_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD)); if (PREG == 0) begin if (MREG == 1) - \$__ABC_DSP48E1_REG rM (.Q(pM)); + \$__ABC_REG rM (.Q(pM)); else begin assign pM = 1'bx; if (ADREG == 1) - \$__ABC_DSP48E1_REG rAD (.Q(pAD)); + \$__ABC_REG rAD (.Q(pAD)); else assign pAD = 1'bx; end end else - \$__ABC_DSP48E1_REG rP (.Q(pP)); + \$__ABC_REG rP (.Q(pP)); if (MREG == 0 && PREG == 0) assign mP = oP, mPCOUT = oPCOUT; @@ -402,15 +402,15 @@ __CELL__ #( if (AREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else - \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA)); + \$__ABC_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA)); if (BREG == 0 && PREG == 0) assign iB = B, pB = 1'bx; else - \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB)); + \$__ABC_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB)); if (CREG == 0 && PREG == 0) assign iC = C, pC = 1'bx; else - \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC)); + \$__ABC_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); if (MREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\""); assign pM = 1'bx; @@ -421,7 +421,7 @@ __CELL__ #( $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); assign pAD = 1'bx; if (PREG == 1) - \$__ABC_DSP48E1_REG rP (.Q(pP)); + \$__ABC_REG rP (.Q(pP)); else assign pP = 1'bx; diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index 137829d65..ab007dfd2 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -27,7 +27,8 @@ module \$__ABC_LUT7 (input A, input [6:0] S, output Y); assign Y = A; endmodule -module \$__ABC_DSP48E1_REG (input [47:0] I, output [47:0] O, output Q); +module \$__ABC_REG (input [WIDTH-1:0] I, output [WIDTH-1:0] O, output Q); + parameter WIDTH = 1; assign O = I; endmodule (* techmap_celltype = "$__ABC_DSP48E1_MULT_P_MUX $__ABC_DSP48E1_MULT_PCOUT_MUX $__ABC_DSP48E1_MULT_DPORT_P_MUX $__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX $__ABC_DSP48E1_P_MUX $__ABC_DSP48E1_PCOUT_MUX" *) From 8a94ce7aa524eea0429446e0a5e8c64bee45ac55 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 20:04:44 -0700 Subject: [PATCH 286/356] Add an index --- passes/pmgen/ice40_dsp.pmg | 1 + passes/pmgen/xilinx_dsp.pmg | 2 ++ 2 files changed, 3 insertions(+) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 73e92031e..35db22807 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -189,6 +189,7 @@ match add index port(add, AB)[0] === sigH[0] filter GetSize(port(add, AB)) <= GetSize(sigH) filter port(add, AB) == sigH.extract(0, GetSize(port(add, AB))) + filter nusers(sigH.extract_end(GetSize(port(add, AB)))) <= 1 set addAB AB optional endmatch diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index f0537670f..20565f47d 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -268,6 +268,8 @@ match postAdd select nusers(port(postAdd, AB)) <= 3 filter ffMcemux || nusers(port(postAdd, AB)) == 2 filter !ffMcemux || nusers(port(postAdd, AB)) == 3 + + index port(postAdd, AB)[0] === sigP[0] filter GetSize(unextend(port(postAdd, AB))) <= GetSize(sigP) filter unextend(port(postAdd, AB)) == sigP.extract(0, GetSize(unextend(port(postAdd, AB)))) filter nusers(sigP.extract_end(GetSize(unextend(port(postAdd, AB))))) <= 1 From 691686f92c011a94a649ae7ecc2f4f22b758fc12 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 20:04:52 -0700 Subject: [PATCH 287/356] Tidy up, fix undriven --- techlibs/xilinx/abc_map.v | 68 ++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 423da3fdb..9d78725df 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -303,8 +303,8 @@ __CELL__ #( generate if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin - // Disconnect the A-input if MREG is enabled, since - // combinatorial path is broken + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken if (AREG == 0 && MREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else @@ -320,21 +320,20 @@ __CELL__ #( if (DREG == 0) assign iD = D; else if (techmap_guard) - $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); assign pD = 1'bx; if (ADREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); assign pAD = 1'bx; - if (PREG == 0) begin - assign pP = 1'bx; - if (MREG == 1) - \$__ABC_REG rM (.Q(pM)); - else - assign pM = 1'bx; - end - else begin - \$__ABC_REG rP (.Q(pP)); + if (PREG == 0) begin + if (MREG == 1) + \$__ABC_REG rM (.Q(pM)); + else + assign pM = 1'bx; + assign pP = 1'bx; + end else begin assign pM = 1'bx; + \$__ABC_REG rP (.Q(pP)); end if (MREG == 0 && PREG == 0) @@ -351,8 +350,8 @@ __CELL__ #( `DSP48E1_INST(\$__ABC_DSP48E1_MULT ) end else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin - // Disconnect the A-input if MREG is enabled, since - // combinatorial path is broken + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else @@ -369,19 +368,22 @@ __CELL__ #( assign iD = D, pD = 1'bx; else \$__ABC_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD)); - if (PREG == 0) begin - if (MREG == 1) - \$__ABC_REG rM (.Q(pM)); - else begin - assign pM = 1'bx; + if (PREG == 0) begin + if (MREG == 1) begin + assign pAD = 1'bx; + \$__ABC_REG rM (.Q(pM)); + end else begin if (ADREG == 1) \$__ABC_REG rAD (.Q(pAD)); else assign pAD = 1'bx; - end - end - else + assign pM = 1'bx; + end + assign pP = 1'bx; + end else begin + assign pAD = 1'bx, pM = 1'bx; \$__ABC_REG rP (.Q(pP)); + end if (MREG == 0 && PREG == 0) assign mP = oP, mPCOUT = oPCOUT; @@ -397,8 +399,8 @@ __CELL__ #( `DSP48E1_INST(\$__ABC_DSP48E1_MULT_DPORT ) end else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin - // Disconnect the A-input if MREG is enabled, since - // combinatorial path is broken + // Disconnect the A-input if MREG is enabled, since + // combinatorial path is broken if (AREG == 0 && PREG == 0) assign iA = A, pA = 1'bx; else @@ -411,16 +413,16 @@ __CELL__ #( assign iC = C, pC = 1'bx; else \$__ABC_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC)); + if (DREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); + assign pD = 1'bx; + if (ADREG == 1 && techmap_guard) + $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); + assign pAD = 1'bx; if (MREG == 1 && techmap_guard) $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\""); assign pM = 1'bx; - if (DREG == 1 && techmap_guard) - $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\""); - assign pD = 1'bx; - if (ADREG == 1 && techmap_guard) - $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\""); - assign pAD = 1'bx; - if (PREG == 1) + if (PREG == 1) \$__ABC_REG rP (.Q(pP)); else assign pP = 1'bx; @@ -440,6 +442,6 @@ __CELL__ #( end else $error("Invalid DSP48E1 configuration"); - endgenerate - `undef DSP48E1_INST + endgenerate + `undef DSP48E1_INST endmodule From 34f9a8ceb285b6b59f24f994d3a877d5f4f09572 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 21:57:11 -0700 Subject: [PATCH 288/356] Update doc for ice40_dsp --- passes/pmgen/ice40_dsp.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index ed3577400..2d264a6d1 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -283,9 +283,18 @@ struct Ice40DspPass : public Pass { log("\n"); log(" ice40_dsp [options] [selection]\n"); log("\n"); - log("Map multipliers and multiply-accumulate blocks to iCE40 DSP resources.\n"); + log("Map multipliers ($mul/SB_MAC16) and multiply-accumulate ($mul/SB_MAC16 + $add)\n"); + log("cells into iCE40 DSP resources.\n"); log("Currently, only the 16x16 multiply mode is supported and not the 2 x 8x8 mode.\n"); log("\n"); + log("Pack input registers (A, B, {C,D}; with optional hold/reset), pipeline registers\n"); + log("({F,J,K,G}, H; with shared reset), output registers (O; with optional hold/reset),\n"); + log("and post-adder into the SB_MAC16 resource.\n"); + log("\n"); + log("Multiply-accumulate operations using the post-adder with feedback on the {C,D}\n"); + log("input will be folded into the DSP. In this scenario only, resetting the\n"); + log("the accumulator to an arbitrary value can be inferred to use the {C,D} input.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { From 1b88211ec61d70ee34f9dc21647ebd941d91fcb4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 21:58:34 -0700 Subject: [PATCH 289/356] Clarify --- passes/pmgen/xilinx_dsp.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index adc09a6e4..abd145723 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -507,7 +507,8 @@ struct XilinxDspPass : public Pass { log("\n"); log("Multiply-accumulate operations using the post-adder with feedback on the 'C'\n"); log("input will be folded into the DSP. In this scenario only, the 'C' input can be\n"); - log("used to override the existing accumulation result with a new value.\n"); + log("used to override the current accumulation result with a new value, which will\n"); + log("be added to the multiplier result to form the next accumulation result.\n"); log("\n"); log("Use of the dedicated 'PCOUT' -> 'PCIN' cascade path is detected for 'P' -> 'C'\n"); log("connections (optionally, where 'P' is right-shifted by 18-bits and used as an\n"); From 4100825b810408e25b1773cb1e57d25821f164b5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 22:39:15 -0700 Subject: [PATCH 290/356] Add more complicated macc testcase --- tests/ice40/macc.v | 22 ++++++++++++++++++++++ tests/ice40/macc.ys | 24 ++++++++++++++++++------ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/tests/ice40/macc.v b/tests/ice40/macc.v index 757c36a66..6f68e7500 100644 --- a/tests/ice40/macc.v +++ b/tests/ice40/macc.v @@ -23,3 +23,25 @@ begin end end endmodule + +module top2(clk,a,b,c,hold); +parameter A_WIDTH = 6 /*4*/; +parameter B_WIDTH = 6 /*3*/; +input hold; +input clk; +input signed [(A_WIDTH - 1):0] a; +input signed [(B_WIDTH - 1):0] b; +output signed [(A_WIDTH + B_WIDTH - 1):0] c; +reg signed [A_WIDTH-1:0] reg_a; +reg signed [B_WIDTH-1:0] reg_b; +reg [(A_WIDTH + B_WIDTH - 1):0] reg_tmp_c; +assign c = reg_tmp_c; +always @(posedge clk) +begin + if (!hold) begin + reg_a <= a; + reg_b <= b; + reg_tmp_c <= reg_a * reg_b + c; + end +end +endmodule diff --git a/tests/ice40/macc.ys b/tests/ice40/macc.ys index 0f4c19be5..fd30e79c5 100644 --- a/tests/ice40/macc.ys +++ b/tests/ice40/macc.ys @@ -1,13 +1,25 @@ read_verilog macc.v proc +design -save read + hierarchy -top top -#equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check - -equiv_opt -run :prove -map +/ice40/cells_sim.v synth_ice40 -dsp -async2sync -equiv_opt -run prove: -assert null - +equiv_opt -assert -multiclock -map +/ice40/cells_sim.v synth_ice40 -dsp # 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:SB_MAC16 select -assert-none t:SB_MAC16 %% t:* %D + +design -load read +hierarchy -top top2 + +#equiv_opt -multiclock -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check + +equiv_opt -run :prove -multiclock -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check +clk2fflogic +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -set-init-zero -seq 4 -verify -prove-asserts -show-ports miter + +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top2 # Constrain all select calls below inside the top module +select -assert-count 1 t:SB_MAC16 +select -assert-none t:SB_MAC16 %% t:* %D From a59f80834f7f8ecf02ed0c608dce1a237a874d34 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 22:39:47 -0700 Subject: [PATCH 291/356] SB_MAC16 ffCD to not pack same as ffO --- passes/pmgen/ice40_dsp.pmg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 35db22807..09fd8406d 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -188,7 +188,7 @@ match add select nusers(port(add, AB)) == 2 index port(add, AB)[0] === sigH[0] filter GetSize(port(add, AB)) <= GetSize(sigH) - filter port(add, AB) == sigH.extract(0, GetSize(port(add, AB))) + filter port(add, AB) == sigH.extract(0, GetSize(port(add, AB))) filter nusers(sigH.extract_end(GetSize(port(add, AB)))) <= 1 set addAB AB optional @@ -280,7 +280,7 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p endcode code argQ ffCD ffCDholdmux ffCDholdpol ffCDrstpol sigCD clock clock_pol - if (!sigCD.empty() && + if (!sigCD.empty() && sigCD != sigO && (mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) { argQ = sigCD; subpattern(in_dffe); From 8cfcaf108e7fd7f538ab2939032f061dc134489b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Sep 2019 22:48:57 -0700 Subject: [PATCH 292/356] Disable support for SB_MAC16 reset since it is async --- passes/pmgen/ice40_dsp.cc | 6 +++--- passes/pmgen/ice40_dsp.pmg | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 2d264a6d1..cff4c5ddb 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -287,9 +287,9 @@ struct Ice40DspPass : public Pass { log("cells into iCE40 DSP resources.\n"); log("Currently, only the 16x16 multiply mode is supported and not the 2 x 8x8 mode.\n"); log("\n"); - log("Pack input registers (A, B, {C,D}; with optional hold/reset), pipeline registers\n"); - log("({F,J,K,G}, H; with shared reset), output registers (O; with optional hold/reset),\n"); - log("and post-adder into the SB_MAC16 resource.\n"); + log("Pack input registers (A, B, {C,D}; with optional hold), pipeline registers\n"); + log("({F,J,K,G}, H), output registers (O; with optional hold), and post-adder into\n"); + log("into the SB_MAC16 resource.\n"); log("\n"); log("Multiply-accumulate operations using the post-adder with feedback on the {C,D}\n"); log("input will be folded into the DSP. In this scenario only, resetting the\n"); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 09fd8406d..b4bfdce4a 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -384,6 +384,8 @@ code argQ argD endcode match ffrstmux + if false /* TODO: ice40 resets are actually async */ + if !argD.empty() select ffrstmux->type.in($mux) index port(ffrstmux, \Y) === argD @@ -487,6 +489,8 @@ code argD argQ endcode match ffrstmux + if false /* TODO: ice40 resets are actually async */ + select ffrstmux->type.in($mux) // ffrstmux output must have two users: ffrstmux and ff.D select nusers(port(ffrstmux, \Y)) == 2 From a0d3ecf8c6cf4710a53fa67a4f60ef7140ee0c3a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 08:41:28 -0700 Subject: [PATCH 293/356] Small cleanup --- passes/pmgen/ice40_dsp.pmg | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index b4bfdce4a..96fd8e5c9 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,5 +1,6 @@ pattern ice40_dsp +udata > unextend state clock state clock_pol cd_signed o_lo state sigA sigB sigCD sigH sigO @@ -27,6 +28,19 @@ match mul endmatch code sigA sigB sigH + unextend = [](const SigSpec &sig) { + int i; + for (i = GetSize(sig)-1; i > 0; i--) + if (sig[i] != sig[i-1]) + break; + // Do not remove non-const sign bit + if (sig[i].wire) + ++i; + return sig.extract(0, i); + }; + sigA = unextend(port(mul, \A)); + sigB = unextend(port(mul, \B)); + SigSpec O; if (mul->type == $mul) O = mul->getPort(\Y); @@ -36,25 +50,8 @@ code sigA sigB sigH if (GetSize(O) <= 10) reject; - sigA = port(mul, \A); - int i; - for (i = GetSize(sigA)-1; i > 0; i--) - if (sigA[i] != sigA[i-1]) - break; - // Do not remove non-const sign bit - if (sigA[i].wire) - ++i; - sigA.remove(i, GetSize(sigA)-i); - sigB = port(mul, \B); - for (i = GetSize(sigB)-1; i > 0; i--) - if (sigB[i] != sigB[i-1]) - break; - // Do not remove non-const sign bit - if (sigB[i].wire) - ++i; - sigB.remove(i, GetSize(sigB)-i); - // Only care about those bits that are used + int i; for (i = 0; i < GetSize(O); i++) { if (nusers(O[i]) <= 1) break; @@ -105,7 +102,7 @@ code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol } endcode -code argD ffFJKG sigH sigO clock clock_pol +code argD ffFJKG sigH clock clock_pol if (nusers(sigH) == 2 && (mul->type != \SB_MAC16 || (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool()))) { @@ -183,9 +180,11 @@ endcode match add if mul->type != \SB_MAC16 || (param(mul, \TOPOUTPUT_SELECT).as_int() == 3 && param(mul, \BOTOUTPUT_SELECT).as_int() == 3) + select add->type.in($add) choice AB {\A, \B} select nusers(port(add, AB)) == 2 + index port(add, AB)[0] === sigH[0] filter GetSize(port(add, AB)) <= GetSize(sigH) filter port(add, AB) == sigH.extract(0, GetSize(port(add, AB))) From e4f4f6a9d5cf8bb23870fc483f16f66c80ceebab Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 08:41:40 -0700 Subject: [PATCH 294/356] Move mul2dsp before wreduce --- techlibs/ice40/synth_ice40.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 284bc90d0..225603475 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -265,6 +265,10 @@ struct SynthIce40Pass : public ScriptPass run("opt_clean"); run("check"); run("opt"); + if (help_mode || dsp) + run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " + "-D DSP_A_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " + "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); run("wreduce"); run("peepopt"); run("opt_clean"); @@ -273,11 +277,6 @@ struct SynthIce40Pass : public ScriptPass run("opt_expr"); run("opt_clean"); if (help_mode || dsp) { - run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " - "-D DSP_A_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " - "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); - run("opt_expr -fine", " (if -dsp)"); - run("wreduce", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); run("chtype -set $mul t:$__soft_mul","(if -dsp)"); } From 829e4f5d2c8a521b5e4f80e85b9d58191d64f0d5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 08:56:16 -0700 Subject: [PATCH 295/356] Revert "Move mul2dsp before wreduce" This reverts commit e4f4f6a9d5cf8bb23870fc483f16f66c80ceebab. --- techlibs/ice40/synth_ice40.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 225603475..284bc90d0 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -265,10 +265,6 @@ struct SynthIce40Pass : public ScriptPass run("opt_clean"); run("check"); run("opt"); - if (help_mode || dsp) - run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " - "-D DSP_A_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " - "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); run("wreduce"); run("peepopt"); run("opt_clean"); @@ -277,6 +273,11 @@ struct SynthIce40Pass : public ScriptPass run("opt_expr"); run("opt_clean"); if (help_mode || dsp) { + run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " + "-D DSP_A_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " + "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); + run("opt_expr -fine", " (if -dsp)"); + run("wreduce", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); run("chtype -set $mul t:$__soft_mul","(if -dsp)"); } From 289cf688b76328d62c7416d1327d2d6777b0ffd9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 09:02:29 -0700 Subject: [PATCH 296/356] Re-add DSP_A_MINWIDTH, remove unnec. opt_expr -fine from synth_ice40 --- techlibs/ice40/synth_ice40.cc | 3 +-- techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 284bc90d0..7a8f3d70c 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -274,9 +274,8 @@ struct SynthIce40Pass : public ScriptPass run("opt_clean"); if (help_mode || dsp) { run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " - "-D DSP_A_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); - run("opt_expr -fine", " (if -dsp)"); run("wreduce", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); run("chtype -set $mul t:$__soft_mul","(if -dsp)"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 6687a0786..022b0d108 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -343,7 +343,7 @@ struct SynthXilinxPass : public ScriptPass if (!nodsp || help_mode) { // NB: Xilinx multipliers are signed only run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 " - "-D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); run("xilinx_dsp"); From 1844498c5f4f19f77919faf056b165d8b282470e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 09:59:42 -0700 Subject: [PATCH 297/356] Add an overload for port/param with default value --- passes/pmgen/pmgen.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index 335d26f16..d5e667911 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -453,11 +453,19 @@ with open(outfile, "w") as f: print(" return sigmap(cell->getPort(portname));", file=f) print(" }", file=f) print("", file=f) + print(" SigSpec port(Cell *cell, IdString portname, const SigSpec& defval) {", file=f) + print(" return sigmap(cell->connections_.at(portname, defval));", file=f) + print(" }", file=f) + print("", file=f) print(" Const param(Cell *cell, IdString paramname) {", file=f) print(" return cell->getParam(paramname);", file=f) print(" }", file=f) print("", file=f) + print(" Const param(Cell *cell, IdString paramname, const Const& defval) {", file=f) + print(" return cell->parameters.at(paramname, defval);", file=f) + print(" }", file=f) + print("", file=f) print(" int nusers(const SigSpec &sig) {", file=f) print(" pool users;", file=f) From ed187ef1cf118727a8964e26c36530560f3e37db Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 10:00:09 -0700 Subject: [PATCH 298/356] Add a xilinx_dsp_cascade matcher for PCIN -> PCOUT --- passes/pmgen/Makefile.inc | 3 +- passes/pmgen/xilinx_dsp.cc | 58 +++--------------- passes/pmgen/xilinx_dsp.pmg | 2 +- passes/pmgen/xilinx_dsp_cascade.pmg | 94 +++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 53 deletions(-) create mode 100644 passes/pmgen/xilinx_dsp_cascade.pmg diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 21f29a49a..82bb40ac8 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -22,8 +22,9 @@ $(eval $(call add_extra_objs,passes/pmgen/ice40_wrapcarry_pm.h)) # -------------------------------------- OBJS += passes/pmgen/xilinx_dsp.o -passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h +passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h passes/pmgen/xilinx_dsp_cascade_pm.h $(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_pm.h)) +$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_cascade_pm.h)) # -------------------------------------- diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index abd145723..0d0c60375 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -25,6 +25,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN #include "passes/pmgen/xilinx_dsp_pm.h" +#include "passes/pmgen/xilinx_dsp_cascade_pm.h" static Cell* addDsp(Module *module) { Cell *cell = module->addCell(NEW_ID, ID(DSP48E1)); @@ -253,9 +254,9 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) } -void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) +void pack_xilinx_dsp(xilinx_dsp_pm &pm) { - auto &st = pm.st_xilinx_dsp; + auto &st = pm.st_xilinx_dsp_pack; #if 1 log("\n"); @@ -487,9 +488,6 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); cell->setPort(ID(P), P); - bit_to_driver.insert(std::make_pair(P[0], cell)); - bit_to_driver.insert(std::make_pair(P[17], cell)); - pm.blacklist(cell); } @@ -508,7 +506,7 @@ struct XilinxDspPass : public Pass { log("Multiply-accumulate operations using the post-adder with feedback on the 'C'\n"); log("input will be folded into the DSP. In this scenario only, the 'C' input can be\n"); log("used to override the current accumulation result with a new value, which will\n"); - log("be added to the multiplier result to form the next accumulation result.\n"); + log("be added to the multiplier result to form the next accumulation result.\n"); log("\n"); log("Use of the dedicated 'PCOUT' -> 'PCIN' cascade path is detected for 'P' -> 'C'\n"); log("connections (optionally, where 'P' is right-shifted by 18-bits and used as an\n"); @@ -545,52 +543,10 @@ struct XilinxDspPass : public Pass { pack_xilinx_simd(module, module->selected_cells()); xilinx_dsp_pm pm(module, module->selected_cells()); - dict bit_to_driver; - auto f = [&bit_to_driver](xilinx_dsp_pm &pm){ pack_xilinx_dsp(bit_to_driver, pm); }; - pm.run_xilinx_dsp(f); + pm.run_xilinx_dsp_pack(pack_xilinx_dsp); - auto &unextend = pm.ud_xilinx_dsp.unextend; - // Look for ability to convert C input from another DSP into PCIN - // NB: Needs to be done after pattern matcher has folded all - // $add cells into the DSP - for (auto cell : module->cells()) { - if (cell->type != ID(DSP48E1)) - continue; - if (cell->parameters.at(ID(CREG), State::S1).as_bool()) - continue; - SigSpec &opmode = cell->connections_.at(ID(OPMODE)); - if (opmode.extract(4,3) != Const::from_string("011")) - continue; - SigSpec C = unextend(pm.sigmap(cell->getPort(ID(C)))); - if (!C[0].wire) - continue; - auto it = bit_to_driver.find(C[0]); - if (it == bit_to_driver.end()) - continue; - auto driver = it->second; - - SigSpec P = driver->getPort(ID(P)); - if (GetSize(P) >= GetSize(C) && P.extract(0, GetSize(C)) == C) { - cell->setPort(ID(C), Const(0, 48)); - Wire *cascade = module->addWire(NEW_ID, 48); - driver->setPort(ID(PCOUT), cascade); - cell->setPort(ID(PCIN), cascade); - opmode[6] = State::S0; - opmode[5] = State::S0; - opmode[4] = State::S1; - bit_to_driver.erase(it); - } - else if (GetSize(P) >= GetSize(C)+17 && P.extract(17, GetSize(C)) == C) { - cell->setPort(ID(C), Const(0, 48)); - Wire *cascade = module->addWire(NEW_ID, 48); - driver->setPort(ID(PCOUT), cascade); - cell->setPort(ID(PCIN), cascade); - opmode[6] = State::S1; - opmode[5] = State::S0; - opmode[4] = State::S1; - bit_to_driver.erase(it); - } - } + xilinx_dsp_cascade_pm pmc(module, module->selected_cells()); + pmc.run_xilinx_dsp_cascade(); } } } XilinxDspPass; diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 20565f47d..0ee230ccc 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,4 +1,4 @@ -pattern xilinx_dsp +pattern xilinx_dsp_pack udata > unextend state clock diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg new file mode 100644 index 000000000..901173724 --- /dev/null +++ b/passes/pmgen/xilinx_dsp_cascade.pmg @@ -0,0 +1,94 @@ +pattern xilinx_dsp_cascade + +udata > unextend +state sigC + +code + unextend = [](const SigSpec &sig) { + int i; + for (i = GetSize(sig)-1; i > 0; i--) + if (sig[i] != sig[i-1]) + break; + // Do not remove non-const sign bit + if (sig[i].wire) + ++i; + return sig.extract(0, i); + }; +endcode + +match dsp_pcin + select dsp_pcin->type.in(\DSP48E1) + select !param(dsp_pcin, \CREG, State::S1).as_bool() + select port(dsp_pcin, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011") + select nusers(port(dsp_pcin, \C, SigSpec())) > 1 + select nusers(port(dsp_pcin, \PCIN, SigSpec())) == 0 +endmatch + +code sigC + sigC = unextend(port(dsp_pcin, \C)); +endcode + +match dsp_pcout + select dsp_pcout->type.in(\DSP48E1) + select nusers(port(dsp_pcout, \P, SigSpec())) > 1 + select nusers(port(dsp_pcout, \PCOUT, SigSpec())) <= 1 + + index port(dsp_pcout, \P)[0] === sigC[0] + filter GetSize(port(dsp_pcin, \P)) >= GetSize(sigC) + filter port(dsp_pcout, \P).extract(0, GetSize(sigC)) == sigC + + optional +endmatch + +match dsp_pcout_shift17 + if !dsp_pcout + select dsp_pcout_shift17->type.in(\DSP48E1) + select nusers(port(dsp_pcout_shift17, \P, SigSpec())) > 1 + select nusers(port(dsp_pcout_shift17, \PCOUT, SigSpec())) <= 1 + + index port(dsp_pcout_shift17, \P)[17] === sigC[0] + filter GetSize(port(dsp_pcout_shift17, \P)) >= GetSize(sigC)+17 + filter port(dsp_pcout_shift17, \P).extract(17, GetSize(sigC)) == sigC +endmatch + +code + Cell *dsp; + if (dsp_pcout) + dsp = dsp_pcout; + else if (dsp_pcout_shift17) + dsp = dsp_pcout_shift17; + else log_abort(); + + dsp_pcin->setPort(ID(C), Const(0, 48)); + + Wire *cascade = module->addWire(NEW_ID, 48); + dsp_pcin->setPort(ID(PCIN), cascade); + dsp->setPort(ID(PCOUT), cascade); + add_siguser(cascade, dsp_pcin); + add_siguser(cascade, dsp); + + SigSpec opmode = param(dsp_pcin, \OPMODE, Const(0, 7)); + if (dsp_pcout) + opmode[6] = State::S0; + else if (dsp_pcout_shift17) + opmode[6] = State::S1; + else log_abort(); + + + opmode[5] = State::S0; + opmode[4] = State::S1; + dsp_pcin->setPort(ID(OPMODE), opmode); + + log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + + if (nusers(port(dsp_pcin, \PCOUT, SigSpec())) > 1) { + log_debug(" Saturated PCIN/PCOUT on %s\n", log_id(dsp_pcin)); + blacklist(dsp_pcin); + } + if (nusers(port(dsp, \PCIN, SigSpec())) > 1) { + log_debug(" Saturated PCIN/PCOUT on %s\n", log_id(dsp)); + blacklist(dsp_pcout); + } + + accept; +endcode From 70c5444b25f18760781509104f4393b3d0a05fc0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 10:07:54 -0700 Subject: [PATCH 299/356] Update doc --- passes/pmgen/ice40_dsp.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index cff4c5ddb..0b7ffe64b 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -288,8 +288,8 @@ struct Ice40DspPass : public Pass { log("Currently, only the 16x16 multiply mode is supported and not the 2 x 8x8 mode.\n"); log("\n"); log("Pack input registers (A, B, {C,D}; with optional hold), pipeline registers\n"); - log("({F,J,K,G}, H), output registers (O; with optional hold), and post-adder into\n"); - log("into the SB_MAC16 resource.\n"); + log("({F,J,K,G}, H), output registers (O -- full 32-bits or lower 16-bits only; with\n"); + log("optional hold), and post-adder into into the SB_MAC16 resource.\n"); log("\n"); log("Multiply-accumulate operations using the post-adder with feedback on the {C,D}\n"); log("input will be folded into the DSP. In this scenario only, resetting the\n"); From ab46d9017b1a6fe6e376278ca9d3bec2e5673f06 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 10:11:36 -0700 Subject: [PATCH 300/356] Fix signedness bug --- techlibs/common/mul2dsp.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index f2b44222e..3ca69b7b1 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -239,9 +239,9 @@ module _80_mul (A, B, Y); ); //assign partial_sum[n] = (last_partial << n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; if (A_SIGNED && B_SIGNED) - assign partial_sum[n][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + partial_sum[n-1][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]; - else assign partial_sum[n][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + $signed(partial_sum[n-1][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]); + else + assign partial_sum[n][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + partial_sum[n-1][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]; assign partial_sum[n][n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0] = partial_sum[n-1][n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0]; assign Y = partial_sum[n]; end From 1809f463fb235a5e4c137ee992712ecc8d235fdc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 12:03:10 -0700 Subject: [PATCH 301/356] More exceptions --- passes/pmgen/pmgen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index d5e667911..39a09991d 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -286,7 +286,7 @@ def process_pmgfile(f, filename): block["gencode"].append(rewrite_cpp(l.rstrip())) break - assert False + raise RuntimeError("'%s' statement not recognised on line %d" % (a[0], linenr)) if block["optional"]: assert not block["semioptional"] @@ -328,7 +328,7 @@ def process_pmgfile(f, filename): blocks.append(block) continue - assert False + raise RuntimeError("'%s' command not recognised" % cmd) for fn in pmgfiles: with open(fn, "r") as f: From d88903e6108f8afc8e74ee3d3e942b98c21e1ae9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 12:03:25 -0700 Subject: [PATCH 302/356] Cleanup xilinx_dsp --- passes/pmgen/xilinx_dsp.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 0ee230ccc..7d34c6a78 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -2,7 +2,7 @@ pattern xilinx_dsp_pack udata > unextend state clock -state sigA sigffAcemuxY sigB sigffBcemuxY sigC sigffCcemuxY sigD sigffDcemuxY sigM sigP +state sigA sigB sigC sigD sigM sigP state postAddAB postAddMuxAB state ffA1cepol ffA2cepol ffADcepol ffB1cepol ffB2cepol ffCcepol ffDcepol ffMcepol ffPcepol state ffArstpol ffADrstpol ffBrstpol ffCrstpol ffDrstpol ffMrstpol ffPrstpol From 1b892ca1be15864830253c2f67fd831de39020bd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 12:03:45 -0700 Subject: [PATCH 303/356] Cleanup ice40_dsp.pmg --- passes/pmgen/ice40_dsp.pmg | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 96fd8e5c9..19ee9054b 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -136,11 +136,9 @@ code argD ffFJKG sigH clock clock_pol clock = dffclock; clock_pol = dffclock_pol; sigH = dffQ; - } - } - if (0) { -reject_ffFJKG: ; +reject_ffFJKG: ; + } } endcode @@ -168,11 +166,9 @@ code argD ffH sigH sigO clock clock_pol clock = dffclock; clock_pol = dffclock_pol; sigH = dffQ; - } - } - if (0) { -reject_ffH: ; +reject_ffH: ; + } } sigO = sigH; @@ -312,11 +308,9 @@ code argQ ffCD ffCDholdmux ffCDholdpol ffCDrstpol sigCD clock clock_pol clock = dffclock; clock_pol = dffclock_pol; sigCD = dffD; - } - } - if (0) { -reject_ffCD: ; +reject_ffCD: ; + } } endcode From b0ad2592befb1a5b5a41319f6d75773aea202173 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 12:04:16 -0700 Subject: [PATCH 304/356] Run until convergence --- passes/pmgen/xilinx_dsp.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 0d0c60375..7530eb5ad 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -24,6 +24,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +bool did_something; + #include "passes/pmgen/xilinx_dsp_pm.h" #include "passes/pmgen/xilinx_dsp_cascade_pm.h" @@ -509,7 +511,7 @@ struct XilinxDspPass : public Pass { log("be added to the multiplier result to form the next accumulation result.\n"); log("\n"); log("Use of the dedicated 'PCOUT' -> 'PCIN' cascade path is detected for 'P' -> 'C'\n"); - log("connections (optionally, where 'P' is right-shifted by 18-bits and used as an\n"); + log("connections (optionally, where 'P' is right-shifted by 17-bits and used as an\n"); log("input to the post-adder -- a pattern common for summing partial products to\n"); log("implement wide multipliers).\n"); log("\n"); @@ -545,8 +547,12 @@ struct XilinxDspPass : public Pass { xilinx_dsp_pm pm(module, module->selected_cells()); pm.run_xilinx_dsp_pack(pack_xilinx_dsp); - xilinx_dsp_cascade_pm pmc(module, module->selected_cells()); - pmc.run_xilinx_dsp_cascade(); + do { + did_something = false; + xilinx_dsp_cascade_pm pmc(module, module->selected_cells()); + pmc.run_xilinx_dsp_cascadeP(); + pmc.run_xilinx_dsp_cascadeAB(); + } while (did_something); } } } XilinxDspPass; From 0bca366bcd0f936bc232cf869ef13818572664f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 12:07:14 -0700 Subject: [PATCH 305/356] WIP for xiinx_dsp_cascadeAB --- passes/pmgen/xilinx_dsp_cascade.pmg | 502 +++++++++++++++++++++++++++- 1 file changed, 499 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg index 901173724..996a3b80f 100644 --- a/passes/pmgen/xilinx_dsp_cascade.pmg +++ b/passes/pmgen/xilinx_dsp_cascade.pmg @@ -1,4 +1,4 @@ -pattern xilinx_dsp_cascade +pattern xilinx_dsp_cascadeP udata > unextend state sigC @@ -33,7 +33,7 @@ match dsp_pcout select nusers(port(dsp_pcout, \P, SigSpec())) > 1 select nusers(port(dsp_pcout, \PCOUT, SigSpec())) <= 1 - index port(dsp_pcout, \P)[0] === sigC[0] + index port(dsp_pcout, \P)[0] === sigC[0] filter GetSize(port(dsp_pcin, \P)) >= GetSize(sigC) filter port(dsp_pcout, \P).extract(0, GetSize(sigC)) == sigC @@ -46,7 +46,7 @@ match dsp_pcout_shift17 select nusers(port(dsp_pcout_shift17, \P, SigSpec())) > 1 select nusers(port(dsp_pcout_shift17, \PCOUT, SigSpec())) <= 1 - index port(dsp_pcout_shift17, \P)[17] === sigC[0] + index port(dsp_pcout_shift17, \P)[17] === sigC[0] filter GetSize(port(dsp_pcout_shift17, \P)) >= GetSize(sigC)+17 filter port(dsp_pcout_shift17, \P).extract(17, GetSize(sigC)) == sigC endmatch @@ -90,5 +90,501 @@ code blacklist(dsp_pcout); } + did_something = true; accept; endcode + +// ########## + +pattern xilinx_dsp_cascadeAB + +udata > unextend +state clock +state sigA sigB + +state ffA1cepol ffA2cepol ffB1cepol ffB2cepol +state ffArstpol ffBrstpol + +state ffA1 ffA1cemux ffA1rstmux ffA2 ffA2cemux ffA2rstmux +state ffB1 ffB1cemux ffB1rstmux ffB2 ffB2cemux ffB2rstmux + +// subpattern +state argQ argD +state ffcepol ffrstpol +state ffoffset +udata dffD dffQ +udata dffclock +udata dff dffcemux dffrstmux +udata dffcepol dffrstpol + +code + unextend = [](const SigSpec &sig) { + int i; + for (i = GetSize(sig)-1; i > 0; i--) + if (sig[i] != sig[i-1]) + break; + // Do not remove non-const sign bit + if (sig[i].wire) + ++i; + return sig.extract(0, i); + }; +endcode + +match dspD + select dspD->type.in(\DSP48E1) + select (param(dspD, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && nusers(port(dspD, \A, SigSpec())) > 1 && nusers(port(dspD, \ACIN, SigSpec())) == 0) || (param(dspD, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && nusers(port(dspD, \B, SigSpec())) > 1 && nusers(port(dspD, \BCIN, SigSpec())) == 0) +endmatch + +code sigA sigB + if (param(dspD, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT") + sigA = unextend(port(dspD, \A)); + if (param(dspD, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT") + sigB = unextend(port(dspD, \B)); +endcode + +code argQ ffA2 ffA2cemux ffA2rstmux ffA2cepol ffArstpol ffA1 ffA1cemux ffA1rstmux ffA1cepol sigA clock + if (!sigA.empty()) { + argQ = sigA; + subpattern(in_dffe); + if (dff) { + ffA2 = dff; + clock = dffclock; + if (dffrstmux) { + ffA2rstmux = dffrstmux; + ffArstpol = dffrstpol; + } + if (dffcemux) { + ffA2cemux = dffcemux; + ffA2cepol = dffcepol; + } + sigA = dffD; + + // Now attempt to match A1 + argQ = sigA; + subpattern(in_dffe); + if (dff) { + if ((ffA2rstmux != nullptr) ^ (dffrstmux != nullptr)) + goto reject_ffA1; + if (dffrstmux) { + if (ffArstpol != dffrstpol) + goto reject_ffA1; + if (port(ffA2rstmux, \S) != port(dffrstmux, \S)) + goto reject_ffA1; + ffA1rstmux = dffrstmux; + } + + ffA1 = dff; + clock = dffclock; + + if (dffcemux) { + ffA1cemux = dffcemux; + ffA1cepol = dffcepol; + } + sigA = dffD; + +reject_ffA1: ; + } + } + } +endcode + +match dspQA2 + if ffA1 + select dspQA2->type.in(\DSP48E1) + select param(dspQA2, \A_REG, 2).as_int() == 2 + select nusers(port(dspQA2, \A, SigSpec())) > 1 + select nusers(port(dspQA2, \ACOUT, SigSpec())) == 0 + slice offset GetSize(port(dspQA2, \A)) + index port(dspQA2, \A)[offset] === sigA[0] + index port(dspQA2, \CLK) === port(dspD, \CLK) + + // Check that the rest of sigA is present + filter GetSize(port(dspQA2, \A)) >= offset + GetSize(sigA) + filter port(dspQA2, \A).extract(offset, GetSize(sigA)) == sigA + + optional +endmatch + +code + if (dspQA2) { + // Check CE and RST are compatible + if ((ffA1cemux != nullptr) == port(dspQA2, \CEA1, State::S1).is_fully_const()) + reject; + if ((ffA2cemux != nullptr) == port(dspQA2, \CEA2, State::S1).is_fully_const()) + reject; + if ((ffA1rstmux != nullptr) == port(dspQA2, \RSTA, State::S0).is_fully_const()) + reject; + if ((ffA2rstmux != nullptr) == port(dspQA2, \RSTA, State::S0).is_fully_const()) + reject; + + if (ffA1cemux) { + if (port(dspQA2, \CEA1) != port(ffA1cemux, \S)) + reject; + // TODO: Support inversions + if (!ffA1cepol) + reject; + } + if (ffA2cemux) { + if (port(dspQA2, \CEA2) != port(ffA2cemux, \S)) + reject; + // TODO: Support inversions + if (!ffA2cepol) + reject; + } + if (ffA1rstmux) { + if (port(dspQA2, \RSTA) != port(ffA1rstmux, \S)) + reject; + // TODO: Support inversions + if (!ffArstpol) + reject; + } + if (ffA2rstmux) { + if (port(dspQA2, \RSTA) != port(ffA2rstmux, \S)) + reject; + // TODO: Support inversions + if (!ffArstpol) + reject; + } + } +endcode + +match dspQA1 + if !dspQA1 && !ffA1 + if ffA2 + select dspQA1->type.in(\DSP48E1) + select param(dspQA1, \A_REG, 2).as_int() == 1 + select nusers(port(dspQA1, \A, SigSpec())) > 1 + select nusers(port(dspQA1, \ACOUT, SigSpec())) == 0 + slice offset GetSize(port(dspQA1, \A)) + index port(dspQA1, \A)[offset] === sigA[0] + index port(dspQA1, \CLK) === port(dspD, \CLK) + + // Check that the rest of sigA is present + filter GetSize(port(dspQA1, \A)) >= offset + GetSize(sigA) + filter port(dspQA1, \A).extract(offset, GetSize(sigA)) == sigA + + optional +endmatch + +code + if (dspQA1) { + // Check CE and RST are compatible + if ((ffA2cemux != NULL) == port(dspQA1, \CEA2, State::S1).is_fully_const()) + reject; + if ((ffA2rstmux != NULL) == port(dspQA1, \RSTA, State::S0).is_fully_const()) + reject; + + if (!ffA2cepol || !ffArstpol) + reject; + + if (ffA2cemux) { + if (port(dspQA1, \CEA2) != port(ffA2cemux, \S)) + reject; + // TODO: Support inversions + if (!ffA2cepol) + reject; + } + if (ffA2rstmux) { + if (port(dspQA1, \RSTA) != port(ffA2rstmux, \S)) + reject; + // TODO: Support inversions + if (!ffArstpol) + reject; + } + } +endcode + +code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol ffB1 ffB1cemux ffB1rstmux ffB1cepol sigB clock + if (!sigB.empty()) { + argQ = sigB; + subpattern(in_dffe); + if (dff) { + ffB2 = dff; + clock = dffclock; + if (dffrstmux) { + ffB2rstmux = dffrstmux; + ffBrstpol = dffrstpol; + } + if (dffcemux) { + ffB2cemux = dffcemux; + ffB2cepol = dffcepol; + } + sigB = dffD; + + // Now attempt to match B1 + argQ = sigB; + subpattern(in_dffe); + if (dff) { + if ((ffB2rstmux != nullptr) ^ (dffrstmux != nullptr)) + goto reject_ffB1; + if (dffrstmux) { + if (ffBrstpol != dffrstpol) + goto reject_ffB1; + if (port(ffB2rstmux, \S) != port(dffrstmux, \S)) + goto reject_ffB1; + ffB1rstmux = dffrstmux; + } + + ffB1 = dff; + clock = dffclock; + + if (dffcemux) { + ffB1cemux = dffcemux; + ffB1cepol = dffcepol; + } + sigB = dffD; + +reject_ffB1: ; + } + } + } +endcode + +match dspQB2 + if ffB1 + select dspQB2->type.in(\DSP48E1) + select param(dspQB2, \B_REG, 2).as_int() == 2 + select nusers(port(dspQB2, \B, SigSpec())) > 1 + select nusers(port(dspQB2, \BCOUT, SigSpec())) == 0 + slice offset GetSize(port(dspQB2, \B)) + index port(dspQB2, \B)[offset] === sigB[0] + index port(dspQB2, \CLK) === port(dspD, \CLK) + + // Check that the rest of sigB is present + filter GetSize(port(dspQB2, \B)) >= offset + GetSize(sigB) + filter port(dspQB2, \B).extract(offset, GetSize(sigB)) == sigB + + optional +endmatch + +code + if (dspQB2) { + // Check CE and RST are compatible + if ((ffB1cemux != nullptr) == port(dspQB2, \CEB1, State::S1).is_fully_const()) + reject; + if ((ffB2cemux != NULL) == port(dspQB2, \CEB2, State::S1).is_fully_const()) + reject; + if ((ffB1rstmux != NULL) == port(dspQB2, \RSTB, State::S0).is_fully_const()) + reject; + if ((ffB2rstmux != NULL) == port(dspQB2, \RSTB, State::S0).is_fully_const()) + reject; + + if (ffB1cemux) { + if (port(dspQB2, \CEB1) != port(ffB1cemux, \S)) + reject; + // TODO: Support inversions + if (!ffB1cepol) + reject; + } + if (ffB2cemux) { + if (port(dspQB2, \CEB2) != port(ffB2cemux, \S)) + reject; + // TODO: Support inversions + if (!ffB2cepol) + reject; + } + if (ffB2rstmux) { + if (port(dspQB2, \RSTB) != port(ffB2rstmux, \S)) + reject; + // TODO: Support inversions + if (!ffBrstpol) + reject; + } + } +endcode + +match dspQB1 + if !dspQB1 && !ffB1 + if ffB2 + select dspQB1->type.in(\DSP48E1) + select param(dspQB1, \B_REG, 2).as_int() >= 1 + select nusers(port(dspQB1, \B, SigSpec())) > 1 + select nusers(port(dspQB1, \BCOUT, SigSpec())) == 0 + slice offset GetSize(port(dspQB1, \B)) + index port(dspQB1, \B)[offset] === sigB[0] + index port(dspQB1, \CLK) === port(dspD, \CLK) + + // Check that the rest of sigB is present + filter GetSize(port(dspQB1, \B)) >= offset + GetSize(sigB) + filter port(dspQB1, \B).extract(offset, GetSize(sigB)) == sigB + + optional +endmatch + +code + if (dspQB1) { + // Check CE and RST are compatible + if ((ffB2cemux != NULL) != port(dspQB1, \CEB2, State::S1).is_fully_const()) + reject; + if ((ffB2rstmux != NULL) != port(dspQB1, \RSTB, State::S0).is_fully_const()) + reject; + + if (!ffA2cepol || !ffArstpol) + reject; + + if (ffA2cemux) { + if (port(dspQB1, \CEB2) != port(ffB2cemux, \S)) + reject; + // TODO: Support inversions + if (!ffA2cepol) + reject; + } + if (ffA2rstmux) { + if (port(dspQB1, \RSTB) != port(ffB2rstmux, \S)) + reject; + // TODO: Support inversions + if (!ffArstpol) + reject; + } + } +endcode + +code + if (dspQA1 || dspQA2) { + dspD->setParam(\A_INPUT, Const("CASCADE")); + dspD->setPort(\A, Const(0, 30)); + + Wire *cascade = module->addWire(NEW_ID, 30); + if (dspQA1) { + dspQA1->setParam(\ACASCREG, 1); + dspQA1->setPort(\ACOUT, cascade); + log_debug("ACOUT -> ACIN cascade for %s -> %s\n", log_id(dspQA1), log_id(dspD)); + } + else if (dspQA2) { + dspQA2->setParam(\ACASCREG, 2); + dspQA2->setPort(\ACOUT, cascade); + log_debug("ACOUT -> ACIN cascade for %s -> %s\n", log_id(dspQA2), log_id(dspD)); + } + else + log_abort(); + + dspD->setPort(\ACIN, cascade); + did_something = true; + } + if (dspQB1 || dspQB2) { + dspD->setParam(\B_INPUT, Const("CASCADE")); + dspD->setPort(\B, Const(0, 18)); + + Wire *cascade = module->addWire(NEW_ID, 18); + if (dspQB1) { + dspQB1->setParam(\BCASCREG, 1); + dspQB1->setPort(\BCOUT, cascade); + log_debug("BCOUT -> BCIN cascade for %s -> %s\n", log_id(dspQB1), log_id(dspD)); + } + else if (dspQB2) { + dspQB2->setParam(\BCASCREG, 2); + dspQB2->setPort(\BCOUT, cascade); + log_debug("BCOUT -> BCIN cascade for %s -> %s\n", log_id(dspQB2), log_id(dspD)); + } + else + log_abort(); + + dspD->setPort(\BCIN, cascade); + did_something = true; + } + + accept; +endcode + + +// ####################### + +subpattern in_dffe +arg argD argQ clock + +code + dff = nullptr; + for (auto c : argQ.chunks()) { + if (!c.wire) + reject; + if (c.wire->get_bool_attribute(\keep)) + reject; + } +endcode + +match ff + select ff->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ff, \CLK_POLARITY).as_bool() + + slice offset GetSize(port(ff, \D)) + index port(ff, \Q)[offset] === argQ[0] + + // Check that the rest of argQ is present + filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ) + filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ + + set ffoffset offset +endmatch + +code argQ argD +{ + if (clock != SigBit() && port(ff, \CLK) != clock) + reject; + + SigSpec Q = port(ff, \Q); + dff = ff; + dffclock = port(ff, \CLK); + dffD = argQ; + argD = port(ff, \D); + argQ = Q; + dffD.replace(argQ, argD); + // Only search for ffrstmux if dffD only + // has two (ff, ffrstmux) users + if (nusers(dffD) > 2) + argD = SigSpec(); +} +endcode + +match ffrstmux + if !argD.empty() + select ffrstmux->type.in($mux) + index port(ffrstmux, \Y) === argD + + choice BA {\B, \A} + // DSP48E1 only supports reset to zero + select port(ffrstmux, BA).is_fully_zero() + + define pol (BA == \B) + set ffrstpol pol + semioptional +endmatch + +code argD + if (ffrstmux) { + dffrstmux = ffrstmux; + dffrstpol = ffrstpol; + argD = port(ffrstmux, ffrstpol ? \A : \B); + dffD.replace(port(ffrstmux, \Y), argD); + + // Only search for ffcemux if argQ has at + // least 3 users (ff, , ffrstmux) and + // dffD only has two (ff, ffrstmux) + if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) + argD = SigSpec(); + } + else + dffrstmux = nullptr; +endcode + +match ffcemux + if !argD.empty() + select ffcemux->type.in($mux) + index port(ffcemux, \Y) === argD + choice AB {\A, \B} + index port(ffcemux, AB) === argQ + define pol (AB == \A) + set ffcepol pol + semioptional +endmatch + +code argD + if (ffcemux) { + dffcemux = ffcemux; + dffcepol = ffcepol; + argD = port(ffcemux, ffcepol ? \B : \A); + dffD.replace(port(ffcemux, \Y), argD); + } + else + dffcemux = nullptr; +endcode From eb597431f03cb402db4fc8a514c031efc29e6580 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 12:18:37 -0700 Subject: [PATCH 306/356] Do not run xilinx_dsp_cascadeAB for now --- passes/pmgen/xilinx_dsp.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 7530eb5ad..4790cc69d 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -551,7 +551,8 @@ struct XilinxDspPass : public Pass { did_something = false; xilinx_dsp_cascade_pm pmc(module, module->selected_cells()); pmc.run_xilinx_dsp_cascadeP(); - pmc.run_xilinx_dsp_cascadeAB(); + //pmc.run_xilinx_dsp_cascadeAB(); + break; } while (did_something); } } From 95644b00cb7544bb284f8071c5a2da70f3899b7c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 12:37:29 -0700 Subject: [PATCH 307/356] OPMODE is port not param --- passes/pmgen/xilinx_dsp_cascade.pmg | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg index 996a3b80f..19fe48bba 100644 --- a/passes/pmgen/xilinx_dsp_cascade.pmg +++ b/passes/pmgen/xilinx_dsp_cascade.pmg @@ -67,17 +67,16 @@ code add_siguser(cascade, dsp_pcin); add_siguser(cascade, dsp); - SigSpec opmode = param(dsp_pcin, \OPMODE, Const(0, 7)); + SigSpec opmode = port(dsp_pcin, \OPMODE, Const(0, 7)); if (dsp_pcout) opmode[6] = State::S0; else if (dsp_pcout_shift17) opmode[6] = State::S1; else log_abort(); - opmode[5] = State::S0; opmode[4] = State::S1; - dsp_pcin->setPort(ID(OPMODE), opmode); + dsp_pcin->setPort(\OPMODE, opmode); log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); @@ -196,7 +195,7 @@ match dspQA2 select nusers(port(dspQA2, \ACOUT, SigSpec())) == 0 slice offset GetSize(port(dspQA2, \A)) index port(dspQA2, \A)[offset] === sigA[0] - index port(dspQA2, \CLK) === port(dspD, \CLK) + index port(dspQA2, \CLK, State::S0) === port(dspD, \CLK, State::S0) // Check that the rest of sigA is present filter GetSize(port(dspQA2, \A)) >= offset + GetSize(sigA) @@ -257,7 +256,7 @@ match dspQA1 select nusers(port(dspQA1, \ACOUT, SigSpec())) == 0 slice offset GetSize(port(dspQA1, \A)) index port(dspQA1, \A)[offset] === sigA[0] - index port(dspQA1, \CLK) === port(dspD, \CLK) + index port(dspQA1, \CLK, State::S0) === port(dspD, \CLK, State::S0) // Check that the rest of sigA is present filter GetSize(port(dspQA1, \A)) >= offset + GetSize(sigA) @@ -348,7 +347,7 @@ match dspQB2 select nusers(port(dspQB2, \BCOUT, SigSpec())) == 0 slice offset GetSize(port(dspQB2, \B)) index port(dspQB2, \B)[offset] === sigB[0] - index port(dspQB2, \CLK) === port(dspD, \CLK) + index port(dspQB2, \CLK, State::S0) === port(dspD, \CLK, State::S0) // Check that the rest of sigB is present filter GetSize(port(dspQB2, \B)) >= offset + GetSize(sigB) @@ -402,7 +401,7 @@ match dspQB1 select nusers(port(dspQB1, \BCOUT, SigSpec())) == 0 slice offset GetSize(port(dspQB1, \B)) index port(dspQB1, \B)[offset] === sigB[0] - index port(dspQB1, \CLK) === port(dspD, \CLK) + index port(dspQB1, \CLK, State::S0) === port(dspD, \CLK, State::S0) // Check that the rest of sigB is present filter GetSize(port(dspQB1, \B)) >= offset + GetSize(sigB) From d122083a112d51ba0d91e44c37b1d4d9d11080aa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 12:42:28 -0700 Subject: [PATCH 308/356] Output pattern matcher items as log_debug() --- passes/pmgen/ice40_dsp.cc | 24 +++++++++++------------- passes/pmgen/xilinx_dsp.cc | 34 ++++++++++++++++------------------ 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 0b7ffe64b..641efe076 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -29,21 +29,19 @@ void create_ice40_dsp(ice40_dsp_pm &pm) { auto &st = pm.st_ice40_dsp; -#if 1 - log("\n"); - log("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAholdmux, "--"), log_id(st.ffArstmux, "--")); - log("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBholdmux, "--"), log_id(st.ffBrstmux, "--")); - log("ffCD: %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDholdmux, "--")); - log("mul: %s\n", log_id(st.mul, "--")); - log("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); - log("ffH: %s\n", log_id(st.ffH, "--")); - log("add: %s\n", log_id(st.add, "--")); - log("mux: %s\n", log_id(st.mux, "--")); - log("ffO: %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOholdmux, "--"), log_id(st.ffOrstmux, "--")); -#endif - log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); + log_debug("\n"); + log_debug("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAholdmux, "--"), log_id(st.ffArstmux, "--")); + log_debug("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBholdmux, "--"), log_id(st.ffBrstmux, "--")); + log_debug("ffCD: %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDholdmux, "--")); + log_debug("mul: %s\n", log_id(st.mul, "--")); + log_debug("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); + log_debug("ffH: %s\n", log_id(st.ffH, "--")); + log_debug("add: %s\n", log_id(st.add, "--")); + log_debug("mux: %s\n", log_id(st.mux, "--")); + log_debug("ffO: %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOholdmux, "--"), log_id(st.ffOrstmux, "--")); + if (GetSize(st.sigA) > 16) { log(" input A (%s) is too large (%d > 16).\n", log_signal(st.sigA), GetSize(st.sigA)); return; diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 4790cc69d..1612b66ec 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -260,26 +260,24 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) { auto &st = pm.st_xilinx_dsp_pack; -#if 1 - log("\n"); - log("preAdd: %s\n", log_id(st.preAdd, "--")); - log("ffAD: %s %s %s\n", log_id(st.ffAD, "--"), log_id(st.ffADcemux, "--"), log_id(st.ffADrstmux, "--")); - log("ffA2: %s %s %s\n", log_id(st.ffA2, "--"), log_id(st.ffA2cemux, "--"), log_id(st.ffA2rstmux, "--")); - log("ffA1: %s %s %s\n", log_id(st.ffA1, "--"), log_id(st.ffA1cemux, "--"), log_id(st.ffA1rstmux, "--")); - log("ffB2: %s %s %s\n", log_id(st.ffB2, "--"), log_id(st.ffB2cemux, "--"), log_id(st.ffB2rstmux, "--")); - log("ffB1: %s %s %s\n", log_id(st.ffB1, "--"), log_id(st.ffB1cemux, "--"), log_id(st.ffB1rstmux, "--")); - log("ffC: %s %s %s\n", log_id(st.ffC, "--"), log_id(st.ffCcemux, "--"), log_id(st.ffCrstmux, "--")); - log("ffD: %s %s %s\n", log_id(st.ffD, "--"), log_id(st.ffDcemux, "--"), log_id(st.ffDrstmux, "--")); - log("dsp: %s\n", log_id(st.dsp, "--")); - log("ffM: %s %s %s\n", log_id(st.ffM, "--"), log_id(st.ffMcemux, "--"), log_id(st.ffMrstmux, "--")); - log("postAdd: %s\n", log_id(st.postAdd, "--")); - log("postAddMux: %s\n", log_id(st.postAddMux, "--")); - log("ffP: %s %s %s\n", log_id(st.ffP, "--"), log_id(st.ffPcemux, "--"), log_id(st.ffPrstmux, "--")); - log("overflow: %s\n", log_id(st.overflow, "--")); -#endif - log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); + log_debug("\n"); + log_debug("preAdd: %s\n", log_id(st.preAdd, "--")); + log_debug("ffAD: %s %s %s\n", log_id(st.ffAD, "--"), log_id(st.ffADcemux, "--"), log_id(st.ffADrstmux, "--")); + log_debug("ffA2: %s %s %s\n", log_id(st.ffA2, "--"), log_id(st.ffA2cemux, "--"), log_id(st.ffA2rstmux, "--")); + log_debug("ffA1: %s %s %s\n", log_id(st.ffA1, "--"), log_id(st.ffA1cemux, "--"), log_id(st.ffA1rstmux, "--")); + log_debug("ffB2: %s %s %s\n", log_id(st.ffB2, "--"), log_id(st.ffB2cemux, "--"), log_id(st.ffB2rstmux, "--")); + log_debug("ffB1: %s %s %s\n", log_id(st.ffB1, "--"), log_id(st.ffB1cemux, "--"), log_id(st.ffB1rstmux, "--")); + log_debug("ffC: %s %s %s\n", log_id(st.ffC, "--"), log_id(st.ffCcemux, "--"), log_id(st.ffCrstmux, "--")); + log_debug("ffD: %s %s %s\n", log_id(st.ffD, "--"), log_id(st.ffDcemux, "--"), log_id(st.ffDrstmux, "--")); + log_debug("dsp: %s\n", log_id(st.dsp, "--")); + log_debug("ffM: %s %s %s\n", log_id(st.ffM, "--"), log_id(st.ffMcemux, "--"), log_id(st.ffMrstmux, "--")); + log_debug("postAdd: %s\n", log_id(st.postAdd, "--")); + log_debug("postAddMux: %s\n", log_id(st.postAddMux, "--")); + log_debug("ffP: %s %s %s\n", log_id(st.ffP, "--"), log_id(st.ffPcemux, "--"), log_id(st.ffPrstmux, "--")); + log_debug("overflow: %s\n", log_id(st.overflow, "--")); + Cell *cell = st.dsp; if (st.preAdd) { From 53817b85753deb3dc5647414de67de1373798049 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 14:21:22 -0700 Subject: [PATCH 309/356] Use new port/param overload in pmg --- passes/pmgen/ice40_dsp.pmg | 4 ++-- passes/pmgen/xilinx_dsp.cc | 2 +- passes/pmgen/xilinx_dsp.pmg | 8 ++++---- passes/pmgen/xilinx_srl.pmg | 30 +++++++++++++++--------------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 19ee9054b..046aae9e2 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -225,9 +225,9 @@ endcode code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_pol cd_signed o_lo if (mul->type != \SB_MAC16 || // Ensure that register is not already used - ((mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1) && + ((param(mul, \TOPOUTPUT_SELECT, 0).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT, 0).as_int() != 1) && // Ensure that OLOADTOP/OLOADBOT is unused or zero - (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero()))) { + (port(mul, \OLOADTOP, State::S0).is_fully_zero() && port(mul, \OLOADBOT, State::S0).is_fully_zero()))) { dff = nullptr; diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 1612b66ec..9d0a77e2b 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -290,7 +290,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) st.sigD.extend_u0(25, D_SIGNED); cell->setPort(ID(A), st.sigA); cell->setPort(ID(D), st.sigD); - cell->connections_.at(ID(INMODE)) = Const::from_string("00100"); + cell->setPort(ID(INMODE), Const::from_string("00100")); if (st.ffAD) { if (st.ffADcemux) { diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 7d34c6a78..bb29bdd99 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -42,7 +42,7 @@ code sigA sigB sigC sigD sigM sigD = dsp->connections_.at(\D, SigSpec()); SigSpec P = port(dsp, \P); - if (dsp->parameters.at(\USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") { + if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") { // Only care about those bits that are used int i; for (i = 0; i < GetSize(P); i++) { @@ -79,8 +79,8 @@ endcode match preAdd if sigD.empty() || sigD.is_fully_zero() // Ensure that preAdder not already used - if dsp->parameters.at(\USE_DPORT, Const("FALSE")).decode_string() == "FALSE" - if dsp->connections_.at(\INMODE, Const(0, 5)).is_fully_zero() + if param(dsp, \USE_DPORT, Const("FALSE")).decode_string() == "FALSE" + if port(dsp, \INMODE, Const(0, 5)).is_fully_zero() select preAdd->type.in($add) // Output has to be 25 bits or less @@ -348,7 +348,7 @@ endcode match overflow if ffP - if dsp->parameters.at(\USE_PATTERN_DETECT, Const("NO_PATDET")).decode_string() == "NO_PATDET" + if param(dsp, \USE_PATTERN_DETECT, Const("NO_PATDET")).decode_string() == "NO_PATDET" select overflow->type.in($ge) select GetSize(port(overflow, \Y)) <= 48 select port(overflow, \B).is_fully_const() diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index b18119b87..535b3dfdc 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -13,9 +13,9 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->has_keep_attr() - select !first->type.in(\FDRE) || !first->parameters.at(\IS_R_INVERTED, State::S0).as_bool() - select !first->type.in(\FDRE) || !first->parameters.at(\IS_D_INVERTED, State::S0).as_bool() - select !first->type.in(\FDRE, \FDRE_1) || first->connections_.at(\R, State::S0).is_fully_zero() + select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED, State::S0).as_bool() + select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED, State::S0).as_bool() + select !first->type.in(\FDRE, \FDRE_1) || port(first, \R, State::S0).is_fully_zero() filter !non_first_cells.count(first) generate SigSpec C = module->addWire(NEW_ID); @@ -84,9 +84,9 @@ arg en_port match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->has_keep_attr() - select !first->type.in(\FDRE) || !first->parameters.at(\IS_R_INVERTED, State::S0).as_bool() - select !first->type.in(\FDRE) || !first->parameters.at(\IS_D_INVERTED, State::S0).as_bool() - select !first->type.in(\FDRE, \FDRE_1) || first->connections_.at(\R, State::S0).is_fully_zero() + select !first->type.in(\FDRE) || !param(first, \IS_R_INVERTED, State::S0).as_bool() + select !first->type.in(\FDRE) || !param(first, \IS_D_INVERTED, State::S0).as_bool() + select !first->type.in(\FDRE, \FDRE_1) || port(first, \R, State::S0).is_fully_zero() endmatch code clk_port en_port @@ -111,10 +111,10 @@ match next index port(next, \Q) === port(first, \D) filter port(next, clk_port) == port(first, clk_port) filter en_port == IdString() || port(next, en_port) == port(first, en_port) - filter !first->type.in(\FDRE) || next->parameters.at(\IS_C_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_C_INVERTED, State::S0).as_bool() - filter !first->type.in(\FDRE) || next->parameters.at(\IS_D_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_D_INVERTED, State::S0).as_bool() - filter !first->type.in(\FDRE) || next->parameters.at(\IS_R_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_R_INVERTED, State::S0).as_bool() - filter !first->type.in(\FDRE, \FDRE_1) || next->connections_.at(\R, State::S0).is_fully_zero() + filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED, State::S0).as_bool() == param(first, \IS_C_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED, State::S0).as_bool() == param(first, \IS_D_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED, State::S0).as_bool() == param(first, \IS_R_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R, State::S0).is_fully_zero() endmatch code @@ -138,10 +138,10 @@ match next index port(next, \Q) === port(chain.back(), \D) filter port(next, clk_port) == port(first, clk_port) filter en_port == IdString() || port(next, en_port) == port(first, en_port) - filter !first->type.in(\FDRE) || next->parameters.at(\IS_C_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_C_INVERTED, State::S0).as_bool() - filter !first->type.in(\FDRE) || next->parameters.at(\IS_D_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_D_INVERTED, State::S0).as_bool() - filter !first->type.in(\FDRE) || next->parameters.at(\IS_R_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_R_INVERTED, State::S0).as_bool() - filter !first->type.in(\FDRE, \FDRE_1) || next->connections_.at(\R, State::S0).is_fully_zero() + filter !first->type.in(\FDRE) || param(next, \IS_C_INVERTED, State::S0).as_bool() == param(first, \IS_C_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || param(next, \IS_D_INVERTED, State::S0).as_bool() == param(first, \IS_D_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || param(next, \IS_R_INVERTED, State::S0).as_bool() == param(first, \IS_R_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R, State::S0).is_fully_zero() generate Cell *cell = module->addCell(NEW_ID, chain.back()->type); cell->setPort(\C, chain.back()->getPort(\C)); @@ -149,7 +149,7 @@ generate cell->setPort(\Q, chain.back()->getPort(\D)); if (cell->type == \FDRE) { if (rng(2) == 0) - cell->setPort(\R, chain.back()->connections_.at(\R, State::S0)); + cell->setPort(\R, port(chain.back(), \R, State::S0)); cell->setPort(\CE, chain.back()->getPort(\CE)); } else if (cell->type.begins_with("$_DFFE_")) From 4401e5f142d9728c09ac95e1cab9b30c449210fe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Sep 2019 14:24:31 -0700 Subject: [PATCH 310/356] Grammar --- techlibs/xilinx/abc_model.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index 1c69dd21c..0a8d531d7 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -47,7 +47,7 @@ endmodule // Modules used to model the comb/seq behaviour of DSP48E1 // With abc_map.v responsible for splicing the below modules -// into between the combinatorial DSP48E1 box (e.g. disconnecting +// between the combinatorial DSP48E1 box (e.g. disconnecting // A when AREG, MREG or PREG is enabled and splicing in the // "$__ABC_DSP48E1_REG" blackbox as "REG" in the diagram below) // this acts to first disables the combinatorial path (as there From a67af3d5e5fd584837f55d2d97d621299e4fdf0c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 13:00:44 -0700 Subject: [PATCH 311/356] Use new port() overload once more --- passes/pmgen/xilinx_dsp.pmg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index bb29bdd99..80bf775bc 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -38,8 +38,8 @@ code sigA sigB sigC sigD sigM sigA = unextend(port(dsp, \A)); sigB = unextend(port(dsp, \B)); - sigC = dsp->connections_.at(\C, SigSpec()); - sigD = dsp->connections_.at(\D, SigSpec()); + sigC = port(dsp, \C, SigSpec()); + sigD = port(dsp, \D, SigSpec()); SigSpec P = port(dsp, \P); if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") { From d0dbbc26054d1cd7b8766e2d996196e246216e8c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 13:26:34 -0700 Subject: [PATCH 312/356] Move unextend initialisation later --- passes/pmgen/xilinx_dsp_cascade.pmg | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg index 19fe48bba..37674efea 100644 --- a/passes/pmgen/xilinx_dsp_cascade.pmg +++ b/passes/pmgen/xilinx_dsp_cascade.pmg @@ -3,19 +3,6 @@ pattern xilinx_dsp_cascadeP udata > unextend state sigC -code - unextend = [](const SigSpec &sig) { - int i; - for (i = GetSize(sig)-1; i > 0; i--) - if (sig[i] != sig[i-1]) - break; - // Do not remove non-const sign bit - if (sig[i].wire) - ++i; - return sig.extract(0, i); - }; -endcode - match dsp_pcin select dsp_pcin->type.in(\DSP48E1) select !param(dsp_pcin, \CREG, State::S1).as_bool() @@ -25,6 +12,16 @@ match dsp_pcin endmatch code sigC + unextend = [](const SigSpec &sig) { + int i; + for (i = GetSize(sig)-1; i > 0; i--) + if (sig[i] != sig[i-1]) + break; + // Do not remove non-const sign bit + if (sig[i].wire) + ++i; + return sig.extract(0, i); + }; sigC = unextend(port(dsp_pcin, \C)); endcode From 26a6c55665e3d7826779d27f32031e58296ed68d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 13:27:00 -0700 Subject: [PATCH 313/356] Move log_debug("\n") later --- passes/pmgen/ice40_dsp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 641efe076..f60e67158 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -31,7 +31,6 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); - log_debug("\n"); log_debug("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAholdmux, "--"), log_id(st.ffArstmux, "--")); log_debug("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBholdmux, "--"), log_id(st.ffBrstmux, "--")); log_debug("ffCD: %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDholdmux, "--")); @@ -41,6 +40,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log_debug("add: %s\n", log_id(st.add, "--")); log_debug("mux: %s\n", log_id(st.mux, "--")); log_debug("ffO: %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOholdmux, "--"), log_id(st.ffOrstmux, "--")); + log_debug("\n"); if (GetSize(st.sigA) > 16) { log(" input A (%s) is too large (%d > 16).\n", log_signal(st.sigA), GetSize(st.sigA)); From 15dfbc812517a284848618eb60e3f9875c2e26ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 13:27:10 -0700 Subject: [PATCH 314/356] Separate out CREG packing into new pattern, to avoid conflict with PREG --- passes/pmgen/Makefile.inc | 3 +- passes/pmgen/xilinx_dsp.cc | 108 +++++++++++++++---- passes/pmgen/xilinx_dsp.pmg | 30 ++---- passes/pmgen/xilinx_dsp_CREG.pmg | 178 +++++++++++++++++++++++++++++++ 4 files changed, 273 insertions(+), 46 deletions(-) create mode 100644 passes/pmgen/xilinx_dsp_CREG.pmg diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 82bb40ac8..366c37943 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -22,8 +22,9 @@ $(eval $(call add_extra_objs,passes/pmgen/ice40_wrapcarry_pm.h)) # -------------------------------------- OBJS += passes/pmgen/xilinx_dsp.o -passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h passes/pmgen/xilinx_dsp_cascade_pm.h +passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h passes/pmgen/xilinx_dsp_CREG_pm.h passes/pmgen/xilinx_dsp_cascade_pm.h $(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_pm.h)) +$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_CREG_pm.h)) $(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_cascade_pm.h)) # -------------------------------------- diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 9d0a77e2b..86472feb5 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -27,6 +27,7 @@ PRIVATE_NAMESPACE_BEGIN bool did_something; #include "passes/pmgen/xilinx_dsp_pm.h" +#include "passes/pmgen/xilinx_dsp_CREG_pm.h" #include "passes/pmgen/xilinx_dsp_cascade_pm.h" static Cell* addDsp(Module *module) { @@ -63,7 +64,7 @@ static Cell* addDsp(Module *module) { return cell; } -void pack_xilinx_simd(Module *module, const std::vector &selected_cells) +void xilinx_simd_pack(Module *module, const std::vector &selected_cells) { std::deque simd12_add, simd12_sub; std::deque simd24_add, simd24_sub; @@ -255,21 +256,18 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) g24(simd24_sub); } - -void pack_xilinx_dsp(xilinx_dsp_pm &pm) +void xilinx_dsp_pack(xilinx_dsp_pm &pm) { auto &st = pm.st_xilinx_dsp_pack; log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); - log_debug("\n"); log_debug("preAdd: %s\n", log_id(st.preAdd, "--")); log_debug("ffAD: %s %s %s\n", log_id(st.ffAD, "--"), log_id(st.ffADcemux, "--"), log_id(st.ffADrstmux, "--")); log_debug("ffA2: %s %s %s\n", log_id(st.ffA2, "--"), log_id(st.ffA2cemux, "--"), log_id(st.ffA2rstmux, "--")); log_debug("ffA1: %s %s %s\n", log_id(st.ffA1, "--"), log_id(st.ffA1cemux, "--"), log_id(st.ffA1rstmux, "--")); log_debug("ffB2: %s %s %s\n", log_id(st.ffB2, "--"), log_id(st.ffB2cemux, "--"), log_id(st.ffB2rstmux, "--")); log_debug("ffB1: %s %s %s\n", log_id(st.ffB1, "--"), log_id(st.ffB1cemux, "--"), log_id(st.ffB1rstmux, "--")); - log_debug("ffC: %s %s %s\n", log_id(st.ffC, "--"), log_id(st.ffCcemux, "--"), log_id(st.ffCrstmux, "--")); log_debug("ffD: %s %s %s\n", log_id(st.ffD, "--"), log_id(st.ffDcemux, "--"), log_id(st.ffDrstmux, "--")); log_debug("dsp: %s\n", log_id(st.dsp, "--")); log_debug("ffM: %s %s %s\n", log_id(st.ffM, "--"), log_id(st.ffMcemux, "--"), log_id(st.ffMrstmux, "--")); @@ -277,6 +275,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log_debug("postAddMux: %s\n", log_id(st.postAddMux, "--")); log_debug("ffP: %s %s %s\n", log_id(st.ffP, "--"), log_id(st.ffPcemux, "--"), log_id(st.ffPrstmux, "--")); log_debug("overflow: %s\n", log_id(st.overflow, "--")); + log_debug("\n"); Cell *cell = st.dsp; @@ -426,12 +425,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) else cell->setParam(ID(BREG), 1); } - if (st.ffC) { - SigSpec &C = cell->connections_.at(ID(C)); - f(C, st.ffC, st.ffCcemux, st.ffCcepol, ID(CEC), st.ffCrstmux, st.ffCrstpol, ID(RSTC)); - pm.add_siguser(C, cell); - cell->setParam(ID(CREG), 1); - } if (st.ffD) { SigSpec &D = cell->connections_.at(ID(D)); f(D, st.ffD, st.ffDcemux, st.ffDcepol, ID(CED), st.ffDrstmux, st.ffDrstpol, ID(RSTD)); @@ -468,9 +461,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) log(" ffB1:%s", log_id(st.ffB1)); } - if (st.ffC) - log(" ffC:%s", log_id(st.ffC)); - if (st.ffD) log(" ffD:%s", log_id(st.ffD)); @@ -491,6 +481,76 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) pm.blacklist(cell); } +void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) +{ + auto &st = pm.st_xilinx_dsp_packC; + + log_debug("Analysing %s.%s for Xilinx DSP packing (CREG).\n", log_id(pm.module), log_id(st.dsp)); + log_debug("ffC: %s %s %s\n", log_id(st.ffC, "--"), log_id(st.ffCcemux, "--"), log_id(st.ffCrstmux, "--")); + log_debug("\n"); + + Cell *cell = st.dsp; + + if (st.clock != SigBit()) + { + cell->setPort(ID(CLK), st.clock); + + auto f = [&pm,cell](SigSpec &A, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) { + SigSpec D = ff->getPort(ID(D)); + SigSpec Q = pm.sigmap(ff->getPort(ID(Q))); + if (!A.empty()) + A.replace(Q, D); + if (rstmux) { + SigSpec Y = rstmux->getPort(ID(Y)); + SigSpec AB = rstmux->getPort(rstpol ? ID(A) : ID(B)); + if (!A.empty()) + A.replace(Y, AB); + if (rstport != IdString()) { + SigSpec S = rstmux->getPort(ID(S)); + cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S)); + } + } + else if (rstport != IdString()) + cell->setPort(rstport, State::S0); + if (cemux) { + SigSpec Y = cemux->getPort(ID(Y)); + SigSpec BA = cemux->getPort(cepol ? ID(B) : ID(A)); + SigSpec S = cemux->getPort(ID(S)); + if (!A.empty()) + A.replace(Y, BA); + cell->setPort(ceport, cepol ? S : pm.module->Not(NEW_ID, S)); + } + else + cell->setPort(ceport, State::S1); + + for (auto c : Q.chunks()) { + auto it = c.wire->attributes.find(ID(init)); + if (it == c.wire->attributes.end()) + continue; + for (int i = c.offset; i < c.offset+c.width; i++) { + log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); + it->second[i] = State::Sx; + } + } + }; + + if (st.ffC) { + SigSpec &C = cell->connections_.at(ID(C)); + f(C, st.ffC, st.ffCcemux, st.ffCcepol, ID(CEC), st.ffCrstmux, st.ffCrstpol, ID(RSTC)); + pm.add_siguser(C, cell); + cell->setParam(ID(CREG), 1); + } + + log(" clock: %s (%s)", log_signal(st.clock), "posedge"); + + if (st.ffC) + log(" ffC:%s", log_id(st.ffC)); + log("\n"); + } + + pm.blacklist(cell); +} + struct XilinxDspPass : public Pass { XilinxDspPass() : Pass("xilinx_dsp", "Xilinx: pack resources into DSPs") { } void help() YS_OVERRIDE @@ -540,17 +600,23 @@ struct XilinxDspPass : public Pass { extra_args(args, argidx, design); for (auto module : design->selected_modules()) { - pack_xilinx_simd(module, module->selected_cells()); + xilinx_simd_pack(module, module->selected_cells()); - xilinx_dsp_pm pm(module, module->selected_cells()); - pm.run_xilinx_dsp_pack(pack_xilinx_dsp); + { + xilinx_dsp_pm pm(module, module->selected_cells()); + pm.run_xilinx_dsp_pack(xilinx_dsp_pack); + } + { + xilinx_dsp_CREG_pm pm(module, module->selected_cells()); + pm.run_xilinx_dsp_packC(xilinx_dsp_packC); + } do { did_something = false; - xilinx_dsp_cascade_pm pmc(module, module->selected_cells()); - pmc.run_xilinx_dsp_cascadeP(); - //pmc.run_xilinx_dsp_cascadeAB(); - break; + xilinx_dsp_cascade_pm pm(module, module->selected_cells()); + pm.run_xilinx_dsp_cascadeP(); + //pm.run_xilinx_dsp_cascadeAB(); + break; } while (did_something); } } diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 80bf775bc..553195649 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -4,11 +4,11 @@ udata > unextend state clock state sigA sigB sigC sigD sigM sigP state postAddAB postAddMuxAB -state ffA1cepol ffA2cepol ffADcepol ffB1cepol ffB2cepol ffCcepol ffDcepol ffMcepol ffPcepol -state ffArstpol ffADrstpol ffBrstpol ffCrstpol ffDrstpol ffMrstpol ffPrstpol +state ffA1cepol ffA2cepol ffADcepol ffB1cepol ffB2cepol ffDcepol ffMcepol ffPcepol +state ffArstpol ffADrstpol ffBrstpol ffDrstpol ffMrstpol ffPrstpol state ffAD ffADcemux ffADrstmux ffA1 ffA1cemux ffA1rstmux ffA2 ffA2cemux ffA2rstmux -state ffB1 ffB1cemux ffB1rstmux ffB2 ffB2cemux ffB2rstmux ffC ffCcemux ffCrstmux +state ffB1 ffB1cemux ffB1rstmux ffB2 ffB2cemux ffB2rstmux state ffD ffDcemux ffDrstmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux // subpattern @@ -24,7 +24,7 @@ match dsp select dsp->type.in(\DSP48E1) endmatch -code sigA sigB sigC sigD sigM +code sigA sigB sigC sigD sigM clock unextend = [](const SigSpec &sig) { int i; for (i = GetSize(sig)-1; i > 0; i--) @@ -54,6 +54,8 @@ code sigA sigB sigC sigD sigM } else sigM = P; + + clock = port(dsp, \CLK, SigBit()); endcode code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock @@ -326,26 +328,6 @@ code sigC sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A); endcode -code argQ ffC ffCcemux ffCrstmux ffCcepol ffCrstpol sigC clock - if (param(dsp, \CREG).as_int() == 0 && sigC != sigP) { - argQ = sigC; - subpattern(in_dffe); - if (dff) { - ffC = dff; - clock = dffclock; - if (dffrstmux) { - ffCrstmux = dffrstmux; - ffCrstpol = dffrstpol; - } - if (dffcemux) { - ffCcemux = dffcemux; - ffCcepol = dffcepol; - } - sigC = dffD; - } - } -endcode - match overflow if ffP if param(dsp, \USE_PATTERN_DETECT, Const("NO_PATDET")).decode_string() == "NO_PATDET" diff --git a/passes/pmgen/xilinx_dsp_CREG.pmg b/passes/pmgen/xilinx_dsp_CREG.pmg new file mode 100644 index 000000000..d79abdd4a --- /dev/null +++ b/passes/pmgen/xilinx_dsp_CREG.pmg @@ -0,0 +1,178 @@ +pattern xilinx_dsp_packC + +udata > unextend +state clock +state sigC sigP +state ffCcepol ffCrstpol +state ffC ffCcemux ffCrstmux + +// subpattern +state argQ argD +state ffcepol ffrstpol +state ffoffset +udata dffD dffQ +udata dffclock +udata dff dffcemux dffrstmux +udata dffcepol dffrstpol + +match dsp + select dsp->type.in(\DSP48E1) + select param(dsp, \CREG, 1).as_int() == 0 + select nusers(port(dsp, \C, SigSpec())) > 1 +endmatch + +code argQ ffC ffCcemux ffCrstmux ffCcepol ffCrstpol sigC sigP clock + unextend = [](const SigSpec &sig) { + int i; + for (i = GetSize(sig)-1; i > 0; i--) + if (sig[i] != sig[i-1]) + break; + // Do not remove non-const sign bit + if (sig[i].wire) + ++i; + return sig.extract(0, i); + }; + sigC = unextend(port(dsp, \C, SigSpec())); + + SigSpec P = port(dsp, \P); + if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") { + // Only care about those bits that are used + int i; + for (i = 0; i < GetSize(P); i++) { + if (nusers(P[i]) <= 1) + break; + sigP.append(P[i]); + } + log_assert(nusers(P.extract_end(i)) <= 1); + } + else + sigP = P; + + if (sigC == sigP) + reject; + + clock = port(dsp, \CLK, SigBit()); + + argQ = sigC; + subpattern(in_dffe); + if (dff) { + ffC = dff; + clock = dffclock; + if (dffrstmux) { + ffCrstmux = dffrstmux; + ffCrstpol = dffrstpol; + } + if (dffcemux) { + ffCcemux = dffcemux; + ffCcepol = dffcepol; + } + sigC = dffD; + } +endcode + +code + if (ffC) + accept; +endcode + +// ####################### + +subpattern in_dffe +arg argD argQ clock + +code + dff = nullptr; + for (auto c : argQ.chunks()) { + if (!c.wire) + reject; + if (c.wire->get_bool_attribute(\keep)) + reject; + } +endcode + +match ff + select ff->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ff, \CLK_POLARITY).as_bool() + + slice offset GetSize(port(ff, \D)) + index port(ff, \Q)[offset] === argQ[0] + + // Check that the rest of argQ is present + filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ) + filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ + + set ffoffset offset +endmatch + +code argQ argD +{ + if (clock != SigBit() && port(ff, \CLK) != clock) + reject; + + SigSpec Q = port(ff, \Q); + dff = ff; + dffclock = port(ff, \CLK); + dffD = argQ; + argD = port(ff, \D); + argQ = Q; + dffD.replace(argQ, argD); + // Only search for ffrstmux if dffD only + // has two (ff, ffrstmux) users + if (nusers(dffD) > 2) + argD = SigSpec(); +} +endcode + +match ffrstmux + if !argD.empty() + select ffrstmux->type.in($mux) + index port(ffrstmux, \Y) === argD + + choice BA {\B, \A} + // DSP48E1 only supports reset to zero + select port(ffrstmux, BA).is_fully_zero() + + define pol (BA == \B) + set ffrstpol pol + semioptional +endmatch + +code argD + if (ffrstmux) { + dffrstmux = ffrstmux; + dffrstpol = ffrstpol; + argD = port(ffrstmux, ffrstpol ? \A : \B); + dffD.replace(port(ffrstmux, \Y), argD); + + // Only search for ffcemux if argQ has at + // least 3 users (ff, , ffrstmux) and + // dffD only has two (ff, ffrstmux) + if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) + argD = SigSpec(); + } + else + dffrstmux = nullptr; +endcode + +match ffcemux + if !argD.empty() + select ffcemux->type.in($mux) + index port(ffcemux, \Y) === argD + choice AB {\A, \B} + index port(ffcemux, AB) === argQ + define pol (AB == \A) + set ffcepol pol + semioptional +endmatch + +code argD + if (ffcemux) { + dffcemux = ffcemux; + dffcepol = ffcepol; + argD = port(ffcemux, ffcepol ? \B : \A); + dffD.replace(port(ffcemux, \Y), argD); + } + else + dffcemux = nullptr; +endcode From b824a56cde5aa692da2dc6b6a0d161a98daac6ef Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 13:58:10 -0700 Subject: [PATCH 315/356] Comment to explain separating CREG packing --- passes/pmgen/xilinx_dsp.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 86472feb5..a145ab184 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -606,6 +606,14 @@ struct XilinxDspPass : public Pass { xilinx_dsp_pm pm(module, module->selected_cells()); pm.run_xilinx_dsp_pack(xilinx_dsp_pack); } + // Separating out CREG packing is necessary since there + // is no guarantee that the cell ordering corresponds + // to the "expected" case (i.e. the order in which + // they appear in the source) thus the possiblity + // existed that a register got packed as CREG into a + // downstream DSP that should have otherwise been a + // PREG of an upstream DSP that had not been pattern + // matched yet { xilinx_dsp_CREG_pm pm(module, module->selected_cells()); pm.run_xilinx_dsp_packC(xilinx_dsp_packC); From e556d48d45b0795f5fb69333b55b9f7de90ff44d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 16:00:11 -0700 Subject: [PATCH 316/356] Set [AB]CASCREG to legal values --- passes/pmgen/xilinx_dsp.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index a145ab184..22df3e009 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -275,7 +275,6 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) log_debug("postAddMux: %s\n", log_id(st.postAddMux, "--")); log_debug("ffP: %s %s %s\n", log_id(st.ffP, "--"), log_id(st.ffPcemux, "--"), log_id(st.ffPrstmux, "--")); log_debug("overflow: %s\n", log_id(st.overflow, "--")); - log_debug("\n"); Cell *cell = st.dsp; @@ -410,9 +409,12 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) if (st.ffA1) { f(A, st.ffA1, st.ffA1cemux, st.ffA1cepol, ID(CEA1), st.ffA1rstmux, st.ffArstpol, IdString()); cell->setParam(ID(AREG), 2); + cell->setParam(ID(ACASCREG), 2); } - else + else { cell->setParam(ID(AREG), 1); + cell->setParam(ID(ACASCREG), 1); + } } if (st.ffB2) { SigSpec &B = cell->connections_.at(ID(B)); @@ -421,9 +423,12 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) if (st.ffB1) { f(B, st.ffB1, st.ffB1cemux, st.ffB1cepol, ID(CEB1), st.ffB1rstmux, st.ffBrstpol, IdString()); cell->setParam(ID(BREG), 2); + cell->setParam(ID(BCASCREG), 2); } - else + else { cell->setParam(ID(BREG), 1); + cell->setParam(ID(BCASCREG), 1); + } } if (st.ffD) { SigSpec &D = cell->connections_.at(ID(D)); @@ -469,9 +474,8 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) if (st.ffP) log(" ffP:%s", log_id(st.ffP)); - - log("\n"); } + log("\n"); SigSpec P = st.sigP; if (GetSize(P) < 48) @@ -624,7 +628,7 @@ struct XilinxDspPass : public Pass { xilinx_dsp_cascade_pm pm(module, module->selected_cells()); pm.run_xilinx_dsp_cascadeP(); //pm.run_xilinx_dsp_cascadeAB(); - break; + break; } while (did_something); } } From 23d90e0439ffef510632ce45a3d2aff1c129f405 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 18:56:02 -0700 Subject: [PATCH 317/356] Add a xilinx_finalise pass --- techlibs/xilinx/Makefile.inc | 1 + techlibs/xilinx/synth_xilinx.cc | 2 + techlibs/xilinx/xilinx_finalise.cc | 84 ++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 techlibs/xilinx/xilinx_finalise.cc diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index ae82311a9..10d783c3c 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -1,5 +1,6 @@ OBJS += techlibs/xilinx/synth_xilinx.o +OBJS += techlibs/xilinx/xilinx_finalise.o GENFILES += techlibs/xilinx/brams_init_36.vh GENFILES += techlibs/xilinx/brams_init_32.vh diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 022b0d108..c2f8279c2 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -512,6 +512,8 @@ struct SynthXilinxPass : public ScriptPass run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I A:top", "(only if '-iopad' or '-ise' and not '-noiopad')"); if (help_mode || ise) run("extractinv -inv INV O:I", "(only if '-ise')"); + if (help_mode || !nodsp) + run("xilinx_finalise", "(skip if '-nodsp')"); } if (check_label("check")) { diff --git a/techlibs/xilinx/xilinx_finalise.cc b/techlibs/xilinx/xilinx_finalise.cc new file mode 100644 index 000000000..db73babe3 --- /dev/null +++ b/techlibs/xilinx/xilinx_finalise.cc @@ -0,0 +1,84 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * (C) 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct XilinxFinalisePass : public Pass +{ + XilinxFinalisePass() : Pass("xilinx_finalise", "") { } + + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" xilinx_finalise [options]\n"); + log("\n"); + } + + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + break; + } + extra_args(args, argidx, design); + + log_header(design, "Executing XILINX_FINALISE pass.\n"); + + for (auto module : design->selected_modules()) + for (auto cell : module->selected_cells()) { + if (cell->type != ID(DSP48E1)) + continue; + for (auto &conn : cell->connections_) { + if (!cell->output(conn.first)) + continue; + bool purge = true; + for (auto &chunk : conn.second.chunks()) { + auto it = chunk.wire->attributes.find(ID(unused_bits)); + if (it == chunk.wire->attributes.end()) + continue; + + std::string unused_bits = stringf("%d", chunk.offset); + for (auto i = 1; i < chunk.width; i++) + unused_bits += stringf(" %d", i+chunk.offset); + + if (it->second.decode_string().find(unused_bits) == std::string::npos) { + purge = false; + break; + } + } + + if (purge) { + log_debug("Purging unused port connection %s %s (.%s(%s))\n", cell->type.c_str(), log_id(cell), log_id(conn.first), log_signal(conn.second)); + conn.second = SigSpec(); + } + } + } + } +} XilinxFinalisePass; + +PRIVATE_NAMESPACE_END From 67c2db3486a7b2ff34f89dc861fb66d51ba6101b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 18:56:18 -0700 Subject: [PATCH 318/356] Remove (* techmap_autopurge *) from abc_unmap.v since no effect --- techlibs/xilinx/abc_unmap.v | 76 ++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index ab007dfd2..630cf5f27 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -56,44 +56,44 @@ module \$__ABC_DSP48E1 ( output PATTERNDETECT, output [47:0] PCOUT, output UNDERFLOW, - (* techmap_autopurge *) input signed [29:0] A, - (* techmap_autopurge *) input [29:0] ACIN, - (* techmap_autopurge *) input [3:0] ALUMODE, - (* techmap_autopurge *) input signed [17:0] B, - (* techmap_autopurge *) input [17:0] BCIN, - (* techmap_autopurge *) input [47:0] C, - (* techmap_autopurge *) input CARRYCASCIN, - (* techmap_autopurge *) input CARRYIN, - (* techmap_autopurge *) input [2:0] CARRYINSEL, - (* techmap_autopurge *) input CEA1, - (* techmap_autopurge *) input CEA2, - (* techmap_autopurge *) input CEAD, - (* techmap_autopurge *) input CEALUMODE, - (* techmap_autopurge *) input CEB1, - (* techmap_autopurge *) input CEB2, - (* techmap_autopurge *) input CEC, - (* techmap_autopurge *) input CECARRYIN, - (* techmap_autopurge *) input CECTRL, - (* techmap_autopurge *) input CED, - (* techmap_autopurge *) input CEINMODE, - (* techmap_autopurge *) input CEM, - (* techmap_autopurge *) input CEP, - (* techmap_autopurge *) input CLK, - (* techmap_autopurge *) input [24:0] D, - (* techmap_autopurge *) input [4:0] INMODE, - (* techmap_autopurge *) input MULTSIGNIN, - (* techmap_autopurge *) input [6:0] OPMODE, - (* techmap_autopurge *) input [47:0] PCIN, - (* techmap_autopurge *) input RSTA, - (* techmap_autopurge *) input RSTALLCARRYIN, - (* techmap_autopurge *) input RSTALUMODE, - (* techmap_autopurge *) input RSTB, - (* techmap_autopurge *) input RSTC, - (* techmap_autopurge *) input RSTCTRL, - (* techmap_autopurge *) input RSTD, - (* techmap_autopurge *) input RSTINMODE, - (* techmap_autopurge *) input RSTM, - (* techmap_autopurge *) input RSTP + input signed [29:0] A, + input [29:0] ACIN, + input [3:0] ALUMODE, + input signed [17:0] B, + input [17:0] BCIN, + input [47:0] C, + input CARRYCASCIN, + input CARRYIN, + input [2:0] CARRYINSEL, + input CEA1, + input CEA2, + input CEAD, + input CEALUMODE, + input CEB1, + input CEB2, + input CEC, + input CECARRYIN, + input CECTRL, + input CED, + input CEINMODE, + input CEM, + input CEP, + input CLK, + input [24:0] D, + input [4:0] INMODE, + input MULTSIGNIN, + input [6:0] OPMODE, + input [47:0] PCIN, + input RSTA, + input RSTALLCARRYIN, + input RSTALUMODE, + input RSTB, + input RSTC, + input RSTCTRL, + input RSTD, + input RSTINMODE, + input RSTM, + input RSTP ); parameter integer ACASCREG = 1; parameter integer ADREG = 1; From 895e2befa76bd326cc47fd40de112ea067fcaf98 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 19:04:07 -0700 Subject: [PATCH 319/356] Vivado does not like zero width port connections --- techlibs/xilinx/xilinx_finalise.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/xilinx_finalise.cc b/techlibs/xilinx/xilinx_finalise.cc index db73babe3..2c0bd3534 100644 --- a/techlibs/xilinx/xilinx_finalise.cc +++ b/techlibs/xilinx/xilinx_finalise.cc @@ -53,7 +53,7 @@ struct XilinxFinalisePass : public Pass for (auto cell : module->selected_cells()) { if (cell->type != ID(DSP48E1)) continue; - for (auto &conn : cell->connections_) { + for (auto conn : cell->connections()) { if (!cell->output(conn.first)) continue; bool purge = true; @@ -74,7 +74,7 @@ struct XilinxFinalisePass : public Pass if (purge) { log_debug("Purging unused port connection %s %s (.%s(%s))\n", cell->type.c_str(), log_id(cell), log_id(conn.first), log_signal(conn.second)); - conn.second = SigSpec(); + cell->unsetPort(conn.first); } } } From 29db96fa1ff89a8224f8ae3c51c754e16a34c31c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 19:52:54 -0700 Subject: [PATCH 320/356] Revert "Vivado does not like zero width port connections" This reverts commit 895e2befa76bd326cc47fd40de112ea067fcaf98. --- techlibs/xilinx/xilinx_finalise.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/xilinx_finalise.cc b/techlibs/xilinx/xilinx_finalise.cc index 2c0bd3534..db73babe3 100644 --- a/techlibs/xilinx/xilinx_finalise.cc +++ b/techlibs/xilinx/xilinx_finalise.cc @@ -53,7 +53,7 @@ struct XilinxFinalisePass : public Pass for (auto cell : module->selected_cells()) { if (cell->type != ID(DSP48E1)) continue; - for (auto conn : cell->connections()) { + for (auto &conn : cell->connections_) { if (!cell->output(conn.first)) continue; bool purge = true; @@ -74,7 +74,7 @@ struct XilinxFinalisePass : public Pass if (purge) { log_debug("Purging unused port connection %s %s (.%s(%s))\n", cell->type.c_str(), log_id(cell), log_id(conn.first), log_signal(conn.second)); - cell->unsetPort(conn.first); + conn.second = SigSpec(); } } } From 0f53893104c84e799db12b6bbd3364af4f5ed338 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 19:52:55 -0700 Subject: [PATCH 321/356] Revert "Remove (* techmap_autopurge *) from abc_unmap.v since no effect" This reverts commit 67c2db3486a7b2ff34f89dc861fb66d51ba6101b. --- techlibs/xilinx/abc_unmap.v | 76 ++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index 630cf5f27..ab007dfd2 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -56,44 +56,44 @@ module \$__ABC_DSP48E1 ( output PATTERNDETECT, output [47:0] PCOUT, output UNDERFLOW, - input signed [29:0] A, - input [29:0] ACIN, - input [3:0] ALUMODE, - input signed [17:0] B, - input [17:0] BCIN, - input [47:0] C, - input CARRYCASCIN, - input CARRYIN, - input [2:0] CARRYINSEL, - input CEA1, - input CEA2, - input CEAD, - input CEALUMODE, - input CEB1, - input CEB2, - input CEC, - input CECARRYIN, - input CECTRL, - input CED, - input CEINMODE, - input CEM, - input CEP, - input CLK, - input [24:0] D, - input [4:0] INMODE, - input MULTSIGNIN, - input [6:0] OPMODE, - input [47:0] PCIN, - input RSTA, - input RSTALLCARRYIN, - input RSTALUMODE, - input RSTB, - input RSTC, - input RSTCTRL, - input RSTD, - input RSTINMODE, - input RSTM, - input RSTP + (* techmap_autopurge *) input signed [29:0] A, + (* techmap_autopurge *) input [29:0] ACIN, + (* techmap_autopurge *) input [3:0] ALUMODE, + (* techmap_autopurge *) input signed [17:0] B, + (* techmap_autopurge *) input [17:0] BCIN, + (* techmap_autopurge *) input [47:0] C, + (* techmap_autopurge *) input CARRYCASCIN, + (* techmap_autopurge *) input CARRYIN, + (* techmap_autopurge *) input [2:0] CARRYINSEL, + (* techmap_autopurge *) input CEA1, + (* techmap_autopurge *) input CEA2, + (* techmap_autopurge *) input CEAD, + (* techmap_autopurge *) input CEALUMODE, + (* techmap_autopurge *) input CEB1, + (* techmap_autopurge *) input CEB2, + (* techmap_autopurge *) input CEC, + (* techmap_autopurge *) input CECARRYIN, + (* techmap_autopurge *) input CECTRL, + (* techmap_autopurge *) input CED, + (* techmap_autopurge *) input CEINMODE, + (* techmap_autopurge *) input CEM, + (* techmap_autopurge *) input CEP, + (* techmap_autopurge *) input CLK, + (* techmap_autopurge *) input [24:0] D, + (* techmap_autopurge *) input [4:0] INMODE, + (* techmap_autopurge *) input MULTSIGNIN, + (* techmap_autopurge *) input [6:0] OPMODE, + (* techmap_autopurge *) input [47:0] PCIN, + (* techmap_autopurge *) input RSTA, + (* techmap_autopurge *) input RSTALLCARRYIN, + (* techmap_autopurge *) input RSTALUMODE, + (* techmap_autopurge *) input RSTB, + (* techmap_autopurge *) input RSTC, + (* techmap_autopurge *) input RSTCTRL, + (* techmap_autopurge *) input RSTD, + (* techmap_autopurge *) input RSTINMODE, + (* techmap_autopurge *) input RSTM, + (* techmap_autopurge *) input RSTP ); parameter integer ACASCREG = 1; parameter integer ADREG = 1; From 27167848f4c5709c6ca3cb0897bac91c4a2a7cbe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 19:52:55 -0700 Subject: [PATCH 322/356] Revert "Add a xilinx_finalise pass" This reverts commit 23d90e0439ffef510632ce45a3d2aff1c129f405. --- techlibs/xilinx/Makefile.inc | 1 - techlibs/xilinx/synth_xilinx.cc | 2 - techlibs/xilinx/xilinx_finalise.cc | 84 ------------------------------ 3 files changed, 87 deletions(-) delete mode 100644 techlibs/xilinx/xilinx_finalise.cc diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 10d783c3c..ae82311a9 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -1,6 +1,5 @@ OBJS += techlibs/xilinx/synth_xilinx.o -OBJS += techlibs/xilinx/xilinx_finalise.o GENFILES += techlibs/xilinx/brams_init_36.vh GENFILES += techlibs/xilinx/brams_init_32.vh diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c2f8279c2..022b0d108 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -512,8 +512,6 @@ struct SynthXilinxPass : public ScriptPass run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I A:top", "(only if '-iopad' or '-ise' and not '-noiopad')"); if (help_mode || ise) run("extractinv -inv INV O:I", "(only if '-ise')"); - if (help_mode || !nodsp) - run("xilinx_finalise", "(skip if '-nodsp')"); } if (check_label("check")) { diff --git a/techlibs/xilinx/xilinx_finalise.cc b/techlibs/xilinx/xilinx_finalise.cc deleted file mode 100644 index db73babe3..000000000 --- a/techlibs/xilinx/xilinx_finalise.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * (C) 2019 Eddie Hung - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/register.h" -#include "kernel/celltypes.h" -#include "kernel/rtlil.h" -#include "kernel/log.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct XilinxFinalisePass : public Pass -{ - XilinxFinalisePass() : Pass("xilinx_finalise", "") { } - - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" xilinx_finalise [options]\n"); - log("\n"); - } - - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - break; - } - extra_args(args, argidx, design); - - log_header(design, "Executing XILINX_FINALISE pass.\n"); - - for (auto module : design->selected_modules()) - for (auto cell : module->selected_cells()) { - if (cell->type != ID(DSP48E1)) - continue; - for (auto &conn : cell->connections_) { - if (!cell->output(conn.first)) - continue; - bool purge = true; - for (auto &chunk : conn.second.chunks()) { - auto it = chunk.wire->attributes.find(ID(unused_bits)); - if (it == chunk.wire->attributes.end()) - continue; - - std::string unused_bits = stringf("%d", chunk.offset); - for (auto i = 1; i < chunk.width; i++) - unused_bits += stringf(" %d", i+chunk.offset); - - if (it->second.decode_string().find(unused_bits) == std::string::npos) { - purge = false; - break; - } - } - - if (purge) { - log_debug("Purging unused port connection %s %s (.%s(%s))\n", cell->type.c_str(), log_id(cell), log_id(conn.first), log_signal(conn.second)); - conn.second = SigSpec(); - } - } - } - } -} XilinxFinalisePass; - -PRIVATE_NAMESPACE_END From 11ac37733d436d5c0217fa6da029d620ec3da1b3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 21:56:28 -0700 Subject: [PATCH 323/356] Add techmap_autopurge to outputs in abc_map.v too --- techlibs/xilinx/abc_map.v | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v index 9d78725df..e4976092c 100644 --- a/techlibs/xilinx/abc_map.v +++ b/techlibs/xilinx/abc_map.v @@ -123,17 +123,17 @@ module SRLC32E ( endmodule module DSP48E1 ( - output [29:0] ACOUT, - output [17:0] BCOUT, - output reg CARRYCASCOUT, - output reg [3:0] CARRYOUT, - output reg MULTSIGNOUT, - output OVERFLOW, - output reg signed [47:0] P, - output PATTERNBDETECT, - output PATTERNDETECT, - output [47:0] PCOUT, - output UNDERFLOW, + (* techmap_autopurge *) output [29:0] ACOUT, + (* techmap_autopurge *) output [17:0] BCOUT, + (* techmap_autopurge *) output reg CARRYCASCOUT, + (* techmap_autopurge *) output reg [3:0] CARRYOUT, + (* techmap_autopurge *) output reg MULTSIGNOUT, + (* techmap_autopurge *) output OVERFLOW, + (* techmap_autopurge *) output reg signed [47:0] P, + (* techmap_autopurge *) output PATTERNBDETECT, + (* techmap_autopurge *) output PATTERNDETECT, + (* techmap_autopurge *) output [47:0] PCOUT, + (* techmap_autopurge *) output UNDERFLOW, (* techmap_autopurge *) input signed [29:0] A, (* techmap_autopurge *) input [29:0] ACIN, (* techmap_autopurge *) input [3:0] ALUMODE, From c340fbfab23c582103402bbd812d9bca4510dc41 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 21:58:04 -0700 Subject: [PATCH 324/356] Force $inout.out ports to begin with '$' to indicate internal --- backends/aiger/xaiger.cc | 2 +- frontends/aiger/aigerparse.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index cbce4c83b..21b281708 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -424,7 +424,7 @@ struct XAigerWriter // inherit existing inout's drivers if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) || keep_bits.count(bit)) { - RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; + RTLIL::IdString wire_name = stringf("$%s$inout.out", wire->name.c_str()); RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) new_wire = module->addWire(wire_name, GetSize(wire)); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index e8ee487e5..986d34fb3 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -868,7 +868,7 @@ void AigerReader::post_process() if (!existing) { if (escaped_s.ends_with("$inout.out")) { wire->port_output = false; - RTLIL::Wire *in_wire = module->wire(escaped_s.substr(0, escaped_s.size()-10)); + RTLIL::Wire *in_wire = module->wire(escaped_s.substr(1, escaped_s.size()-11)); log_assert(in_wire); log_assert(in_wire->port_input && !in_wire->port_output); in_wire->port_output = true; @@ -889,7 +889,7 @@ void AigerReader::post_process() if (!existing) { if (escaped_s.ends_with("$inout.out")) { wire->port_output = false; - RTLIL::Wire *in_wire = module->wire(stringf("%s[%d]", escaped_s.substr(0, escaped_s.size()-10).c_str(), index)); + RTLIL::Wire *in_wire = module->wire(stringf("%s[%d]", escaped_s.substr(1, escaped_s.size()-11).c_str(), index)); log_assert(in_wire); log_assert(in_wire->port_input && !in_wire->port_output); in_wire->port_output = true; From 44374b1b2b0dbc455c9e43d713e133d7d78a5e1a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 21:58:40 -0700 Subject: [PATCH 325/356] "abc_padding" attr for blackbox outputs that were padded, remove them later --- backends/aiger/xaiger.cc | 7 ++++++- passes/techmap/abc9.cc | 19 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 21b281708..5e49f3c80 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -350,6 +350,8 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; + bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); + // Fully pad all unused input connections of this box cell with S0 // Fully pad all undriven output connections of this box cell with anonymous wires // NB: Assume box_module->ports are sorted alphabetically @@ -394,7 +396,10 @@ struct XAigerWriter rhs = it->second; } else { - rhs = module->addWire(NEW_ID, GetSize(w)); + Wire *wire = module->addWire(NEW_ID, GetSize(w)); + if (blackbox) + wire->set_bool_attribute(ID(abc_padding)); + rhs = wire; cell->setPort(port_name, rhs); } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 7eac08d17..aa473e67d 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -606,7 +606,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri existing_cell = module->cell(c->name); log_assert(existing_cell); cell = module->addCell(remap_name(c->name), c->type); - module->swap_names(cell, existing_cell); } if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; @@ -642,8 +641,22 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - for (auto cell : boxes) - module->remove(cell); + for (auto existing_cell : boxes) { + Cell *cell = module->cell(remap_name(existing_cell->name)); + if (cell) { + for (auto &conn : existing_cell->connections()) { + if (!conn.second.is_wire()) + continue; + Wire *wire = conn.second.as_wire(); + if (!wire->get_bool_attribute(ID(abc_padding))) + continue; + cell->unsetPort(conn.first); + log_debug("Dropping padded port connection for %s (%s) .%s (%s )\n", log_id(cell), cell->type.c_str(), log_id(conn.first), log_signal(conn.second)); + } + module->swap_names(cell, existing_cell); + } + module->remove(existing_cell); + } // Copy connections (and rename) from mapped_mod to module for (auto conn : mapped_mod->connections()) { From b41d2fb4e49a5ee8cda1906405f32614b39302bc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 22:02:22 -0700 Subject: [PATCH 326/356] Add (* techmap_autopurge *) to abc_unmap.v too --- techlibs/xilinx/abc_unmap.v | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v index ab007dfd2..8bd0579ed 100644 --- a/techlibs/xilinx/abc_unmap.v +++ b/techlibs/xilinx/abc_unmap.v @@ -45,17 +45,17 @@ endmodule (* techmap_celltype = "$__ABC_DSP48E1_MULT $__ABC_DSP48E1_MULT_DPORT $__ABC_DSP48E1" *) module \$__ABC_DSP48E1 ( - output [29:0] ACOUT, - output [17:0] BCOUT, - output reg CARRYCASCOUT, - output reg [3:0] CARRYOUT, - output reg MULTSIGNOUT, - output OVERFLOW, - output reg signed [47:0] P, - output PATTERNBDETECT, - output PATTERNDETECT, - output [47:0] PCOUT, - output UNDERFLOW, + (* techmap_autopurge *) output [29:0] ACOUT, + (* techmap_autopurge *) output [17:0] BCOUT, + (* techmap_autopurge *) output reg CARRYCASCOUT, + (* techmap_autopurge *) output reg [3:0] CARRYOUT, + (* techmap_autopurge *) output reg MULTSIGNOUT, + (* techmap_autopurge *) output OVERFLOW, + (* techmap_autopurge *) output reg signed [47:0] P, + (* techmap_autopurge *) output PATTERNBDETECT, + (* techmap_autopurge *) output PATTERNDETECT, + (* techmap_autopurge *) output [47:0] PCOUT, + (* techmap_autopurge *) output UNDERFLOW, (* techmap_autopurge *) input signed [29:0] A, (* techmap_autopurge *) input [29:0] ACIN, (* techmap_autopurge *) input [3:0] ALUMODE, From 93363c94a2e88e2cdbdb962ff9e10ba5dfe3f586 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 10:33:16 -0700 Subject: [PATCH 327/356] Oops. Actually use __NAME__ in ABC_DSP48E1 macro --- techlibs/xilinx/abc_model.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v index 0a8d531d7..f19235a27 100644 --- a/techlibs/xilinx/abc_model.v +++ b/techlibs/xilinx/abc_model.v @@ -102,7 +102,7 @@ endmodule (* abc_box_id=2105 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_PCOUT_MUX ) `define ABC_DSP48E1(__NAME__) """ -module \$__ABC_DSP48E1_MULT ( +module __NAME__ ( output [29:0] ACOUT, output [17:0] BCOUT, output reg CARRYCASCOUT, From 53ea5daa42db335a69d3fccbf237fe5555f4bccb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 14:04:36 -0700 Subject: [PATCH 328/356] Call 'wreduce' after mul2dsp to avoid unextend() --- passes/pmgen/xilinx_dsp.pmg | 9 ++++----- techlibs/xilinx/synth_xilinx.cc | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 553195649..bca44c08d 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -1,6 +1,5 @@ pattern xilinx_dsp_pack -udata > unextend state clock state sigA sigB sigC sigD sigM sigP state postAddAB postAddMuxAB @@ -25,7 +24,7 @@ match dsp endmatch code sigA sigB sigC sigD sigM clock - unextend = [](const SigSpec &sig) { + auto unextend = [](const SigSpec &sig) { int i; for (i = GetSize(sig)-1; i > 0; i--) if (sig[i] != sig[i-1]) @@ -272,9 +271,9 @@ match postAdd filter !ffMcemux || nusers(port(postAdd, AB)) == 3 index port(postAdd, AB)[0] === sigP[0] - filter GetSize(unextend(port(postAdd, AB))) <= GetSize(sigP) - filter unextend(port(postAdd, AB)) == sigP.extract(0, GetSize(unextend(port(postAdd, AB)))) - filter nusers(sigP.extract_end(GetSize(unextend(port(postAdd, AB))))) <= 1 + filter GetSize(port(postAdd, AB)) <= GetSize(sigP) + filter port(postAdd, AB) == sigP.extract(0, GetSize(port(postAdd, AB))) + filter nusers(sigP.extract_end(GetSize(port(postAdd, AB)))) <= 1 set postAddAB AB optional endmatch diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 022b0d108..ca108e9d6 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -346,6 +346,7 @@ struct SynthXilinxPass : public ScriptPass "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); + run("wreduce t:$add"); run("xilinx_dsp"); run("chtype -set $mul t:$__soft_mul"); } From 486dd7c483d4277ffb09975fb943881bdc122f4d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 14:05:59 -0700 Subject: [PATCH 329/356] unextend only used in init --- passes/pmgen/ice40_dsp.pmg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 046aae9e2..9330dd09b 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,6 +1,5 @@ pattern ice40_dsp -udata > unextend state clock state clock_pol cd_signed o_lo state sigA sigB sigCD sigH sigO @@ -28,7 +27,7 @@ match mul endmatch code sigA sigB sigH - unextend = [](const SigSpec &sig) { + auto unextend = [](const SigSpec &sig) { int i; for (i = GetSize(sig)-1; i > 0; i--) if (sig[i] != sig[i-1]) From 1d875ac76a354f654f28b9632d83f6b43542e827 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 14:06:21 -0700 Subject: [PATCH 330/356] No need for $__mul anymore? --- techlibs/common/mul2dsp.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 3ca69b7b1..25ff28ab5 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -49,7 +49,7 @@ $fatal(1, "Macro DSP_NAME must be defined"); `define MAX(a,b) (a > b ? a : b) `define MIN(a,b) (a < b ? a : b) -(* techmap_celltype = "$mul $__mul" *) +(* techmap_celltype = "$mul" *) module _80_mul (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -132,9 +132,9 @@ module _80_mul (A, B, Y); end for (i = 0; i < n; i=i+1) begin:slice - \$__mul #( + \$mul #( .A_SIGNED(sign_headroom), - .B_SIGNED(B_SIGNED), + .B_SIGNED(sign_headroom), .A_WIDTH(`DSP_A_MAXWIDTH_PARTIAL), .B_WIDTH(B_WIDTH), .Y_WIDTH(partial_Y_WIDTH) @@ -161,7 +161,7 @@ module _80_mul (A, B, Y); end end - \$__mul #( + \$mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(last_A_WIDTH), @@ -197,8 +197,8 @@ module _80_mul (A, B, Y); end for (i = 0; i < n; i=i+1) begin:slice - \$__mul #( - .A_SIGNED(A_SIGNED), + \$mul #( + .A_SIGNED(sign_headroom), .B_SIGNED(sign_headroom), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH_PARTIAL), @@ -226,7 +226,7 @@ module _80_mul (A, B, Y); end end - \$__mul #( + \$mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), @@ -271,7 +271,7 @@ module _80_mul (A, B, Y); endgenerate endmodule -(* techmap_celltype = "$mul $__mul" *) +(* techmap_celltype = "$mul" *) module _90_soft_mul (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; From 5f8917c98491edd352dce96c63187aa814c32192 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 16:45:51 -0700 Subject: [PATCH 331/356] Fix memory issue since SigSpec& could be invalidated --- passes/pmgen/xilinx_dsp.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 22df3e009..db8fba38b 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -403,9 +403,8 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) }; if (st.ffA2) { - SigSpec &A = cell->connections_.at(ID(A)); + SigSpec A = cell->getPort(ID(A)); f(A, st.ffA2, st.ffA2cemux, st.ffA2cepol, ID(CEA2), st.ffA2rstmux, st.ffArstpol, ID(RSTA)); - pm.add_siguser(A, cell); if (st.ffA1) { f(A, st.ffA1, st.ffA1cemux, st.ffA1cepol, ID(CEA1), st.ffA1rstmux, st.ffArstpol, IdString()); cell->setParam(ID(AREG), 2); @@ -415,11 +414,12 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) cell->setParam(ID(AREG), 1); cell->setParam(ID(ACASCREG), 1); } + pm.add_siguser(A, cell); + cell->setPort(ID(A), A); } if (st.ffB2) { - SigSpec &B = cell->connections_.at(ID(B)); + SigSpec B = cell->getPort(ID(B)); f(B, st.ffB2, st.ffB2cemux, st.ffB2cepol, ID(CEB2), st.ffB2rstmux, st.ffBrstpol, ID(RSTB)); - pm.add_siguser(B, cell); if (st.ffB1) { f(B, st.ffB1, st.ffB1cemux, st.ffB1cepol, ID(CEB1), st.ffB1rstmux, st.ffBrstpol, IdString()); cell->setParam(ID(BREG), 2); @@ -429,11 +429,14 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) cell->setParam(ID(BREG), 1); cell->setParam(ID(BCASCREG), 1); } + pm.add_siguser(B, cell); + cell->setPort(ID(B), B); } if (st.ffD) { - SigSpec &D = cell->connections_.at(ID(D)); + SigSpec D = cell->getPort(ID(D)); f(D, st.ffD, st.ffDcemux, st.ffDcepol, ID(CED), st.ffDrstmux, st.ffDrstpol, ID(RSTD)); pm.add_siguser(D, cell); + cell->setPort(ID(D), D); cell->setParam(ID(DREG), 1); } if (st.ffM) { @@ -539,9 +542,10 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) }; if (st.ffC) { - SigSpec &C = cell->connections_.at(ID(C)); + SigSpec C = cell->getPort(ID(C)); f(C, st.ffC, st.ffCcemux, st.ffCcepol, ID(CEC), st.ffCrstmux, st.ffCrstpol, ID(RSTC)); pm.add_siguser(C, cell); + cell->setPort(ID(C), C); cell->setParam(ID(CREG), 1); } From 234738b103d4f2b3d937ed928fd89bc4e31627f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 16:51:31 -0700 Subject: [PATCH 332/356] Remove _TECHMAP_CELLTYPE_ check since all $mul --- techlibs/common/mul2dsp.v | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 25ff28ab5..8c6a836f8 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -61,8 +61,6 @@ module _80_mul (A, B, Y); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; - parameter _TECHMAP_CELLTYPE_ = ""; - generate if (0) begin end `ifdef DSP_A_MINWIDTH @@ -77,10 +75,8 @@ module _80_mul (A, B, Y); else if (Y_WIDTH < `DSP_Y_MINWIDTH) wire _TECHMAP_FAIL_ = 1; `endif - else if (_TECHMAP_CELLTYPE_ == "$mul" && A_SIGNED != B_SIGNED) - wire _TECHMAP_FAIL_ = 1; `ifdef DSP_SIGNEDONLY - else if (_TECHMAP_CELLTYPE_ == "$mul" && !A_SIGNED) + else if (!A_SIGNED) \$mul #( .A_SIGNED(1), .B_SIGNED(1), @@ -93,7 +89,7 @@ module _80_mul (A, B, Y); .Y(Y) ); `endif - else if (_TECHMAP_CELLTYPE_ == "$mul" && A_WIDTH < B_WIDTH) + else if (A_WIDTH < B_WIDTH) \$mul #( .A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), From 63940913d21fcfb18cd844d7e5b9c8b41a82295b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 17:22:04 -0700 Subject: [PATCH 333/356] Only wreduce on t:$add --- techlibs/ice40/synth_ice40.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 7a8f3d70c..98d3e44e3 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -276,7 +276,7 @@ struct SynthIce40Pass : public ScriptPass run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); - run("wreduce", " (if -dsp)"); + run("wreduce t:$add", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); run("chtype -set $mul t:$__soft_mul","(if -dsp)"); } From aeb15398182abf5de7e340976e204195ab80a739 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 17:22:30 -0700 Subject: [PATCH 334/356] Rework xilinx_dsp postAdd for new wreduce call --- passes/pmgen/xilinx_dsp.pmg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index bca44c08d..e256f7d7e 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -271,9 +271,9 @@ match postAdd filter !ffMcemux || nusers(port(postAdd, AB)) == 3 index port(postAdd, AB)[0] === sigP[0] - filter GetSize(port(postAdd, AB)) <= GetSize(sigP) - filter port(postAdd, AB) == sigP.extract(0, GetSize(port(postAdd, AB))) - filter nusers(sigP.extract_end(GetSize(port(postAdd, AB)))) <= 1 + filter GetSize(port(postAdd, AB)) >= GetSize(sigP) + filter port(postAdd, AB).extract(0, GetSize(sigP)) == sigP + filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(sigP[GetSize(sigP)-1], GetSize(port(postAdd, AB))-GetSize(sigP)) set postAddAB AB optional endmatch From f4387e817c3f75a06c9c94f307fa60572ea06383 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 17:24:11 -0700 Subject: [PATCH 335/356] Revert "No need for $__mul anymore?" This reverts commit 1d875ac76a354f654f28b9632d83f6b43542e827. --- techlibs/common/mul2dsp.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 8c6a836f8..953fc28d1 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -49,7 +49,7 @@ $fatal(1, "Macro DSP_NAME must be defined"); `define MAX(a,b) (a > b ? a : b) `define MIN(a,b) (a < b ? a : b) -(* techmap_celltype = "$mul" *) +(* techmap_celltype = "$mul $__mul" *) module _80_mul (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -128,9 +128,9 @@ module _80_mul (A, B, Y); end for (i = 0; i < n; i=i+1) begin:slice - \$mul #( + \$__mul #( .A_SIGNED(sign_headroom), - .B_SIGNED(sign_headroom), + .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH_PARTIAL), .B_WIDTH(B_WIDTH), .Y_WIDTH(partial_Y_WIDTH) @@ -157,7 +157,7 @@ module _80_mul (A, B, Y); end end - \$mul #( + \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(last_A_WIDTH), @@ -193,8 +193,8 @@ module _80_mul (A, B, Y); end for (i = 0; i < n; i=i+1) begin:slice - \$mul #( - .A_SIGNED(sign_headroom), + \$__mul #( + .A_SIGNED(A_SIGNED), .B_SIGNED(sign_headroom), .A_WIDTH(A_WIDTH), .B_WIDTH(`DSP_B_MAXWIDTH_PARTIAL), @@ -222,7 +222,7 @@ module _80_mul (A, B, Y); end end - \$mul #( + \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), @@ -267,7 +267,7 @@ module _80_mul (A, B, Y); endgenerate endmodule -(* techmap_celltype = "$mul" *) +(* techmap_celltype = "$mul $__mul" *) module _90_soft_mul (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; From a4238637acc4e6670ccefb1894b00c602a827408 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 17:25:44 -0700 Subject: [PATCH 336/356] Revert "Remove _TECHMAP_CELLTYPE_ check since all $mul" This reverts commit 234738b103d4f2b3d937ed928fd89bc4e31627f1. --- techlibs/common/mul2dsp.v | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 953fc28d1..3ca69b7b1 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -61,6 +61,8 @@ module _80_mul (A, B, Y); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; + parameter _TECHMAP_CELLTYPE_ = ""; + generate if (0) begin end `ifdef DSP_A_MINWIDTH @@ -75,8 +77,10 @@ module _80_mul (A, B, Y); else if (Y_WIDTH < `DSP_Y_MINWIDTH) wire _TECHMAP_FAIL_ = 1; `endif + else if (_TECHMAP_CELLTYPE_ == "$mul" && A_SIGNED != B_SIGNED) + wire _TECHMAP_FAIL_ = 1; `ifdef DSP_SIGNEDONLY - else if (!A_SIGNED) + else if (_TECHMAP_CELLTYPE_ == "$mul" && !A_SIGNED) \$mul #( .A_SIGNED(1), .B_SIGNED(1), @@ -89,7 +93,7 @@ module _80_mul (A, B, Y); .Y(Y) ); `endif - else if (A_WIDTH < B_WIDTH) + else if (_TECHMAP_CELLTYPE_ == "$mul" && A_WIDTH < B_WIDTH) \$mul #( .A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), From 34aa3532fb1df2300da83df4071b46da69e3723c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 17:26:47 -0700 Subject: [PATCH 337/356] Remove unnecessary check for A_SIGNED != B_SIGNED; be more explicit --- techlibs/common/mul2dsp.v | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 3ca69b7b1..9932e288f 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -77,10 +77,8 @@ module _80_mul (A, B, Y); else if (Y_WIDTH < `DSP_Y_MINWIDTH) wire _TECHMAP_FAIL_ = 1; `endif - else if (_TECHMAP_CELLTYPE_ == "$mul" && A_SIGNED != B_SIGNED) - wire _TECHMAP_FAIL_ = 1; `ifdef DSP_SIGNEDONLY - else if (_TECHMAP_CELLTYPE_ == "$mul" && !A_SIGNED) + else if (_TECHMAP_CELLTYPE_ == "$mul" && !A_SIGNED && !B_SIGNED) \$mul #( .A_SIGNED(1), .B_SIGNED(1), From cd8a640989d0819266d2678304951de2a247405d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 18:21:08 -0700 Subject: [PATCH 338/356] Reject if (* init *) present --- passes/pmgen/ice40_dsp.pmg | 3 +++ passes/pmgen/xilinx_dsp.pmg | 3 +++ 2 files changed, 6 insertions(+) diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 9330dd09b..6b6d2b56f 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -333,6 +333,9 @@ code reject; if (c.wire->get_bool_attribute(\keep)) reject; + Const init = c.wire->attributes.at(\init, State::Sx); + if (!init.is_fully_undef() && !init.is_fully_zero()) + reject; } endcode diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index e256f7d7e..0a345e88d 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -355,6 +355,9 @@ code reject; if (c.wire->get_bool_attribute(\keep)) reject; + Const init = c.wire->attributes.at(\init, State::Sx); + if (!init.is_fully_undef() && !init.is_fully_zero()) + reject; } endcode From f1de93edf5b5c73440d445d8d6fa32251d2bdab1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 22:58:03 -0700 Subject: [PATCH 339/356] Do not die if DSP48E1.P has no users (would otherwise get 'clean'-ed) --- passes/pmgen/xilinx_dsp.pmg | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 0a345e88d..3d0b1f2c3 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -53,6 +53,10 @@ code sigA sigB sigC sigD sigM clock } else sigM = P; + // This sigM could have no users if downstream $add + // is narrower than $mul result, for example + if (sigM.empty()) + reject; clock = port(dsp, \CLK, SigBit()); endcode @@ -261,7 +265,7 @@ endcode match postAdd // Ensure that Z mux is not already used - if port(dsp, \OPMODE).extract(4,3).is_fully_zero() + if port(dsp, \OPMODE, SigSpec()).extract(4,3).is_fully_zero() select postAdd->type.in($add) select GetSize(port(postAdd, \Y)) <= 48 From 35aaa8d73a75f36a42eea9ef2b210d9e79e5edc3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 25 Sep 2019 22:58:55 -0700 Subject: [PATCH 340/356] mul2dsp.v slice names --- techlibs/common/mul2dsp.v | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 9932e288f..60b180ac0 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -129,14 +129,14 @@ module _80_mul (A, B, Y); wire [Y_WIDTH-1:0] partial_sum [n:0]; end - for (i = 0; i < n; i=i+1) begin:slice + for (i = 0; i < n; i=i+1) begin:sliceA \$__mul #( .A_SIGNED(sign_headroom), .B_SIGNED(B_SIGNED), .A_WIDTH(`DSP_A_MAXWIDTH_PARTIAL), .B_WIDTH(B_WIDTH), .Y_WIDTH(partial_Y_WIDTH) - ) mul_slice ( + ) mul ( .A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_A_MAXWIDTH_PARTIAL-sign_headroom]}), .B(B), .Y(partial[i]) @@ -165,7 +165,7 @@ module _80_mul (A, B, Y); .A_WIDTH(last_A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(last_Y_WIDTH) - ) mul_slice_last ( + ) sliceA.last ( .A(A[A_WIDTH-1 -: last_A_WIDTH]), .B(B), .Y(last_partial) @@ -194,7 +194,7 @@ module _80_mul (A, B, Y); wire [Y_WIDTH-1:0] partial_sum [n:0]; end - for (i = 0; i < n; i=i+1) begin:slice + for (i = 0; i < n; i=i+1) begin:sliceB \$__mul #( .A_SIGNED(A_SIGNED), .B_SIGNED(sign_headroom), @@ -230,7 +230,7 @@ module _80_mul (A, B, Y); .A_WIDTH(A_WIDTH), .B_WIDTH(last_B_WIDTH), .Y_WIDTH(last_Y_WIDTH) - ) mul_last ( + ) mul_sliceB_last ( .A(A), .B(B[B_WIDTH-1 -: last_B_WIDTH]), .Y(last_partial) From 27e5bf5aad229ef330bfea932f6b194ec5c09b68 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 09:57:11 -0700 Subject: [PATCH 341/356] Stop trying to be too smart by prematurely optimising --- techlibs/common/mul2dsp.v | 40 +++++---------------------------- techlibs/ice40/synth_ice40.cc | 8 ++++--- techlibs/xilinx/synth_xilinx.cc | 4 +++- 3 files changed, 14 insertions(+), 38 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 60b180ac0..6dcdcf226 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -146,17 +146,8 @@ module _80_mul (A, B, Y); // reduction' approach also exists... if (i == 0) assign partial_sum[i] = partial[i]; - else begin - // Rewrite the following statement explicitly in order - // to save on a call to 'opt_expr -fine' which would - // optimise away the '<<' op and trim size of adder - //assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; - if (A_SIGNED && B_SIGNED) - assign partial_sum[i][Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] = partial[i] + $signed(partial_sum[i-1][Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)]); - else - assign partial_sum[i][Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] = partial[i] + partial_sum[i-1][Y_WIDTH-1:i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)]; - assign partial_sum[i][i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0] = partial_sum[i-1][i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0]; - end + else + assign partial_sum[i] = (partial[i] << (* mul2dsp *) i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) partial_sum[i-1]; end \$__mul #( @@ -170,12 +161,7 @@ module _80_mul (A, B, Y); .B(B), .Y(last_partial) ); - //assign partial_sum[n] = (last_partial << n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; - if (A_SIGNED && B_SIGNED) - assign partial_sum[n][Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + $signed(partial_sum[n-1][Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)]); - else - assign partial_sum[n][Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + partial_sum[n-1][Y_WIDTH-1:n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)]; - assign partial_sum[n][n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0] = partial_sum[n-1][n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)-1:0]; + assign partial_sum[n] = (last_partial << (* mul2dsp *) n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) partial_sum[n-1]; assign Y = partial_sum[n]; end else if (B_WIDTH > `DSP_B_MAXWIDTH) begin @@ -211,17 +197,8 @@ module _80_mul (A, B, Y); // reduction' approach also exists... if (i == 0) assign partial_sum[i] = partial[i]; - else begin - // Rewrite the following statement explicitly in order - // to save on a call to 'opt_expr -fine' which would - // optimise away the '<<' op and trim size of adder - //assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; - if (A_SIGNED && B_SIGNED) - assign partial_sum[i][Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = partial[i] + $signed(partial_sum[i-1][Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]); - else - assign partial_sum[i][Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = partial[i] + partial_sum[i-1][Y_WIDTH-1:i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]; - assign partial_sum[i][i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0] = partial_sum[i-1][i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0]; - end + else + assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; end \$__mul #( @@ -235,12 +212,7 @@ module _80_mul (A, B, Y); .B(B[B_WIDTH-1 -: last_B_WIDTH]), .Y(last_partial) ); - //assign partial_sum[n] = (last_partial << n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; - if (A_SIGNED && B_SIGNED) - assign partial_sum[n][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + $signed(partial_sum[n-1][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]); - else - assign partial_sum[n][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)] = last_partial + partial_sum[n-1][Y_WIDTH-1:n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)]; - assign partial_sum[n][n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0] = partial_sum[n-1][n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)-1:0]; + assign partial_sum[n] = (last_partial << n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; assign Y = partial_sum[n]; end else begin diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 98d3e44e3..694782e5b 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -276,9 +276,11 @@ struct SynthIce40Pass : public ScriptPass run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); - run("wreduce t:$add", " (if -dsp)"); - run("ice40_dsp", " (if -dsp)"); - run("chtype -set $mul t:$__soft_mul","(if -dsp)"); + run("opt_expr -fine a:mul2dsp", " (if -dsp)"); + run("wreduce a:mul2dsp", " (if -dsp)"); + run("ice40_dsp", " (if -dsp)"); + run("setattr -unset mul2dsp a:mul2dsp", "(if -dsp)"); + run("chtype -set $mul t:$__soft_mul", " (if -dsp)"); } run("alumacc"); run("opt"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ca108e9d6..b87fa9f6f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -346,7 +346,9 @@ struct SynthXilinxPass : public ScriptPass "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); - run("wreduce t:$add"); + run("opt_expr -fine a:mul2dsp"); + run("wreduce a:mul2dsp"); + run("setattr -unset mul2dsp a:mul2dsp"); run("xilinx_dsp"); run("chtype -set $mul t:$__soft_mul"); } From 781dda6175c86fcb2b08d055565d3d99a687e636 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 10:15:05 -0700 Subject: [PATCH 342/356] select once --- techlibs/ice40/synth_ice40.cc | 12 +++++++----- techlibs/xilinx/synth_xilinx.cc | 8 +++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 694782e5b..52e13bdc2 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -276,11 +276,13 @@ struct SynthIce40Pass : public ScriptPass run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); - run("opt_expr -fine a:mul2dsp", " (if -dsp)"); - run("wreduce a:mul2dsp", " (if -dsp)"); - run("ice40_dsp", " (if -dsp)"); - run("setattr -unset mul2dsp a:mul2dsp", "(if -dsp)"); - run("chtype -set $mul t:$__soft_mul", " (if -dsp)"); + run("select a:mul2dsp", " (if -dsp)"); + run("opt_expr -fine", " (if -dsp)"); + run("wreduce", " (if -dsp)"); + run("setattr -unset mul2dsp", " (if -dsp)"); + run("select -clear", " (if -dsp)"); + run("ice40_dsp", " (if -dsp)"); + run("chtype -set $mul t:$__soft_mul", "(if -dsp)"); } run("alumacc"); run("opt"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b87fa9f6f..0445eb720 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -346,9 +346,11 @@ struct SynthXilinxPass : public ScriptPass "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); - run("opt_expr -fine a:mul2dsp"); - run("wreduce a:mul2dsp"); - run("setattr -unset mul2dsp a:mul2dsp"); + run("select a:mul2dsp"); + run("opt_expr -fine"): + run("wreduce"); + run("setattr -unset mul2dsp"); + run("select -clear"); run("xilinx_dsp"); run("chtype -set $mul t:$__soft_mul"); } From c0bb1d22e81b935e90032ed886e58787b3e61df5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 10:31:55 -0700 Subject: [PATCH 343/356] Remove newline --- passes/pmgen/xilinx_dsp.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index db8fba38b..4c297a50a 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -494,7 +494,6 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) log_debug("Analysing %s.%s for Xilinx DSP packing (CREG).\n", log_id(pm.module), log_id(st.dsp)); log_debug("ffC: %s %s %s\n", log_id(st.ffC, "--"), log_id(st.ffCcemux, "--"), log_id(st.ffCrstmux, "--")); - log_debug("\n"); Cell *cell = st.dsp; From bd8661e0247121cf411b4c35fcedbc12a5919b50 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 10:32:01 -0700 Subject: [PATCH 344/356] CREG to check for \keep --- passes/pmgen/xilinx_dsp_CREG.pmg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/pmgen/xilinx_dsp_CREG.pmg b/passes/pmgen/xilinx_dsp_CREG.pmg index d79abdd4a..a31dc80bf 100644 --- a/passes/pmgen/xilinx_dsp_CREG.pmg +++ b/passes/pmgen/xilinx_dsp_CREG.pmg @@ -87,6 +87,9 @@ code reject; if (c.wire->get_bool_attribute(\keep)) reject; + Const init = c.wire->attributes.at(\init, State::Sx); + if (!init.is_fully_undef() && !init.is_fully_zero()) + reject; } endcode From 033aefc0f44abdca50e34cad884c81875dcd7441 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 10:34:14 -0700 Subject: [PATCH 345/356] Typo --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 0445eb720..d73cc3b16 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -347,7 +347,7 @@ struct SynthXilinxPass : public ScriptPass "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); run("select a:mul2dsp"); - run("opt_expr -fine"): + run("opt_expr -fine"); run("wreduce"); run("setattr -unset mul2dsp"); run("select -clear"); From 84825f937827f3e8fd3702a7ea85b8997ac74534 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 10:45:14 -0700 Subject: [PATCH 346/356] Combine 'flatten' & 'coarse' labels in synth_ecp5 so proc run once --- techlibs/ecp5/synth_ecp5.cc | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 0a3dcc62c..1f5b1cb6b 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -226,16 +226,13 @@ struct SynthEcp5Pass : public ScriptPass run(stringf("hierarchy -check %s", help_mode ? "-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("proc"); + if (flatten || help_mode) + run("flatten"); + run("tribuf -logic"); + run("deminout"); run("opt_expr"); run("opt_clean"); run("check"); @@ -248,9 +245,7 @@ struct SynthEcp5Pass : public ScriptPass run("opt_expr"); run("opt_clean"); if (!nodsp) { - run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18", "(unless -nodsp)"); - run("clean", "(unless -nodsp)"); - run("techmap -map +/ecp5/dsp_map.v", "(unless -nodsp)"); + run("techmap -map +/mul2dsp.v -map +/ecp5/dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18", "(unless -nodsp)"); run("chtype -set $mul t:$__soft_mul", "(unless -nodsp)"); } run("alumacc"); From 832216dab072cb4f1793aeda07604fb2eb32b399 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 12:09:57 -0700 Subject: [PATCH 347/356] Try recursive pmgen for P cascade --- passes/pmgen/xilinx_dsp_cascade.pmg | 200 ++++++++++++++++------------ 1 file changed, 115 insertions(+), 85 deletions(-) diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg index 37674efea..59cd1267d 100644 --- a/passes/pmgen/xilinx_dsp_cascade.pmg +++ b/passes/pmgen/xilinx_dsp_cascade.pmg @@ -1,100 +1,133 @@ pattern xilinx_dsp_cascadeP -udata > unextend -state sigC +udata >> chain longest_chain -match dsp_pcin - select dsp_pcin->type.in(\DSP48E1) - select !param(dsp_pcin, \CREG, State::S1).as_bool() - select port(dsp_pcin, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011") - select nusers(port(dsp_pcin, \C, SigSpec())) > 1 - select nusers(port(dsp_pcin, \PCIN, SigSpec())) == 0 -endmatch - -code sigC - unextend = [](const SigSpec &sig) { - int i; - for (i = GetSize(sig)-1; i > 0; i--) - if (sig[i] != sig[i-1]) - break; - // Do not remove non-const sign bit - if (sig[i].wire) - ++i; - return sig.extract(0, i); - }; - sigC = unextend(port(dsp_pcin, \C)); +code +#define MAX_DSP_CASCADE 20 endcode -match dsp_pcout - select dsp_pcout->type.in(\DSP48E1) - select nusers(port(dsp_pcout, \P, SigSpec())) > 1 - select nusers(port(dsp_pcout, \PCOUT, SigSpec())) <= 1 - - index port(dsp_pcout, \P)[0] === sigC[0] - filter GetSize(port(dsp_pcin, \P)) >= GetSize(sigC) - filter port(dsp_pcout, \P).extract(0, GetSize(sigC)) == sigC - - optional -endmatch - -match dsp_pcout_shift17 - if !dsp_pcout - select dsp_pcout_shift17->type.in(\DSP48E1) - select nusers(port(dsp_pcout_shift17, \P, SigSpec())) > 1 - select nusers(port(dsp_pcout_shift17, \PCOUT, SigSpec())) <= 1 - - index port(dsp_pcout_shift17, \P)[17] === sigC[0] - filter GetSize(port(dsp_pcout_shift17, \P)) >= GetSize(sigC)+17 - filter port(dsp_pcout_shift17, \P).extract(17, GetSize(sigC)) == sigC +match first + select first->type.in(\DSP48E1) + select port(first, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("000") + select nusers(port(first, \PCOUT, SigSpec())) <= 1 endmatch code - Cell *dsp; - if (dsp_pcout) - dsp = dsp_pcout; - else if (dsp_pcout_shift17) - dsp = dsp_pcout_shift17; - else log_abort(); + longest_chain.clear(); + chain.emplace_back(first, false); + subpattern(tail); +finally + chain.pop_back(); + log_assert(chain.empty()); + if (GetSize(longest_chain) > 1) { + Cell *dsp = longest_chain.front().first; - dsp_pcin->setPort(ID(C), Const(0, 48)); + for (int i = 1; i < GetSize(longest_chain); i++) { + Cell *dsp_pcin = longest_chain[i].first; + bool shift17 = longest_chain[i].second; - Wire *cascade = module->addWire(NEW_ID, 48); - dsp_pcin->setPort(ID(PCIN), cascade); - dsp->setPort(ID(PCOUT), cascade); - add_siguser(cascade, dsp_pcin); - add_siguser(cascade, dsp); + dsp_pcin->setPort(ID(C), Const(0, 48)); - SigSpec opmode = port(dsp_pcin, \OPMODE, Const(0, 7)); - if (dsp_pcout) - opmode[6] = State::S0; - else if (dsp_pcout_shift17) - opmode[6] = State::S1; - else log_abort(); + if (i % MAX_DSP_CASCADE > 0) { + Wire *cascade = module->addWire(NEW_ID, 48); + dsp_pcin->setPort(ID(PCIN), cascade); + dsp->setPort(ID(PCOUT), cascade); + add_siguser(cascade, dsp_pcin); + add_siguser(cascade, dsp); - opmode[5] = State::S0; - opmode[4] = State::S1; - dsp_pcin->setPort(\OPMODE, opmode); + SigSpec opmode = port(dsp_pcin, \OPMODE, Const(0, 7)); + if (shift17) + opmode[6] = State::S1; + else + opmode[6] = State::S0; - log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + opmode[5] = State::S0; + opmode[4] = State::S1; + dsp_pcin->setPort(\OPMODE, opmode); - if (nusers(port(dsp_pcin, \PCOUT, SigSpec())) > 1) { - log_debug(" Saturated PCIN/PCOUT on %s\n", log_id(dsp_pcin)); - blacklist(dsp_pcin); - } - if (nusers(port(dsp, \PCIN, SigSpec())) > 1) { - log_debug(" Saturated PCIN/PCOUT on %s\n", log_id(dsp)); - blacklist(dsp_pcout); + log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + } + else { + log_debug("Blocking PCOUT -> PCIN cascade for %s -> %s (exceeds max: %d)\n", log_id(dsp), log_id(dsp_pcin), MAX_DSP_CASCADE); + } + + dsp = dsp_pcin; + } + + did_something = true; + accept; } +endcode - did_something = true; - accept; +// ------------------------------------------------------------------ + +subpattern tail +arg first + +match next + select next->type.in(\DSP48E1) + select !param(next, \CREG, State::S1).as_bool() + select port(next, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011") + select nusers(port(next, \C, SigSpec())) > 1 + select nusers(port(next, \PCIN, SigSpec())) == 0 + index port(next, \C)[0] === port(chain.back().first, \P)[0] + semioptional +endmatch + +match next_shift17 + if !next_shift17 + select next_shift17->type.in(\DSP48E1) + select !param(next_shift17, \CREG, State::S1).as_bool() + select port(next_shift17, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011") + select nusers(port(next_shift17, \C, SigSpec())) > 1 + select nusers(port(next_shift17, \PCIN, SigSpec())) == 0 + index port(next_shift17, \C)[0] === port(chain.back().first, \P)[17] + semioptional +endmatch + +code next + if (!next) + next = next_shift17; + if (next) { + chain.emplace_back(next, next_shift17); + + auto unextend = [](const SigSpec &sig) { + int i; + for (i = GetSize(sig)-1; i > 0; i--) + if (sig[i] != sig[i-1]) + break; + // Do not remove non-const sign bit + if (sig[i].wire) + ++i; + return sig.extract(0, i); + }; + SigSpec sigC = unextend(port(next, \C)); + + // TODO: Cannot use 'reject' since semioptional + if (next_shift17) { + if (GetSize(sigC)+17 <= GetSize(port(chain.back().first, \P)) && + port(chain.back().first, \P).extract(17, GetSize(sigC)) != sigC) + subpattern(tail); + } + else { + if (GetSize(sigC) <= GetSize(port(chain.back().first, \P)) && + port(chain.back().first, \P).extract(0, GetSize(sigC)) != sigC) + subpattern(tail); + + } + } else { + if (GetSize(chain) > GetSize(longest_chain)) + longest_chain = chain; + } +finally + if (next) + chain.pop_back(); endcode // ########## pattern xilinx_dsp_cascadeAB -udata > unextend state clock state sigA sigB @@ -113,8 +146,13 @@ udata dffclock udata dff dffcemux dffrstmux udata dffcepol dffrstpol -code - unextend = [](const SigSpec &sig) { +match dspD + select dspD->type.in(\DSP48E1) + select (param(dspD, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && nusers(port(dspD, \A, SigSpec())) > 1 && nusers(port(dspD, \ACIN, SigSpec())) == 0) || (param(dspD, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && nusers(port(dspD, \B, SigSpec())) > 1 && nusers(port(dspD, \BCIN, SigSpec())) == 0) +endmatch + +code sigA sigB + auto unextend = [](const SigSpec &sig) { int i; for (i = GetSize(sig)-1; i > 0; i--) if (sig[i] != sig[i-1]) @@ -124,14 +162,6 @@ code ++i; return sig.extract(0, i); }; -endcode - -match dspD - select dspD->type.in(\DSP48E1) - select (param(dspD, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && nusers(port(dspD, \A, SigSpec())) > 1 && nusers(port(dspD, \ACIN, SigSpec())) == 0) || (param(dspD, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && nusers(port(dspD, \B, SigSpec())) > 1 && nusers(port(dspD, \BCIN, SigSpec())) == 0) -endmatch - -code sigA sigB if (param(dspD, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT") sigA = unextend(port(dspD, \A)); if (param(dspD, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT") From af59856ba1be1f7cde3154994334f45500af6c22 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 13:29:18 -0700 Subject: [PATCH 348/356] xilinx_dsp_cascade to also cascade AREG and BREG --- passes/pmgen/xilinx_dsp.cc | 42 +- passes/pmgen/xilinx_dsp_cascade.pmg | 592 ++++++++-------------------- 2 files changed, 176 insertions(+), 458 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 4c297a50a..b0251de50 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -609,30 +609,26 @@ struct XilinxDspPass : public Pass { for (auto module : design->selected_modules()) { xilinx_simd_pack(module, module->selected_cells()); - { - xilinx_dsp_pm pm(module, module->selected_cells()); - pm.run_xilinx_dsp_pack(xilinx_dsp_pack); - } - // Separating out CREG packing is necessary since there - // is no guarantee that the cell ordering corresponds - // to the "expected" case (i.e. the order in which - // they appear in the source) thus the possiblity - // existed that a register got packed as CREG into a - // downstream DSP that should have otherwise been a - // PREG of an upstream DSP that had not been pattern - // matched yet - { - xilinx_dsp_CREG_pm pm(module, module->selected_cells()); - pm.run_xilinx_dsp_packC(xilinx_dsp_packC); - } - - do { - did_something = false; + { + xilinx_dsp_pm pm(module, module->selected_cells()); + pm.run_xilinx_dsp_pack(xilinx_dsp_pack); + } + // Separating out CREG packing is necessary since there + // is no guarantee that the cell ordering corresponds + // to the "expected" case (i.e. the order in which + // they appear in the source) thus the possiblity + // existed that a register got packed as CREG into a + // downstream DSP that should have otherwise been a + // PREG of an upstream DSP that had not been pattern + // matched yet + { + xilinx_dsp_CREG_pm pm(module, module->selected_cells()); + pm.run_xilinx_dsp_packC(xilinx_dsp_packC); + } + { xilinx_dsp_cascade_pm pm(module, module->selected_cells()); - pm.run_xilinx_dsp_cascadeP(); - //pm.run_xilinx_dsp_cascadeAB(); - break; - } while (did_something); + pm.run_xilinx_dsp_cascade(); + } } } } XilinxDspPass; diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg index 59cd1267d..2fc943a66 100644 --- a/passes/pmgen/xilinx_dsp_cascade.pmg +++ b/passes/pmgen/xilinx_dsp_cascade.pmg @@ -1,6 +1,19 @@ -pattern xilinx_dsp_cascadeP +pattern xilinx_dsp_cascade -udata >> chain longest_chain +udata > unextend +udata >> chain longest_chain +state next +state clock +state AREG BREG + +// subpattern +state argQ argD +state ffcepol ffrstpol +state ffoffset +udata dffD dffQ +udata dffclock +udata dff dffcemux dffrstmux +udata dffcepol dffrstpol code #define MAX_DSP_CASCADE 20 @@ -14,41 +27,71 @@ endmatch code longest_chain.clear(); - chain.emplace_back(first, false); + chain.emplace_back(first, -1, -1, -1); subpattern(tail); finally chain.pop_back(); log_assert(chain.empty()); if (GetSize(longest_chain) > 1) { - Cell *dsp = longest_chain.front().first; + Cell *dsp = std::get<0>(longest_chain.front()); + Cell *dsp_pcin; + int P, AREG, BREG; for (int i = 1; i < GetSize(longest_chain); i++) { - Cell *dsp_pcin = longest_chain[i].first; - bool shift17 = longest_chain[i].second; + std::tie(dsp_pcin,P,AREG,BREG) = longest_chain[i]; dsp_pcin->setPort(ID(C), Const(0, 48)); if (i % MAX_DSP_CASCADE > 0) { - Wire *cascade = module->addWire(NEW_ID, 48); - dsp_pcin->setPort(ID(PCIN), cascade); - dsp->setPort(ID(PCOUT), cascade); - add_siguser(cascade, dsp_pcin); - add_siguser(cascade, dsp); + if (P >= 0) { + Wire *cascade = module->addWire(NEW_ID, 48); + dsp_pcin->setPort(ID(PCIN), cascade); + dsp->setPort(ID(PCOUT), cascade); + add_siguser(cascade, dsp_pcin); + add_siguser(cascade, dsp); - SigSpec opmode = port(dsp_pcin, \OPMODE, Const(0, 7)); - if (shift17) - opmode[6] = State::S1; - else - opmode[6] = State::S0; + SigSpec opmode = port(dsp_pcin, \OPMODE, Const(0, 7)); + if (P == 17) + opmode[6] = State::S1; + else if (P == 0) + opmode[6] = State::S0; + else log_abort(); - opmode[5] = State::S0; - opmode[4] = State::S1; - dsp_pcin->setPort(\OPMODE, opmode); + opmode[5] = State::S0; + opmode[4] = State::S1; + dsp_pcin->setPort(\OPMODE, opmode); - log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + } + if (AREG >= 0) { + Wire *cascade = module->addWire(NEW_ID, 30); + dsp_pcin->setPort(ID(ACIN), cascade); + dsp->setPort(ID(ACOUT), cascade); + dsp_pcin->unsetPort(ID(A)); + add_siguser(cascade, dsp_pcin); + add_siguser(cascade, dsp); + + dsp->setParam(ID(ACASCREG), AREG); + dsp_pcin->setParam(ID(A_INPUT), Const("CASCADE")); + + log_debug("ACOUT -> ACIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + } + if (BREG >= 0) { + Wire *cascade = module->addWire(NEW_ID, 18); + dsp_pcin->setPort(ID(BCIN), cascade); + dsp->setPort(ID(BCOUT), cascade); + dsp_pcin->unsetPort(ID(B)); + add_siguser(cascade, dsp_pcin); + add_siguser(cascade, dsp); + + dsp->setParam(ID(BCASCREG), BREG); + dsp_pcin->setParam(ID(B_INPUT), Const("CASCADE")); + + log_debug("BCOUT -> BCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + } } else { - log_debug("Blocking PCOUT -> PCIN cascade for %s -> %s (exceeds max: %d)\n", log_id(dsp), log_id(dsp_pcin), MAX_DSP_CASCADE); + log_debug(" Blocking %s -> %s cascade (exceeds max: %d)\n", log_id(dsp), log_id(dsp_pcin), MAX_DSP_CASCADE); } dsp = dsp_pcin; @@ -63,35 +106,35 @@ endcode subpattern tail arg first +arg next -match next - select next->type.in(\DSP48E1) - select !param(next, \CREG, State::S1).as_bool() - select port(next, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011") - select nusers(port(next, \C, SigSpec())) > 1 - select nusers(port(next, \PCIN, SigSpec())) == 0 - index port(next, \C)[0] === port(chain.back().first, \P)[0] +match nextP + select nextP->type.in(\DSP48E1) + select !param(nextP, \CREG, State::S1).as_bool() + select port(nextP, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011") + select nusers(port(nextP, \C, SigSpec())) > 1 + select nusers(port(nextP, \PCIN, SigSpec())) == 0 + index port(nextP, \C)[0] === port(std::get<0>(chain.back()), \P)[0] semioptional endmatch -match next_shift17 - if !next_shift17 - select next_shift17->type.in(\DSP48E1) - select !param(next_shift17, \CREG, State::S1).as_bool() - select port(next_shift17, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011") - select nusers(port(next_shift17, \C, SigSpec())) > 1 - select nusers(port(next_shift17, \PCIN, SigSpec())) == 0 - index port(next_shift17, \C)[0] === port(chain.back().first, \P)[17] +match nextP_shift17 + if !nextP + select nextP_shift17->type.in(\DSP48E1) + select !param(nextP_shift17, \CREG, State::S1).as_bool() + select port(nextP_shift17, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("011") + select nusers(port(nextP_shift17, \C, SigSpec())) > 1 + select nusers(port(nextP_shift17, \PCIN, SigSpec())) == 0 + index port(nextP_shift17, \C)[0] === port(std::get<0>(chain.back()), \P)[17] semioptional endmatch code next - if (!next) - next = next_shift17; + next = nextP; + if (!nextP) + next = nextP_shift17; if (next) { - chain.emplace_back(next, next_shift17); - - auto unextend = [](const SigSpec &sig) { + unextend = [](const SigSpec &sig) { int i; for (i = GetSize(sig)-1; i > 0; i--) if (sig[i] != sig[i-1]) @@ -101,17 +144,82 @@ code next ++i; return sig.extract(0, i); }; + } +endcode + +code argQ clock AREG + AREG = 0; + if (next) { + Cell *prev = std::get<0>(chain.back()); + if (param(prev, \AREG, 2).as_int() > 0 && + param(next, \AREG, 2).as_int() > 0 && + param(next, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && + port(next, \ACIN, SigSpec()).is_fully_zero() && + nusers(port(prev, \ACOUT, SigSpec())) <= 1) { + argQ = unextend(port(next, \A)); + clock = port(prev, \CLK); + subpattern(in_dffe); + if (dff) { + if (!dffrstmux && port(prev, \RSTA, State::S0) != State::S0) + goto reject_AREG; + if (dffrstmux && port(dffrstmux, \S) != port(prev, \RSTA, State::S0)) + goto reject_AREG; + if (!dffcemux && port(prev, \CEA2, State::S0) != State::S0) + goto reject_AREG; + if (dffcemux && port(dffcemux, \S) != port(prev, \CEA2, State::S0)) + goto reject_AREG; + if (dffD == unextend(port(prev, \A))) + AREG = 1; +reject_AREG: ; + } + } + } +endcode + +code argQ clock BREG + BREG = 0; + if (next) { + Cell *prev = std::get<0>(chain.back()); + if (param(prev, \BREG, 2).as_int() > 0 && + param(next, \BREG, 2).as_int() > 0 && + param(next, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && + port(next, \BCIN, SigSpec()).is_fully_zero() && + nusers(port(prev, \BCOUT, SigSpec())) <= 1) { + argQ = unextend(port(next, \B)); + clock = port(prev, \CLK); + subpattern(in_dffe); + if (dff) { + if (!dffrstmux && port(prev, \RSTB, State::S0) != State::S0) + goto reject_BREG; + if (dffrstmux && port(dffrstmux, \S) != port(prev, \RSTB, State::S0)) + goto reject_BREG; + if (!dffcemux && port(prev, \CEB2, State::S0) != State::S0) + goto reject_BREG; + if (dffcemux && port(dffcemux, \S) != port(prev, \CEB2, State::S0)) + goto reject_BREG; + if (dffD == unextend(port(prev, \B))) + BREG = 1; +reject_BREG: ; + } + } + } +endcode + +code + if (next) { + chain.emplace_back(next, nextP_shift17 ? 17 : nextP ? 0 : -1, AREG, BREG); + SigSpec sigC = unextend(port(next, \C)); // TODO: Cannot use 'reject' since semioptional - if (next_shift17) { - if (GetSize(sigC)+17 <= GetSize(port(chain.back().first, \P)) && - port(chain.back().first, \P).extract(17, GetSize(sigC)) != sigC) + if (nextP_shift17) { + if (GetSize(sigC)+17 <= GetSize(port(std::get<0>(chain.back()), \P)) && + port(std::get<0>(chain.back()), \P).extract(17, GetSize(sigC)) != sigC) subpattern(tail); } else { - if (GetSize(sigC) <= GetSize(port(chain.back().first, \P)) && - port(chain.back().first, \P).extract(0, GetSize(sigC)) != sigC) + if (GetSize(sigC) <= GetSize(port(std::get<0>(chain.back()), \P)) && + port(std::get<0>(chain.back()), \P).extract(0, GetSize(sigC)) != sigC) subpattern(tail); } @@ -124,395 +232,6 @@ finally chain.pop_back(); endcode -// ########## - -pattern xilinx_dsp_cascadeAB - -state clock -state sigA sigB - -state ffA1cepol ffA2cepol ffB1cepol ffB2cepol -state ffArstpol ffBrstpol - -state ffA1 ffA1cemux ffA1rstmux ffA2 ffA2cemux ffA2rstmux -state ffB1 ffB1cemux ffB1rstmux ffB2 ffB2cemux ffB2rstmux - -// subpattern -state argQ argD -state ffcepol ffrstpol -state ffoffset -udata dffD dffQ -udata dffclock -udata dff dffcemux dffrstmux -udata dffcepol dffrstpol - -match dspD - select dspD->type.in(\DSP48E1) - select (param(dspD, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && nusers(port(dspD, \A, SigSpec())) > 1 && nusers(port(dspD, \ACIN, SigSpec())) == 0) || (param(dspD, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT" && nusers(port(dspD, \B, SigSpec())) > 1 && nusers(port(dspD, \BCIN, SigSpec())) == 0) -endmatch - -code sigA sigB - auto unextend = [](const SigSpec &sig) { - int i; - for (i = GetSize(sig)-1; i > 0; i--) - if (sig[i] != sig[i-1]) - break; - // Do not remove non-const sign bit - if (sig[i].wire) - ++i; - return sig.extract(0, i); - }; - if (param(dspD, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT") - sigA = unextend(port(dspD, \A)); - if (param(dspD, \B_INPUT, Const("DIRECT")).decode_string() == "DIRECT") - sigB = unextend(port(dspD, \B)); -endcode - -code argQ ffA2 ffA2cemux ffA2rstmux ffA2cepol ffArstpol ffA1 ffA1cemux ffA1rstmux ffA1cepol sigA clock - if (!sigA.empty()) { - argQ = sigA; - subpattern(in_dffe); - if (dff) { - ffA2 = dff; - clock = dffclock; - if (dffrstmux) { - ffA2rstmux = dffrstmux; - ffArstpol = dffrstpol; - } - if (dffcemux) { - ffA2cemux = dffcemux; - ffA2cepol = dffcepol; - } - sigA = dffD; - - // Now attempt to match A1 - argQ = sigA; - subpattern(in_dffe); - if (dff) { - if ((ffA2rstmux != nullptr) ^ (dffrstmux != nullptr)) - goto reject_ffA1; - if (dffrstmux) { - if (ffArstpol != dffrstpol) - goto reject_ffA1; - if (port(ffA2rstmux, \S) != port(dffrstmux, \S)) - goto reject_ffA1; - ffA1rstmux = dffrstmux; - } - - ffA1 = dff; - clock = dffclock; - - if (dffcemux) { - ffA1cemux = dffcemux; - ffA1cepol = dffcepol; - } - sigA = dffD; - -reject_ffA1: ; - } - } - } -endcode - -match dspQA2 - if ffA1 - select dspQA2->type.in(\DSP48E1) - select param(dspQA2, \A_REG, 2).as_int() == 2 - select nusers(port(dspQA2, \A, SigSpec())) > 1 - select nusers(port(dspQA2, \ACOUT, SigSpec())) == 0 - slice offset GetSize(port(dspQA2, \A)) - index port(dspQA2, \A)[offset] === sigA[0] - index port(dspQA2, \CLK, State::S0) === port(dspD, \CLK, State::S0) - - // Check that the rest of sigA is present - filter GetSize(port(dspQA2, \A)) >= offset + GetSize(sigA) - filter port(dspQA2, \A).extract(offset, GetSize(sigA)) == sigA - - optional -endmatch - -code - if (dspQA2) { - // Check CE and RST are compatible - if ((ffA1cemux != nullptr) == port(dspQA2, \CEA1, State::S1).is_fully_const()) - reject; - if ((ffA2cemux != nullptr) == port(dspQA2, \CEA2, State::S1).is_fully_const()) - reject; - if ((ffA1rstmux != nullptr) == port(dspQA2, \RSTA, State::S0).is_fully_const()) - reject; - if ((ffA2rstmux != nullptr) == port(dspQA2, \RSTA, State::S0).is_fully_const()) - reject; - - if (ffA1cemux) { - if (port(dspQA2, \CEA1) != port(ffA1cemux, \S)) - reject; - // TODO: Support inversions - if (!ffA1cepol) - reject; - } - if (ffA2cemux) { - if (port(dspQA2, \CEA2) != port(ffA2cemux, \S)) - reject; - // TODO: Support inversions - if (!ffA2cepol) - reject; - } - if (ffA1rstmux) { - if (port(dspQA2, \RSTA) != port(ffA1rstmux, \S)) - reject; - // TODO: Support inversions - if (!ffArstpol) - reject; - } - if (ffA2rstmux) { - if (port(dspQA2, \RSTA) != port(ffA2rstmux, \S)) - reject; - // TODO: Support inversions - if (!ffArstpol) - reject; - } - } -endcode - -match dspQA1 - if !dspQA1 && !ffA1 - if ffA2 - select dspQA1->type.in(\DSP48E1) - select param(dspQA1, \A_REG, 2).as_int() == 1 - select nusers(port(dspQA1, \A, SigSpec())) > 1 - select nusers(port(dspQA1, \ACOUT, SigSpec())) == 0 - slice offset GetSize(port(dspQA1, \A)) - index port(dspQA1, \A)[offset] === sigA[0] - index port(dspQA1, \CLK, State::S0) === port(dspD, \CLK, State::S0) - - // Check that the rest of sigA is present - filter GetSize(port(dspQA1, \A)) >= offset + GetSize(sigA) - filter port(dspQA1, \A).extract(offset, GetSize(sigA)) == sigA - - optional -endmatch - -code - if (dspQA1) { - // Check CE and RST are compatible - if ((ffA2cemux != NULL) == port(dspQA1, \CEA2, State::S1).is_fully_const()) - reject; - if ((ffA2rstmux != NULL) == port(dspQA1, \RSTA, State::S0).is_fully_const()) - reject; - - if (!ffA2cepol || !ffArstpol) - reject; - - if (ffA2cemux) { - if (port(dspQA1, \CEA2) != port(ffA2cemux, \S)) - reject; - // TODO: Support inversions - if (!ffA2cepol) - reject; - } - if (ffA2rstmux) { - if (port(dspQA1, \RSTA) != port(ffA2rstmux, \S)) - reject; - // TODO: Support inversions - if (!ffArstpol) - reject; - } - } -endcode - -code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol ffB1 ffB1cemux ffB1rstmux ffB1cepol sigB clock - if (!sigB.empty()) { - argQ = sigB; - subpattern(in_dffe); - if (dff) { - ffB2 = dff; - clock = dffclock; - if (dffrstmux) { - ffB2rstmux = dffrstmux; - ffBrstpol = dffrstpol; - } - if (dffcemux) { - ffB2cemux = dffcemux; - ffB2cepol = dffcepol; - } - sigB = dffD; - - // Now attempt to match B1 - argQ = sigB; - subpattern(in_dffe); - if (dff) { - if ((ffB2rstmux != nullptr) ^ (dffrstmux != nullptr)) - goto reject_ffB1; - if (dffrstmux) { - if (ffBrstpol != dffrstpol) - goto reject_ffB1; - if (port(ffB2rstmux, \S) != port(dffrstmux, \S)) - goto reject_ffB1; - ffB1rstmux = dffrstmux; - } - - ffB1 = dff; - clock = dffclock; - - if (dffcemux) { - ffB1cemux = dffcemux; - ffB1cepol = dffcepol; - } - sigB = dffD; - -reject_ffB1: ; - } - } - } -endcode - -match dspQB2 - if ffB1 - select dspQB2->type.in(\DSP48E1) - select param(dspQB2, \B_REG, 2).as_int() == 2 - select nusers(port(dspQB2, \B, SigSpec())) > 1 - select nusers(port(dspQB2, \BCOUT, SigSpec())) == 0 - slice offset GetSize(port(dspQB2, \B)) - index port(dspQB2, \B)[offset] === sigB[0] - index port(dspQB2, \CLK, State::S0) === port(dspD, \CLK, State::S0) - - // Check that the rest of sigB is present - filter GetSize(port(dspQB2, \B)) >= offset + GetSize(sigB) - filter port(dspQB2, \B).extract(offset, GetSize(sigB)) == sigB - - optional -endmatch - -code - if (dspQB2) { - // Check CE and RST are compatible - if ((ffB1cemux != nullptr) == port(dspQB2, \CEB1, State::S1).is_fully_const()) - reject; - if ((ffB2cemux != NULL) == port(dspQB2, \CEB2, State::S1).is_fully_const()) - reject; - if ((ffB1rstmux != NULL) == port(dspQB2, \RSTB, State::S0).is_fully_const()) - reject; - if ((ffB2rstmux != NULL) == port(dspQB2, \RSTB, State::S0).is_fully_const()) - reject; - - if (ffB1cemux) { - if (port(dspQB2, \CEB1) != port(ffB1cemux, \S)) - reject; - // TODO: Support inversions - if (!ffB1cepol) - reject; - } - if (ffB2cemux) { - if (port(dspQB2, \CEB2) != port(ffB2cemux, \S)) - reject; - // TODO: Support inversions - if (!ffB2cepol) - reject; - } - if (ffB2rstmux) { - if (port(dspQB2, \RSTB) != port(ffB2rstmux, \S)) - reject; - // TODO: Support inversions - if (!ffBrstpol) - reject; - } - } -endcode - -match dspQB1 - if !dspQB1 && !ffB1 - if ffB2 - select dspQB1->type.in(\DSP48E1) - select param(dspQB1, \B_REG, 2).as_int() >= 1 - select nusers(port(dspQB1, \B, SigSpec())) > 1 - select nusers(port(dspQB1, \BCOUT, SigSpec())) == 0 - slice offset GetSize(port(dspQB1, \B)) - index port(dspQB1, \B)[offset] === sigB[0] - index port(dspQB1, \CLK, State::S0) === port(dspD, \CLK, State::S0) - - // Check that the rest of sigB is present - filter GetSize(port(dspQB1, \B)) >= offset + GetSize(sigB) - filter port(dspQB1, \B).extract(offset, GetSize(sigB)) == sigB - - optional -endmatch - -code - if (dspQB1) { - // Check CE and RST are compatible - if ((ffB2cemux != NULL) != port(dspQB1, \CEB2, State::S1).is_fully_const()) - reject; - if ((ffB2rstmux != NULL) != port(dspQB1, \RSTB, State::S0).is_fully_const()) - reject; - - if (!ffA2cepol || !ffArstpol) - reject; - - if (ffA2cemux) { - if (port(dspQB1, \CEB2) != port(ffB2cemux, \S)) - reject; - // TODO: Support inversions - if (!ffA2cepol) - reject; - } - if (ffA2rstmux) { - if (port(dspQB1, \RSTB) != port(ffB2rstmux, \S)) - reject; - // TODO: Support inversions - if (!ffArstpol) - reject; - } - } -endcode - -code - if (dspQA1 || dspQA2) { - dspD->setParam(\A_INPUT, Const("CASCADE")); - dspD->setPort(\A, Const(0, 30)); - - Wire *cascade = module->addWire(NEW_ID, 30); - if (dspQA1) { - dspQA1->setParam(\ACASCREG, 1); - dspQA1->setPort(\ACOUT, cascade); - log_debug("ACOUT -> ACIN cascade for %s -> %s\n", log_id(dspQA1), log_id(dspD)); - } - else if (dspQA2) { - dspQA2->setParam(\ACASCREG, 2); - dspQA2->setPort(\ACOUT, cascade); - log_debug("ACOUT -> ACIN cascade for %s -> %s\n", log_id(dspQA2), log_id(dspD)); - } - else - log_abort(); - - dspD->setPort(\ACIN, cascade); - did_something = true; - } - if (dspQB1 || dspQB2) { - dspD->setParam(\B_INPUT, Const("CASCADE")); - dspD->setPort(\B, Const(0, 18)); - - Wire *cascade = module->addWire(NEW_ID, 18); - if (dspQB1) { - dspQB1->setParam(\BCASCREG, 1); - dspQB1->setPort(\BCOUT, cascade); - log_debug("BCOUT -> BCIN cascade for %s -> %s\n", log_id(dspQB1), log_id(dspD)); - } - else if (dspQB2) { - dspQB2->setParam(\BCASCREG, 2); - dspQB2->setPort(\BCOUT, cascade); - log_debug("BCOUT -> BCIN cascade for %s -> %s\n", log_id(dspQB2), log_id(dspD)); - } - else - log_abort(); - - dspD->setPort(\BCIN, cascade); - did_something = true; - } - - accept; -endcode - - // ####################### subpattern in_dffe @@ -525,6 +244,9 @@ code reject; if (c.wire->get_bool_attribute(\keep)) reject; + Const init = c.wire->attributes.at(\init, State::Sx); + if (!init.is_fully_undef() && !init.is_fully_zero()) + reject; } endcode From 58f31096abbb0bc68c8339c88b7db410b8edcdba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 13:40:38 -0700 Subject: [PATCH 349/356] Zero out ports --- passes/pmgen/xilinx_dsp_cascade.pmg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg index 2fc943a66..d4b4b8e22 100644 --- a/passes/pmgen/xilinx_dsp_cascade.pmg +++ b/passes/pmgen/xilinx_dsp_cascade.pmg @@ -67,7 +67,7 @@ finally Wire *cascade = module->addWire(NEW_ID, 30); dsp_pcin->setPort(ID(ACIN), cascade); dsp->setPort(ID(ACOUT), cascade); - dsp_pcin->unsetPort(ID(A)); + dsp_pcin->setPort(ID(A), Const(0, 30)); add_siguser(cascade, dsp_pcin); add_siguser(cascade, dsp); @@ -80,7 +80,7 @@ finally Wire *cascade = module->addWire(NEW_ID, 18); dsp_pcin->setPort(ID(BCIN), cascade); dsp->setPort(ID(BCOUT), cascade); - dsp_pcin->unsetPort(ID(B)); + dsp_pcin->setPort(ID(B), Const(0, 18)); add_siguser(cascade, dsp_pcin); add_siguser(cascade, dsp); From 95f0dd57df5209f77df6771e381b87871ab9860a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 13:44:41 -0700 Subject: [PATCH 350/356] Update doc --- passes/pmgen/xilinx_dsp.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index b0251de50..5ccc47ba8 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -578,7 +578,8 @@ struct XilinxDspPass : public Pass { log("Use of the dedicated 'PCOUT' -> 'PCIN' cascade path is detected for 'P' -> 'C'\n"); log("connections (optionally, where 'P' is right-shifted by 17-bits and used as an\n"); log("input to the post-adder -- a pattern common for summing partial products to\n"); - log("implement wide multipliers).\n"); + log("implement wide multipliers). Initial support also exists for similar cascading\n"); + log("for AREG and BREG using '[AB]OUT' -> '[AB]IN'.\n"); log("\n"); log("\n"); log("Experimental feature: addition/subtractions less than 12 or 24 bits with the\n"); From 5b9deef10df2ab958112f6ff55f27776e492f187 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 13:59:05 -0700 Subject: [PATCH 351/356] Do not always zero out C (e.g. during cascade breaks) --- passes/pmgen/xilinx_dsp.cc | 2 -- passes/pmgen/xilinx_dsp_cascade.pmg | 8 +++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 5ccc47ba8..6ce5f2e16 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -24,8 +24,6 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -bool did_something; - #include "passes/pmgen/xilinx_dsp_pm.h" #include "passes/pmgen/xilinx_dsp_CREG_pm.h" #include "passes/pmgen/xilinx_dsp_cascade_pm.h" diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg index d4b4b8e22..714316808 100644 --- a/passes/pmgen/xilinx_dsp_cascade.pmg +++ b/passes/pmgen/xilinx_dsp_cascade.pmg @@ -40,11 +40,10 @@ finally for (int i = 1; i < GetSize(longest_chain); i++) { std::tie(dsp_pcin,P,AREG,BREG) = longest_chain[i]; - dsp_pcin->setPort(ID(C), Const(0, 48)); - if (i % MAX_DSP_CASCADE > 0) { if (P >= 0) { Wire *cascade = module->addWire(NEW_ID, 48); + dsp_pcin->setPort(ID(C), Const(0, 48)); dsp_pcin->setPort(ID(PCIN), cascade); dsp->setPort(ID(PCOUT), cascade); add_siguser(cascade, dsp_pcin); @@ -65,9 +64,9 @@ finally } if (AREG >= 0) { Wire *cascade = module->addWire(NEW_ID, 30); + dsp_pcin->setPort(ID(A), Const(0, 30)); dsp_pcin->setPort(ID(ACIN), cascade); dsp->setPort(ID(ACOUT), cascade); - dsp_pcin->setPort(ID(A), Const(0, 30)); add_siguser(cascade, dsp_pcin); add_siguser(cascade, dsp); @@ -78,9 +77,9 @@ finally } if (BREG >= 0) { Wire *cascade = module->addWire(NEW_ID, 18); + dsp_pcin->setPort(ID(B), Const(0, 18)); dsp_pcin->setPort(ID(BCIN), cascade); dsp->setPort(ID(BCOUT), cascade); - dsp_pcin->setPort(ID(B), Const(0, 18)); add_siguser(cascade, dsp_pcin); add_siguser(cascade, dsp); @@ -97,7 +96,6 @@ finally dsp = dsp_pcin; } - did_something = true; accept; } endcode From 26657037b8de3cf09bafb2bca3940515dad96222 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 26 Sep 2019 14:31:02 -0700 Subject: [PATCH 352/356] Update doc with max cascade chain of 20 --- passes/pmgen/xilinx_dsp.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 6ce5f2e16..11c7e5ea8 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -576,8 +576,10 @@ struct XilinxDspPass : public Pass { log("Use of the dedicated 'PCOUT' -> 'PCIN' cascade path is detected for 'P' -> 'C'\n"); log("connections (optionally, where 'P' is right-shifted by 17-bits and used as an\n"); log("input to the post-adder -- a pattern common for summing partial products to\n"); - log("implement wide multipliers). Initial support also exists for similar cascading\n"); - log("for AREG and BREG using '[AB]OUT' -> '[AB]IN'.\n"); + log("implement wide multipliers). Limited support also exists for similar cascading\n"); + log("for A and B using '[AB]COUT' -> '[AB]CIN'. Currently, cascade chains are limited\n"); + log("to a maximum length of 20 cells, corresponding to the smallest Xilinx 7 Series\n"); + log("device.\n"); log("\n"); log("\n"); log("Experimental feature: addition/subtractions less than 12 or 24 bits with the\n"); From aebbfffd71ab6a85f86ef44f40b1d46a7d6a60ee Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Sep 2019 11:57:53 -0700 Subject: [PATCH 353/356] Ooops AREG and BREG to default to -1 --- passes/pmgen/xilinx_dsp_cascade.pmg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg index 714316808..6f4ac5849 100644 --- a/passes/pmgen/xilinx_dsp_cascade.pmg +++ b/passes/pmgen/xilinx_dsp_cascade.pmg @@ -146,7 +146,7 @@ code next endcode code argQ clock AREG - AREG = 0; + AREG = -1; if (next) { Cell *prev = std::get<0>(chain.back()); if (param(prev, \AREG, 2).as_int() > 0 && @@ -175,7 +175,7 @@ reject_AREG: ; endcode code argQ clock BREG - BREG = 0; + BREG = -1; if (next) { Cell *prev = std::get<0>(chain.back()); if (param(prev, \BREG, 2).as_int() > 0 && From 90236025b7e1409027550451abe4ffc1cc63f128 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Sep 2019 14:21:47 -0700 Subject: [PATCH 354/356] Missing (* mul2dsp *) for sliceB --- techlibs/common/mul2dsp.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 6dcdcf226..4cabb4453 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -198,7 +198,7 @@ module _80_mul (A, B, Y); if (i == 0) assign partial_sum[i] = partial[i]; else - assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[i-1]; + assign partial_sum[i] = (partial[i] << (* mul2dsp *) i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) partial_sum[i-1]; end \$__mul #( @@ -212,7 +212,7 @@ module _80_mul (A, B, Y); .B(B[B_WIDTH-1 -: last_B_WIDTH]), .Y(last_partial) ); - assign partial_sum[n] = (last_partial << n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + partial_sum[n-1]; + assign partial_sum[n] = (last_partial << (* mul2dsp *) n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) partial_sum[n-1]; assign Y = partial_sum[n]; end else begin From b3d8a60cbd94176076f23c4ea6c94ec24e6773e0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Sep 2019 14:32:07 -0700 Subject: [PATCH 355/356] Re-order --- techlibs/ice40/synth_ice40.cc | 2 +- techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 52e13bdc2..841f10244 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -277,9 +277,9 @@ struct SynthIce40Pass : public ScriptPass "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " "-D DSP_NAME=$__MUL16X16", "(if -dsp)"); run("select a:mul2dsp", " (if -dsp)"); + run("setattr -unset mul2dsp", " (if -dsp)"); run("opt_expr -fine", " (if -dsp)"); run("wreduce", " (if -dsp)"); - run("setattr -unset mul2dsp", " (if -dsp)"); run("select -clear", " (if -dsp)"); run("ice40_dsp", " (if -dsp)"); run("chtype -set $mul t:$__soft_mul", "(if -dsp)"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index d73cc3b16..6c58e0913 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -347,9 +347,9 @@ struct SynthXilinxPass : public ScriptPass "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); run("select a:mul2dsp"); + run("setattr -unset mul2dsp"); run("opt_expr -fine"); run("wreduce"); - run("setattr -unset mul2dsp"); run("select -clear"); run("xilinx_dsp"); run("chtype -set $mul t:$__soft_mul"); From 8c2b4f0a50678f949418b7b7329550615fadde83 Mon Sep 17 00:00:00 2001 From: Henner Zeller Date: Sun, 29 Sep 2019 00:17:40 -0700 Subject: [PATCH 356/356] Avoid work in replace() if rules empty. This speeds up processing when number of bits are large but there is actually nothing to replace. Adresses part of #1382. Signed-off-by: Henner Zeller --- kernel/rtlil.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 1d380135b..17be28f78 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3083,6 +3083,7 @@ void RTLIL::SigSpec::replace(const dict &rules, RT log_assert(other != NULL); log_assert(width_ == other->width_); + if (rules.empty()) return; unpack(); other->unpack(); @@ -3107,6 +3108,7 @@ void RTLIL::SigSpec::replace(const std::map &rules log_assert(other != NULL); log_assert(width_ == other->width_); + if (rules.empty()) return; unpack(); other->unpack();