From 419130a11abd9795a5bf9bb0ddb3e7344ddd2c3f Mon Sep 17 00:00:00 2001 From: John McMaster Date: Thu, 25 Oct 2018 10:18:34 -0700 Subject: [PATCH 1/2] 101-bram-config: READ/WRITE_WIDTH Signed-off-by: John McMaster --- fuzzers/101-bram-config/Makefile | 3 +- fuzzers/101-bram-config/generate.py | 77 +++++++++++++++++++++++------ fuzzers/101-bram-config/top.py | 17 ++++++- minitests/bram_basic/Makefile | 2 + minitests/bram_basic/top.v | 71 +++++++++++++++++++++----- 5 files changed, 143 insertions(+), 27 deletions(-) diff --git a/fuzzers/101-bram-config/Makefile b/fuzzers/101-bram-config/Makefile index d764becb..ccd825a4 100644 --- a/fuzzers/101-bram-config/Makefile +++ b/fuzzers/101-bram-config/Makefile @@ -1,4 +1,5 @@ -N := 1 +# read/write width is relatively slow to resolve +N := 2 SPECIMENS := $(addprefix build/specimen_,$(shell seq -f '%03.0f' $(N))) SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS)) diff --git a/fuzzers/101-bram-config/generate.py b/fuzzers/101-bram-config/generate.py index 22bddcfb..29c22f9f 100644 --- a/fuzzers/101-bram-config/generate.py +++ b/fuzzers/101-bram-config/generate.py @@ -5,19 +5,8 @@ import json from prjxray.segmaker import Segmaker from prjxray import verilog -segmk = Segmaker("design.bits", verbose=True) -#segmk.set_def_bt('BLOCK_RAM') - -print("Loading tags") -f = open('params.jl', 'r') -f.readline() -for l in f: - j = json.loads(l) - ps = j['params'] - assert j['module'] == 'my_RAMB18E1' - site = verilog.unquote(ps['LOC']) - #print('site', site) +def isenv_tags(segmk, ps, site): # all of these bits are inverted ks = [ ('IS_CLKARDCLK_INVERTED', 'ZINV_CLKARDCLK'), @@ -31,6 +20,9 @@ for l in f: ] for param, tagname in ks: segmk.add_site_tag(site, tagname, 1 ^ verilog.parsei(ps[param])) + + +def bus_tags(segmk, ps, site): ''' parameter DOA_REG = 1'b0; parameter DOB_REG = 1'b0; @@ -45,5 +37,62 @@ for l in f: for i in range(18): segmk.add_site_tag(site, '%s[%u]' % (param, i), 1 ^ bitstr[i]) -segmk.compile() -segmk.write() + +def rw_width_tags(segmk, ps, site): + ''' + Y0.READ_WIDTH_A + width 001_03 001_04 001_05 + 1 0 0 0 + 2 1 0 0 + 4 0 1 0 + 9 1 1 0 + 18 0 0 1 + ''' + ''' + for param, vals in { + "READ_WIDTH_A": [1, 2, 4, 9, 18], + "READ_WIDTH_B": [1, 2, 4, 9, 18], + "WRITE_WIDTH_A": [1, 2, 4, 9, 18], + "WRITE_WIDTH_B": [1, 2, 4, 9, 18], + }.items(): + set_val = int(ps[param]) + for val in vals: + has = set_val == val + segmk.add_site_tag(site, '%s_B0' % (param), has) + ''' + for param in ["READ_WIDTH_A", "READ_WIDTH_B", "WRITE_WIDTH_A", + "WRITE_WIDTH_B"]: + set_val = int(ps[param]) + segmk.add_site_tag(site, '%s_B0' % (param), set_val in (2, 9)) + segmk.add_site_tag(site, '%s_B1' % (param), set_val in (4, 9)) + segmk.add_site_tag(site, '%s_B2' % (param), set_val in (18, )) + + +def run(): + + segmk = Segmaker("design.bits", verbose=True) + #segmk.set_def_bt('BLOCK_RAM') + + print("Loading tags") + f = open('params.jl', 'r') + f.readline() + for l in f: + j = json.loads(l) + ps = j['params'] + assert j['module'] == 'my_RAMB18E1' + site = verilog.unquote(ps['LOC']) + #print('site', site) + + # isenv_tags(segmk, ps, site) + # bus_tags(segmk, ps, site) + rw_width_tags(segmk, ps, site) + + def bitfilter(frame, bit): + # rw_width_tags() aliasing interconnect on large widths + return frame not in (20, 21) + + segmk.compile(bitfilter=bitfilter) + segmk.write() + + +run() diff --git a/fuzzers/101-bram-config/top.py b/fuzzers/101-bram-config/top.py index c9d84b64..a8234553 100644 --- a/fuzzers/101-bram-config/top.py +++ b/fuzzers/101-bram-config/top.py @@ -99,6 +99,12 @@ for loci, (site_type, site) in enumerate(brams): "SRVAL_B": vrandbits(18), "INIT_A": vrandbits(18), "INIT_B": vrandbits(18), + # Datasheet says 72 is legal, but think its a copy paste error from BRAM36 + # also 0 and 36 aren't real sizes + "READ_WIDTH_A": random.choice([1, 2, 4, 9, 18]), + "READ_WIDTH_B": random.choice([1, 2, 4, 9, 18]), + "WRITE_WIDTH_A": random.choice([1, 2, 4, 9, 18]), + "WRITE_WIDTH_B": random.choice([1, 2, 4, 9, 18]), } return ('my_RAMB18E1', ports, params) @@ -211,6 +217,10 @@ module my_RAMB18E1 (input clk, input [7:0] din, output [7:0] dout); parameter INIT_A = 18'b0; parameter INIT_B = 18'b0; + parameter READ_WIDTH_A = 0; + parameter READ_WIDTH_B = 0; + parameter WRITE_WIDTH_A = 0; + parameter WRITE_WIDTH_B = 0; ''') print('''\ (* LOC=LOC *) @@ -240,7 +250,12 @@ print( .SRVAL_A(SRVAL_A), .SRVAL_B(SRVAL_B), .INIT_A(INIT_A), - .INIT_B(INIT_B) + .INIT_B(INIT_B), + + .READ_WIDTH_A(READ_WIDTH_A), + .READ_WIDTH_B(READ_WIDTH_B), + .WRITE_WIDTH_A(WRITE_WIDTH_A), + .WRITE_WIDTH_B(WRITE_WIDTH_B) ) ram ( .CLKARDCLK(din[0]), .CLKBWRCLK(din[1]), diff --git a/minitests/bram_basic/Makefile b/minitests/bram_basic/Makefile index db953213..d5fb4675 100644 --- a/minitests/bram_basic/Makefile +++ b/minitests/bram_basic/Makefile @@ -37,4 +37,6 @@ build/roi_bram18iy1_bit01.diff: build/roi_bramis_bit01.diff: $(MAKE) -f diff.mk OUT_DIFF=build/roi_bramis_bit01.diff PRJL=roi_bramis_bit0 PRJR=roi_bramis_bit1 +build/roi_bram18_width.diff: + $(MAKE) -f diff.mk OUT_DIFF=build/roi_bram18_width.diff PRJL=roi_bram18_width_a PRJR=roi_bram18_width_b diff --git a/minitests/bram_basic/top.v b/minitests/bram_basic/top.v index 376306c1..3fd399b3 100644 --- a/minitests/bram_basic/top.v +++ b/minitests/bram_basic/top.v @@ -265,6 +265,21 @@ module roi_hck(input clk, input [255:0] din, output [255:0] dout); endmodule +/****************************************************************************** +Misc ROI +******************************************************************************/ + +module roi_bram18_width_a(input clk, input [255:0] din, output [255:0] dout); + ram_RAMB18E1 #(.LOC("RAMB18_X0Y40"), .READ_WIDTH_A(1)) + r0(.clk(clk), .din(din[ 0 +: 8]), .dout(dout[ 0 +: 8])); +endmodule + +//"READ_WIDTH_A": [0, 1, 2, 4, 9, 18, 36], +module roi_bram18_width_b(input clk, input [255:0] din, output [255:0] dout); + ram_RAMB18E1 #(.LOC("RAMB18_X0Y40"), .READ_WIDTH_A(0)) + r0(.clk(clk), .din(din[ 0 +: 8]), .dout(dout[ 0 +: 8])); +endmodule + /****************************************************************************** Library ******************************************************************************/ @@ -280,10 +295,33 @@ for i in xrange(0x40): print '.INIT_%02X(INIT),' % i */ module ram_RAMB18E1 (input clk, input [7:0] din, output [7:0] dout); parameter LOC = ""; + parameter INIT0 = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INIT = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter RAM_MODE = "TDP"; + + parameter IS_CLKARDCLK_INVERTED = 1'b0; + parameter IS_CLKBWRCLK_INVERTED = 1'b0; parameter IS_ENARDEN_INVERTED = 1'b0; + parameter IS_ENBWREN_INVERTED = 1'b0; + parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0; + parameter IS_RSTRAMB_INVERTED = 1'b0; + parameter IS_RSTREGARSTREG_INVERTED = 1'b0; + parameter IS_RSTREGB_INVERTED = 1'b0; + parameter RAM_MODE = "TDP"; + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + + parameter DOA_REG = 1'b0; + parameter DOB_REG = 1'b0; + parameter SRVAL_A = 18'b0; + parameter SRVAL_B = 18'b0; + parameter INIT_A = 18'b0; + parameter INIT_B = 18'b0; + + parameter READ_WIDTH_A = 0; + parameter READ_WIDTH_B = 0; + parameter WRITE_WIDTH_A = 0; + parameter WRITE_WIDTH_B = 0; (* LOC=LOC *) RAMB18E1 #( @@ -361,18 +399,29 @@ module ram_RAMB18E1 (input clk, input [7:0] din, output [7:0] dout); .INIT_3E(INIT), .INIT_3F(INIT), - .IS_CLKARDCLK_INVERTED(1'b0), - .IS_CLKBWRCLK_INVERTED(1'b0), + .IS_CLKARDCLK_INVERTED(IS_CLKARDCLK_INVERTED), + .IS_CLKBWRCLK_INVERTED(IS_CLKBWRCLK_INVERTED), .IS_ENARDEN_INVERTED(IS_ENARDEN_INVERTED), - .IS_ENBWREN_INVERTED(1'b0), - .IS_RSTRAMARSTRAM_INVERTED(1'b0), - .IS_RSTRAMB_INVERTED(1'b0), - .IS_RSTREGARSTREG_INVERTED(1'b0), - .IS_RSTREGB_INVERTED(1'b0), + .IS_ENBWREN_INVERTED(IS_ENBWREN_INVERTED), + .IS_RSTRAMARSTRAM_INVERTED(IS_RSTRAMARSTRAM_INVERTED), + .IS_RSTRAMB_INVERTED(IS_RSTRAMB_INVERTED), + .IS_RSTREGARSTREG_INVERTED(IS_RSTREGARSTREG_INVERTED), + .IS_RSTREGB_INVERTED(IS_RSTREGB_INVERTED), .RAM_MODE(RAM_MODE), - .WRITE_MODE_A("WRITE_FIRST"), - .WRITE_MODE_B("WRITE_FIRST"), - .SIM_DEVICE("VIRTEX6") + .WRITE_MODE_A(WRITE_MODE_A), + .WRITE_MODE_B(WRITE_MODE_B), + + .DOA_REG(DOA_REG), + .DOB_REG(DOB_REG), + .SRVAL_A(SRVAL_A), + .SRVAL_B(SRVAL_B), + .INIT_A(INIT_A), + .INIT_B(INIT_B), + + .READ_WIDTH_A(READ_WIDTH_A), + .READ_WIDTH_B(READ_WIDTH_B), + .WRITE_WIDTH_A(WRITE_WIDTH_A), + .WRITE_WIDTH_B(WRITE_WIDTH_B) ) ram ( .CLKARDCLK(din[0]), .CLKBWRCLK(din[1]), From abe9c82575f60f16bf2ba7cf823a40c604de45a6 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Mon, 29 Oct 2018 15:26:52 -0700 Subject: [PATCH 2/2] 101-bram-config: READ/WRITE_WIDTH SRVAL/INIT parity tweaks Signed-off-by: John McMaster --- fuzzers/101-bram-config/Makefile | 2 +- fuzzers/101-bram-config/generate.py | 12 ++++++++--- fuzzers/101-bram-config/top.py | 32 ++++++++++------------------- prjxray/verilog.py | 15 ++++++++++++++ 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/fuzzers/101-bram-config/Makefile b/fuzzers/101-bram-config/Makefile index ccd825a4..6fb1f91c 100644 --- a/fuzzers/101-bram-config/Makefile +++ b/fuzzers/101-bram-config/Makefile @@ -1,5 +1,5 @@ # read/write width is relatively slow to resolve -N := 2 +N := 4 SPECIMENS := $(addprefix build/specimen_,$(shell seq -f '%03.0f' $(N))) SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS)) diff --git a/fuzzers/101-bram-config/generate.py b/fuzzers/101-bram-config/generate.py index 29c22f9f..f89351db 100644 --- a/fuzzers/101-bram-config/generate.py +++ b/fuzzers/101-bram-config/generate.py @@ -34,8 +34,14 @@ def bus_tags(segmk, ps, site): for param, tagname in [('SRVAL_A', 'ZSRVAL_A'), ('SRVAL_B', 'ZSRVAL_B'), ('INIT_A', 'ZINIT_A'), ('INIT_B', 'ZINIT_B')]: bitstr = verilog.parse_bitstr(ps[param]) + ab = param[-1] + # Are all bits present? + hasparity = ps['READ_WIDTH_' + ab] == 18 for i in range(18): - segmk.add_site_tag(site, '%s[%u]' % (param, i), 1 ^ bitstr[i]) + # Magic bit positions from experimentation + # we could just only solve when parity, but this check documents the fine points a bit better + if hasparity or i not in (1, 9): + segmk.add_site_tag(site, '%s[%u]' % (param, i), 1 ^ bitstr[i]) def rw_width_tags(segmk, ps, site): @@ -83,8 +89,8 @@ def run(): site = verilog.unquote(ps['LOC']) #print('site', site) - # isenv_tags(segmk, ps, site) - # bus_tags(segmk, ps, site) + isenv_tags(segmk, ps, site) + bus_tags(segmk, ps, site) rw_width_tags(segmk, ps, site) def bitfilter(frame, bit): diff --git a/fuzzers/101-bram-config/top.py b/fuzzers/101-bram-config/top.py index a8234553..ea5b1e5e 100644 --- a/fuzzers/101-bram-config/top.py +++ b/fuzzers/101-bram-config/top.py @@ -3,6 +3,7 @@ import random random.seed(int(os.getenv("SEED"), 16)) from prjxray import util from prjxray import verilog +from prjxray.verilog import vrandbit, vrandbits import sys import json @@ -57,21 +58,6 @@ print( 'module roi(input clk, input [%d:0] din, output [%d:0] dout);' % (DIN_N - 1, DOUT_N - 1)) - -def vrandbit(): - if random.randint(0, 1): - return "1'b1" - else: - return "1'b0" - - -def vrandbits(n): - ret = "%u'b" % n - for _i in range(n): - ret += str(random.randint(0, 1)) - return ret - - for loci, (site_type, site) in enumerate(brams): def place_bram18(): @@ -80,6 +66,11 @@ for loci, (site_type, site) in enumerate(brams): 'din': 'din[ %d +: 8]' % (8 * loci, ), 'dout': 'dout[ %d +: 8]' % (8 * loci, ), } + + # Datasheet says 72 is legal in some cases, but think its a copy paste error from BRAM36 + # also 0 and 36 aren't real sizes + # Bias choice to 18 as its needed to solve certain bits quickly + widths = [1, 2, 4, 9, 18, 18, 18, 18] params = { 'LOC': verilog.quote(site), 'IS_CLKARDCLK_INVERTED': vrandbit(), @@ -99,13 +90,12 @@ for loci, (site_type, site) in enumerate(brams): "SRVAL_B": vrandbits(18), "INIT_A": vrandbits(18), "INIT_B": vrandbits(18), - # Datasheet says 72 is legal, but think its a copy paste error from BRAM36 - # also 0 and 36 aren't real sizes - "READ_WIDTH_A": random.choice([1, 2, 4, 9, 18]), - "READ_WIDTH_B": random.choice([1, 2, 4, 9, 18]), - "WRITE_WIDTH_A": random.choice([1, 2, 4, 9, 18]), - "WRITE_WIDTH_B": random.choice([1, 2, 4, 9, 18]), + "READ_WIDTH_A": random.choice(widths), + "READ_WIDTH_B": random.choice(widths), + "WRITE_WIDTH_A": random.choice(widths), + "WRITE_WIDTH_B": random.choice(widths), } + return ('my_RAMB18E1', ports, params) def place_bram36(): diff --git a/prjxray/verilog.py b/prjxray/verilog.py index 9ab29a40..029a01fd 100644 --- a/prjxray/verilog.py +++ b/prjxray/verilog.py @@ -1,4 +1,5 @@ import sys +import random def top_harness(DIN_N, DOUT_N, f=sys.stdout): @@ -76,3 +77,17 @@ def parse_bitstr(s): bitstr = postfix[1:] assert len(bitstr) == n return [int(x) for x in bitstr] + + +def vrandbit(): + if random.randint(0, 1): + return "1'b1" + else: + return "1'b0" + + +def vrandbits(n): + ret = "%u'b" % n + for _i in range(n): + ret += str(random.randint(0, 1)) + return ret