Towards Xilinx bram support
authorClifford Wolf <clifford@clifford.at>
Mon, 5 Jan 2015 12:59:04 +0000 (13:59 +0100)
committerClifford Wolf <clifford@clifford.at>
Mon, 5 Jan 2015 12:59:04 +0000 (13:59 +0100)
passes/memory/memory_bram.cc
techlibs/xilinx/brams.txt
techlibs/xilinx/brams.v
techlibs/xilinx/synth_xilinx.cc
techlibs/xilinx/tests/.gitignore [new file with mode: 0644]
techlibs/xilinx/tests/bram1.sh [new file with mode: 0644]
techlibs/xilinx/tests/bram1.v [new file with mode: 0644]
techlibs/xilinx/tests/bram1_tb.v [new file with mode: 0644]

index efabfc06daffec6a91630a57406125ae7b1d7e5d..e7a42f26d50051dec20bda4405237f6445a3d6af 100644 (file)
@@ -215,6 +215,9 @@ struct rules_t
 
        void parse(string filename)
        {
+               if (filename.substr(0, 2) == "+/")
+                       filename = proc_share_dirname() + filename.substr(1);
+
                infile.open(filename);
                linecount = 0;
 
index 7c5fe081faf75acd4d7cf06788f53fea9848e278..69214fd596a2787338c2667529f4fca37e56e124 100644 (file)
@@ -85,7 +85,7 @@ endbram
 
 match $__XILINX_RAMB36_SDP72
   shuffle_enable 8
-  min efficiency 20
+  min efficiency 20
   # or_next_if_better
 endmatch
 
index 067ca8b28223c4616e28d388d70400c247d9ad1a..aaab8d475df48da1ea80eea86121db790b31240d 100644 (file)
@@ -29,6 +29,7 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN
                .RAM_MODE("SDP"),
                .READ_WIDTH_A(72),
                .WRITE_WIDTH_B(72),
+               .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"),
                .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST")
        ) _TECHMAP_REPLACE_ (
                .DOBDO(DO[63:32]),
@@ -41,7 +42,7 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN
                .DIPADIP(DIP[3:0]),
 
                .ADDRARDADDR(A1ADDR_16),
-               .CLKARDCLK(CLK2 == |CLKPOL2),
+               .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2),
                .ENARDEN(|1),
                .REGCEAREGCE(|1),
                .RSTRAMARSTRAM(|0),
@@ -49,7 +50,7 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN
                .WEA(4'b0),
 
                .ADDRBWRADDR(B1ADDR_16),
-               .CLKBWRCLK(CLK3 == |CLKPOL3),
+               .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3),
                .ENBWREN(|1),
                .REGCEB(|0),
                .RSTRAMB(|0),
index 8df5c4e42c137b9f84a7a89cc148a881326f9424..7b7dbd0fdb15c0f2a508a69a99e792021f676359 100644 (file)
@@ -69,25 +69,26 @@ struct SynthXilinxPass : public Pass {
                log("        hierarchy -check -top <top>\n");
                log("\n");
                log("    coarse:\n");
-               log("        proc\n");
-               log("        opt\n");
-               log("        memory\n");
-               log("        clean\n");
-               log("        fsm\n");
-               log("        opt\n");
+               log("        synth -run coarse\n");
+               log("        memory_bram -rules +/xilinx/brams.txt\n");
+               log("        techmap -map +/xilinx/brams.v\n");
                log("\n");
                log("    fine:\n");
                log("        techmap\n");
-               log("        opt\n");
+               log("        opt -fast -full\n");
                log("\n");
                log("    map_luts:\n");
                log("        abc -lut 6\n");
                log("        clean\n");
                log("\n");
                log("    map_cells:\n");
-               log("        techmap -share_map xilinx/cells.v\n");
+               log("        techmap -map +/xilinx/cells.v\n");
                log("        clean\n");
                log("\n");
+               log("    flatten:\n");
+               log("        flatten\n");
+               log("        opt -fast -full\n");
+               log("\n");
                log("    clkbuf:\n");
                log("        select -set xilinx_clocks <top>/t:FDRE %%x:+FDRE[C] <top>/t:FDRE %%d\n");
                log("        iopadmap -inpad BUFGP O:I @xilinx_clocks\n");
@@ -163,18 +164,15 @@ struct SynthXilinxPass : public Pass {
 
                if (check_label(active, run_from, run_to, "coarse"))
                {
-                       Pass::call(design, "proc");
-                       Pass::call(design, "opt");
-                       Pass::call(design, "memory");
-                       Pass::call(design, "clean");
-                       Pass::call(design, "fsm");
-                       Pass::call(design, "opt");
+                       Pass::call(design, "synth -run coarse");
+                       Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
+                       Pass::call(design, "techmap -map +/xilinx/brams.v");
                }
 
                if (check_label(active, run_from, run_to, "fine"))
                {
                        Pass::call(design, "techmap");
-                       Pass::call(design, "opt");
+                       Pass::call(design, "opt -fast -full");
                }
 
                if (check_label(active, run_from, run_to, "map_luts"))
@@ -185,10 +183,16 @@ struct SynthXilinxPass : public Pass {
 
                if (check_label(active, run_from, run_to, "map_cells"))
                {
-                       Pass::call(design, "techmap -share_map xilinx/cells.v");
+                       Pass::call(design, "techmap -map +/xilinx/cells.v");
                        Pass::call(design, "clean");
                }
 
+               if (check_label(active, run_from, run_to, "flatten"))
+               {
+                       Pass::call(design, "flatten");
+                       Pass::call(design, "opt -fast -full");
+               }
+
                if (check_label(active, run_from, run_to, "clkbuf"))
                {
                        Pass::call(design, stringf("select -set xilinx_clocks %s/t:FDRE %%x:+FDRE[C] %s/t:FDRE %%d", top_module.c_str(), top_module.c_str()));
diff --git a/techlibs/xilinx/tests/.gitignore b/techlibs/xilinx/tests/.gitignore
new file mode 100644 (file)
index 0000000..bc2f8ba
--- /dev/null
@@ -0,0 +1,3 @@
+bram1_cmp
+bram1.mk
+bram1_[0-9]*/
diff --git a/techlibs/xilinx/tests/bram1.sh b/techlibs/xilinx/tests/bram1.sh
new file mode 100644 (file)
index 0000000..3a72cce
--- /dev/null
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+echo "all: all_list" > bram1.mk
+all_list="all_list:"
+
+for transp in 0 1; do
+for abits in 1 2 4 8 10 16 20; do
+for dbits in 1 2 4 8 10 16 20 24 30 32 40 48 50 56 60 64 70 72 80; do
+       if [ $(( (1 << $abits) * $dbits )) -gt 1000000 ]; then continue; fi
+       if [ $(( (1 << $abits) * $dbits )) -gt 100 ]; then continue; fi
+       id=`printf "%d%02d%02d" $transp $abits $dbits`
+       echo "Creating bram1_$id.."
+       rm -rf bram1_$id
+       mkdir -p bram1_$id
+       cp bram1.v bram1_tb.v bram1_$id/
+       sed -i "/parameter/ s,ABITS *= *[0-9]*,ABITS = $abits," bram1_$id/*.v
+       sed -i "/parameter/ s,DBITS *= *[0-9]*,DBITS = $dbits," bram1_$id/*.v
+       sed -i "/parameter/ s,TRANSP *= *[0-9]*,TRANSP = $transp," bram1_$id/*.v
+       {
+               echo "set -e"
+               echo "../../../../yosys -q -lsynth.log -p 'synth_xilinx -top bram1; write_verilog synth.v' bram1.v"
+               echo "xvlog --work gold bram1_tb.v bram1.v > gold.txt"
+               echo "xvlog --work gate bram1_tb.v synth.v > gate.txt"
+               echo "xelab -R gold.bram1_tb >> gold.txt"
+               echo "mv testbench.vcd gold.vcd"
+               echo "xelab -L unisim -R gate.bram1_tb >> gate.txt"
+               echo "mv testbench.vcd gate.vcd"
+               echo "../bram1_cmp <( grep '#OUT#' gold.txt; ) <( grep '#OUT#' gate.txt; )"
+       } > bram1_$id/run.sh
+       {
+               echo "bram1_$id/ok:"
+               echo "  @cd bram1_$id && bash run.sh"
+               echo "  @echo -n '[$id]'"
+               echo "  @touch \$@"
+       } >> bram1.mk
+       all_list="$all_list bram1_$id/ok"
+done; done; done
+
+cc -o bram1_cmp ../../../tests/tools/cmp_tbdata.c
+echo "$all_list" >> bram1.mk
+
+echo "Testing..."
+${MAKE:-make} -f bram1.mk
+echo
+
+# echo "Cleaning up..."
+# rm -rf bram1_cmp bram1.mk bram1_[0-9]*/
+
diff --git a/techlibs/xilinx/tests/bram1.v b/techlibs/xilinx/tests/bram1.v
new file mode 100644 (file)
index 0000000..034cc18
--- /dev/null
@@ -0,0 +1,24 @@
+module bram1 #(
+       parameter ABITS = 8, DBITS = 8, TRANSP = 0
+) (
+       input clk,
+
+       input [ABITS-1:0] WR_ADDR,
+       input [DBITS-1:0] WR_DATA,
+       input WR_EN,
+
+       input [ABITS-1:0] RD_ADDR,
+       output [DBITS-1:0] RD_DATA
+);
+       reg [DBITS-1:0] memory [0:2**ABITS-1];
+       reg [ABITS-1:0] RD_ADDR_BUF;
+       reg [DBITS-1:0] RD_DATA_BUF;
+
+       always @(posedge clk) begin
+               if (WR_EN) memory[WR_ADDR] <= WR_DATA;
+               RD_ADDR_BUF <= RD_ADDR;
+               RD_DATA_BUF <= memory[RD_ADDR];
+       end
+
+       assign RD_DATA = TRANSP ? memory[RD_ADDR_BUF] : RD_DATA_BUF;
+endmodule
diff --git a/techlibs/xilinx/tests/bram1_tb.v b/techlibs/xilinx/tests/bram1_tb.v
new file mode 100644 (file)
index 0000000..98e6baf
--- /dev/null
@@ -0,0 +1,73 @@
+module bram1_tb #(
+       parameter ABITS = 8, DBITS = 8, TRANSP = 0
+);
+       reg clk;
+       reg [ABITS-1:0] WR_ADDR;
+       reg [DBITS-1:0] WR_DATA;
+       reg WR_EN;
+       reg [ABITS-1:0] RD_ADDR;
+       wire [DBITS-1:0] RD_DATA;
+
+       bram1 #(
+               // .ABITS(ABITS),
+               // .DBITS(DBITS),
+               // .TRANSP(TRANSP)
+       ) uut  (
+               .clk    (clk    ),
+               .WR_ADDR(WR_ADDR),
+               .WR_DATA(WR_DATA),
+               .WR_EN  (WR_EN  ),
+               .RD_ADDR(RD_ADDR),
+               .RD_DATA(RD_DATA)
+       );
+
+       function [31:0] getaddr(input [3:0] n);
+               begin
+                       case (n)
+                               0: getaddr = 0;
+                               1: getaddr = 2**ABITS-1;
+                               2: getaddr = 'b101 << (ABITS / 3);
+                               3: getaddr = 'b101 << (2*ABITS / 3);
+                               4: getaddr = 'b11011 << (ABITS / 4);
+                               5: getaddr = 'b11011 << (2*ABITS / 4);
+                               6: getaddr = 'b11011 << (3*ABITS / 4);
+                               7: getaddr = 123456789;
+                               default: getaddr = 1 << (2*n-16);
+                       endcase
+               end
+       endfunction
+
+       reg [DBITS-1:0] memory [0:2**ABITS-1];
+       reg [DBITS-1:0] expected_rd;
+
+       integer i, j;
+       initial begin
+               $dumpfile("testbench.vcd");
+               $dumpvars(0, bram1_tb);
+               clk <= 0;
+               for (i = 0; i < 256; i = i+1) begin
+                       WR_DATA <= i;
+                       WR_ADDR <= getaddr(i[7:4]);
+                       RD_ADDR <= getaddr(i[3:0]);
+                       WR_EN <= ^i;
+
+                       #1; clk <= 1;
+                       #1; clk <= 0;
+
+                       if (TRANSP) begin
+                               if (WR_EN) memory[WR_ADDR] = WR_DATA;
+                               expected_rd = memory[RD_ADDR];
+                       end else begin
+                               expected_rd = memory[RD_ADDR];
+                               if (WR_EN) memory[WR_ADDR] = WR_DATA;
+                       end
+
+                       for (j = 0; j < DBITS; j = j+1) begin
+                               if (expected_rd[j] === 1'bx)
+                                       expected_rd[j] = RD_DATA[j];
+                       end
+
+                       $display("#OUT# | WA=%x WD=%x WE=%x | RA=%x RD=%x | %s", WR_ADDR, WR_DATA, WR_EN, RD_ADDR, RD_DATA, expected_rd === RD_DATA ? "ok" : "ERROR");
+               end
+       end
+endmodule