Merge pull request #1474 from litghost/fix_new_bram36_features

Fix new BRAM36 features.
diff --git a/fuzzers/027-bram36-config/Makefile b/fuzzers/027-bram36-config/Makefile
index 98141f9..4d3d8de 100644
--- a/fuzzers/027-bram36-config/Makefile
+++ b/fuzzers/027-bram36-config/Makefile
@@ -7,14 +7,14 @@
 # SPDX-License-Identifier: ISC
 # read/write width is relatively slow to resolve
 # Even slower with multi bit masks...
-N ?= 10
+N ?= 20
 
 include ../fuzzer.mk
 
 database: build/segbits_bramx.db
 
 build/segbits_bramx.rdb: $(SPECIMENS_OK)
-	${XRAY_SEGMATCH} -o build/segbits_bramx.rdb $(addsuffix /segdata_bram_[lr].txt,$(SPECIMENS))
+	${XRAY_SEGMATCH} -c 1 -o build/segbits_bramx.rdb $(addsuffix /segdata_bram_[lr].txt,$(SPECIMENS))
 
 build/segbits_bramx.db: build/segbits_bramx.rdb
 	${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@
diff --git a/fuzzers/027-bram36-config/README.md b/fuzzers/027-bram36-config/README.md
new file mode 100644
index 0000000..8b20de7
--- /dev/null
+++ b/fuzzers/027-bram36-config/README.md
@@ -0,0 +1,29 @@
+RAMB36 features
+===============
+
+This fuzzer emits features that only are used in the RAMB36E1 cell.  There are
+3 categories:
+
+ - ECC
+ - RAM extension
+ - Odd address modes
+
+Odd address modes
+-----------------
+
+Most RAMB36E1 address widths are expressed by configuring the underlying
+RAMB18E1 to handle half of the data.  So `RAMB36.READ_WIDTH = 4` is
+expressed as `RAM18_Y0.READ_WIDTH = 2` and `RAM18_Y1.READ_WIDTH = 2`.  However
+two address widths (1 and 9) are odd (e.g. not divisible by 2).  In these
+cases, a RAMB36E1 specific feature is used.  So `RAMB36.READ_WIDTH = 9` is
+expressed as:
+
+ - `RAMB18_Y0.READ_WIDTH_4`
+ - `RAMB18_Y1.READ_WIDTH_4`
+ - `RAMB36.BRAM36_READ_WIDTH_1`
+
+and `RAMB36.READ_WIDTH = 1` is expressed as:
+
+ - `RAMB18_Y0.READ_WIDTH_1`
+ - `RAMB18_Y1.READ_WIDTH_1`
+ - `RAMB36.BRAM36_READ_WIDTH_1`
diff --git a/fuzzers/027-bram36-config/generate.py b/fuzzers/027-bram36-config/generate.py
index 2d679d3..ce0c79c 100644
--- a/fuzzers/027-bram36-config/generate.py
+++ b/fuzzers/027-bram36-config/generate.py
@@ -36,13 +36,23 @@
         if tile_param['BRAM36_IN_USE']:
             write_ram_ext_tags(segmk, tile_param)
 
-            segmk.add_site_tag(tile_param['site'], 'BRAM36_IN_USE', 1)
             segmk.add_site_tag(
                 tile_param['site'], 'EN_ECC_READ', tile_param['EN_ECC_READ'])
             segmk.add_site_tag(
                 tile_param['site'], 'EN_ECC_WRITE', tile_param['EN_ECC_WRITE'])
-        else:
-            segmk.add_site_tag(tile_param['site'], 'BRAM36_IN_USE', 0)
+
+    for ab in 'ab':
+        for rw in 'rw':
+            if rw == 'r':
+                dir = 'READ'
+            else:
+                dir = 'WRITE'
+
+            width = tile_param['bram36_{}{}_width'.format(rw, ab)]
+            tag = 'BRAM36_{}_WIDTH_{}_1'.format(dir, ab.upper())
+            if width == 1:
+                segmk.add_site_tag(
+                    tile_param['site'], tag, tile_param['BRAM36_IN_USE'])
 
     segmk.compile()
     segmk.write()
diff --git a/fuzzers/027-bram36-config/top.py b/fuzzers/027-bram36-config/top.py
index 26ce066..4a60eaa 100644
--- a/fuzzers/027-bram36-config/top.py
+++ b/fuzzers/027-bram36-config/top.py
@@ -47,6 +47,9 @@
     "UPPER",
 ]
 
+BRAM36_WIDTHS = [1, 2]
+BRAM36_TO_18_WIDTHS = {1: 1, 2: 1}
+
 
 def main():
     db = Database(util.get_db_root(), util.get_part())
@@ -59,9 +62,27 @@
     params = []
     for tile_name, bram36_site_name, bram18_site_name, fifo18_site_name in gen_bram36(
             grid):
+        bram36_ra_width = random.choice(BRAM36_WIDTHS)
+        bram36_wa_width = random.choice(BRAM36_WIDTHS)
+        bram36_rb_width = random.choice(BRAM36_WIDTHS)
+        bram36_wb_width = random.choice(BRAM36_WIDTHS)
+
+        bram18_ra_width = BRAM36_TO_18_WIDTHS[bram36_ra_width]
+        bram18_wa_width = BRAM36_TO_18_WIDTHS[bram36_wa_width]
+        bram18_rb_width = BRAM36_TO_18_WIDTHS[bram36_rb_width]
+        bram18_wb_width = BRAM36_TO_18_WIDTHS[bram36_wb_width]
+
         if random.random() < .8:
-            ram_extension_a = random.choice(RAM_EXTENSION_OPTS)
-            ram_extension_b = random.choice(RAM_EXTENSION_OPTS)
+            if bram36_ra_width == 1 and bram36_wa_width == 1:
+                ram_extension_a = random.choice(RAM_EXTENSION_OPTS)
+            else:
+                ram_extension_a = 'NONE'
+
+            if bram36_rb_width == 1 and bram36_wb_width == 1:
+                ram_extension_b = random.choice(RAM_EXTENSION_OPTS)
+            else:
+                ram_extension_b = 'NONE'
+
             en_ecc_read = random.randint(0, 1)
             en_ecc_write = random.randint(0, 1)
 
@@ -69,10 +90,10 @@
                 '''
                 (* KEEP, DONT_TOUCH, LOC = "{site}" *)
                 RAMB36E1 #(
-                    .READ_WIDTH_A(1),
-                    .WRITE_WIDTH_A(1),
-                    .READ_WIDTH_B(1),
-                    .WRITE_WIDTH_B(1),
+                    .READ_WIDTH_A({bram36_ra_width}),
+                    .WRITE_WIDTH_A({bram36_wa_width}),
+                    .READ_WIDTH_B({bram36_rb_width}),
+                    .WRITE_WIDTH_B({bram36_wb_width}),
                     .RAM_EXTENSION_A({ram_extension_a}),
                     .RAM_EXTENSION_B({ram_extension_b}),
                     .EN_ECC_READ({en_ecc_read}),
@@ -106,6 +127,10 @@
                     ram_extension_b=verilog.quote(ram_extension_b),
                     en_ecc_read=en_ecc_read,
                     en_ecc_write=en_ecc_write,
+                    bram36_ra_width=bram36_ra_width,
+                    bram36_wa_width=bram36_wa_width,
+                    bram36_rb_width=bram36_rb_width,
+                    bram36_wb_width=bram36_wb_width,
                 ))
 
             params.append(
@@ -117,16 +142,20 @@
                     'RAM_EXTENSION_B': ram_extension_b,
                     'EN_ECC_READ': en_ecc_read,
                     'EN_ECC_WRITE': en_ecc_write,
+                    'bram36_ra_width': bram36_ra_width,
+                    'bram36_wa_width': bram36_wa_width,
+                    'bram36_rb_width': bram36_rb_width,
+                    'bram36_wb_width': bram36_wb_width,
                 })
         else:
             print(
                 '''
                 (* KEEP, DONT_TOUCH, LOC = "{bram18}" *)
                 RAMB18E1 #(
-                    .READ_WIDTH_A(1),
-                    .WRITE_WIDTH_A(1),
-                    .READ_WIDTH_B(1),
-                    .WRITE_WIDTH_B(1)
+                    .READ_WIDTH_A({bram18_ra_width}),
+                    .WRITE_WIDTH_A({bram18_wa_width}),
+                    .READ_WIDTH_B({bram18_rb_width}),
+                    .WRITE_WIDTH_B({bram18_wb_width})
                     ) bram_{bram18} (
                         .CLKARDCLK(),
                         .CLKBWRCLK(),
@@ -153,10 +182,10 @@
 
                 (* KEEP, DONT_TOUCH, LOC = "{fifo18}" *)
                 RAMB18E1 #(
-                    .READ_WIDTH_A(1),
-                    .WRITE_WIDTH_A(1),
-                    .READ_WIDTH_B(1),
-                    .WRITE_WIDTH_B(1)
+                    .READ_WIDTH_A({bram18_ra_width}),
+                    .WRITE_WIDTH_A({bram18_wa_width}),
+                    .READ_WIDTH_B({bram18_rb_width}),
+                    .WRITE_WIDTH_B({bram18_wb_width})
                     ) bram_{fifo18} (
                         .CLKARDCLK(),
                         .CLKBWRCLK(),
@@ -183,6 +212,10 @@
                 '''.format(
                     bram18=bram18_site_name,
                     fifo18=fifo18_site_name,
+                    bram18_ra_width=bram18_ra_width,
+                    bram18_wa_width=bram18_wa_width,
+                    bram18_rb_width=bram18_rb_width,
+                    bram18_wb_width=bram18_wb_width,
                 ))
 
             params.append(
@@ -190,6 +223,10 @@
                     'tile': tile_name,
                     'BRAM36_IN_USE': False,
                     'site': bram36_site_name,
+                    'bram36_ra_width': bram36_ra_width,
+                    'bram36_wa_width': bram36_wa_width,
+                    'bram36_rb_width': bram36_rb_width,
+                    'bram36_wb_width': bram36_wb_width,
                 })
 
     print("endmodule")