From 5598d39d6d4d88ca2b269158e9bd81bf35a7793a Mon Sep 17 00:00:00 2001 From: Jake Mercer Date: Sun, 29 Sep 2019 13:55:29 +0100 Subject: [PATCH 01/10] IGNORE - Ignore .swp Files Ignore .swp files created by various text editors e.g. VIM. Signed-off-by: Jake Mercer --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b8811137..ec469db3 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ database run.ok __pycache__ *.pyc +*.swp From c575adf8a0f14fdd1c45b69adeee1f17a00a6b99 Mon Sep 17 00:00:00 2001 From: Jake Mercer Date: Sat, 5 Oct 2019 00:09:58 +0100 Subject: [PATCH 02/10] FUZZER - DSP - Add A & B Input Attributes Adding `A_INPUT` and `B_INPUT` attribute fuzzing for the DSP48 tiles. Signed-off-by: Jake Mercer --- fuzzers/100-dsp-mskpat/generate.py | 10 ++++++++++ fuzzers/100-dsp-mskpat/top.py | 23 ++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/fuzzers/100-dsp-mskpat/generate.py b/fuzzers/100-dsp-mskpat/generate.py index ead33cd5..133a71e2 100644 --- a/fuzzers/100-dsp-mskpat/generate.py +++ b/fuzzers/100-dsp-mskpat/generate.py @@ -10,6 +10,16 @@ with open('params.csv', 'r') as f: for d in csv.DictReader(f): dsp = "DSP_0" if d['site'][-1] in "02468" else "DSP_1" + a_input = str(d['a_input']) + segmk.add_site_tag( + d['site'], "%s.A_INPUT[0]" % (dsp), + (1 if a_input == "DIRECT" else 0)) + + b_input = str(d['b_input']) + segmk.add_site_tag( + d['site'], "%s.B_INPUT[0]" % (dsp), + (1 if b_input == "DIRECT" else 0)) + mask = int(d['mask']) pattern = int(d['pattern']) diff --git a/fuzzers/100-dsp-mskpat/top.py b/fuzzers/100-dsp-mskpat/top.py index a64915cb..c32f978c 100644 --- a/fuzzers/100-dsp-mskpat/top.py +++ b/fuzzers/100-dsp-mskpat/top.py @@ -18,9 +18,14 @@ def gen_sites(): def write_params(lines): - pinstr = 'tile,site,mask,pattern\n' - for tile, site, mask, pattern in lines: - pinstr += '%s,%s,%s,%s\n' % (tile, site, mask, pattern) + pinstr = 'tile,site,a_input,b_input,mask,pattern\n' + for tile, site, a_input, b_input, mask, pattern in lines: + pinstr += '%s,' % (tile) + pinstr += '%s,' % (site) + pinstr += '%s,' % (a_input) + pinstr += '%s,' % (b_input) + pinstr += '%s,' % (mask) + pinstr += '%s\n' % (pattern) open('params.csv', 'w').write(pinstr) @@ -36,17 +41,21 @@ module top(); for (tile_name, site_name) in sites: mask = random.randint(0, 2**48 - 1) pattern = random.randint(0, 2**48 - 1) - lines.append((tile_name, site_name, mask, pattern)) + a_input = random.choice(('DIRECT', 'CASCADE')) + b_input = random.choice(('DIRECT', 'CASCADE')) + lines.append((tile_name, site_name, a_input, b_input, mask, pattern)) print( ''' (* KEEP, DONT_TOUCH, LOC = "{0}" *) DSP48E1 #( - .MASK(48'h{1:x}), - .PATTERN(48'h{2:x}) + .A_INPUT("{1}"), + .B_INPUT("{2}"), + .MASK(48'h{3:x}), + .PATTERN(48'h{4:x}) ) dsp_{0} ( ); -'''.format(site_name, mask, pattern)) +'''.format(site_name, a_input, b_input, mask, pattern)) print("endmodule") write_params(lines) From 78d64f755888f6c89968342ded6128cc9943025f Mon Sep 17 00:00:00 2001 From: Jake Mercer Date: Sun, 6 Oct 2019 16:30:10 +0100 Subject: [PATCH 03/10] FUZZER - DSP - Add AUTORESET_PATDET Attribute Fuzzing Added fuzzing for the AUTORESET_PATDET attribute of the DSP48 block. Values are RESET_MATCH, NO_RESET, and RESET_NOT_MATCH; so this can be represented by 2 bits. Signed-off-by: Jake Mercer --- fuzzers/100-dsp-mskpat/generate.py | 11 +++++++++++ fuzzers/100-dsp-mskpat/top.py | 19 +++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/fuzzers/100-dsp-mskpat/generate.py b/fuzzers/100-dsp-mskpat/generate.py index 133a71e2..2dfcc6d9 100644 --- a/fuzzers/100-dsp-mskpat/generate.py +++ b/fuzzers/100-dsp-mskpat/generate.py @@ -20,6 +20,17 @@ with open('params.csv', 'r') as f: d['site'], "%s.B_INPUT[0]" % (dsp), (1 if b_input == "DIRECT" else 0)) + autoreset_patdet = str(d['autoreset_patdet']) + if autoreset_patdet == "RESET_MATCH": + segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) + segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[1]" % (dsp), 0) + elif autoreset_patdet == "NO_RESET": + segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) + segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[1]" % (dsp), 1) + elif autoreset_patdet == "RESET_NOT_MATCH": + segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 1) + segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[1]" % (dsp), 0) + mask = int(d['mask']) pattern = int(d['pattern']) diff --git a/fuzzers/100-dsp-mskpat/top.py b/fuzzers/100-dsp-mskpat/top.py index c32f978c..d536a91e 100644 --- a/fuzzers/100-dsp-mskpat/top.py +++ b/fuzzers/100-dsp-mskpat/top.py @@ -18,12 +18,13 @@ def gen_sites(): def write_params(lines): - pinstr = 'tile,site,a_input,b_input,mask,pattern\n' - for tile, site, a_input, b_input, mask, pattern in lines: + pinstr = 'tile,site,a_input,b_input,autoreset_patdet,mask,pattern\n' + for tile, site, a_input, b_input, autoreset_patdet, mask, pattern in lines: pinstr += '%s,' % (tile) pinstr += '%s,' % (site) pinstr += '%s,' % (a_input) pinstr += '%s,' % (b_input) + pinstr += '%s,' % (autoreset_patdet) pinstr += '%s,' % (mask) pinstr += '%s\n' % (pattern) @@ -43,7 +44,12 @@ module top(); pattern = random.randint(0, 2**48 - 1) a_input = random.choice(('DIRECT', 'CASCADE')) b_input = random.choice(('DIRECT', 'CASCADE')) - lines.append((tile_name, site_name, a_input, b_input, mask, pattern)) + autoreset_patdet = random.choice( + ('NO_RESET', 'RESET_MATCH', 'RESET_NOT_MATCH')) + lines.append( + ( + tile_name, site_name, a_input, b_input, autoreset_patdet, mask, + pattern)) print( ''' @@ -51,11 +57,12 @@ module top(); DSP48E1 #( .A_INPUT("{1}"), .B_INPUT("{2}"), - .MASK(48'h{3:x}), - .PATTERN(48'h{4:x}) + .AUTORESET_PATDET("{3}"), + .MASK(48'h{4:x}), + .PATTERN(48'h{5:x}) ) dsp_{0} ( ); -'''.format(site_name, a_input, b_input, mask, pattern)) +'''.format(site_name, a_input, b_input, autoreset_patdet, mask, pattern)) print("endmodule") write_params(lines) From 624de250e87ae57d2adbc0aa22e7d8da9f934613 Mon Sep 17 00:00:00 2001 From: Jake Mercer Date: Wed, 9 Oct 2019 20:55:39 +0100 Subject: [PATCH 04/10] FUZZER - DSP - Cleared Bits Changed some tags to be prefixed with 'Z'; these bits are cleared and need the prefix to indicate the inversion so that they are resolved to the DB correctly. Signed-off-by: Jake Mercer --- fuzzers/100-dsp-mskpat/generate.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/fuzzers/100-dsp-mskpat/generate.py b/fuzzers/100-dsp-mskpat/generate.py index 2dfcc6d9..6376b62a 100644 --- a/fuzzers/100-dsp-mskpat/generate.py +++ b/fuzzers/100-dsp-mskpat/generate.py @@ -12,24 +12,27 @@ with open('params.csv', 'r') as f: a_input = str(d['a_input']) segmk.add_site_tag( - d['site'], "%s.A_INPUT[0]" % (dsp), - (1 if a_input == "DIRECT" else 0)) + d['site'], "%s.ZA_INPUT[0]" % (dsp), + (0 if a_input == "DIRECT" else 1)) b_input = str(d['b_input']) segmk.add_site_tag( - d['site'], "%s.B_INPUT[0]" % (dsp), - (1 if b_input == "DIRECT" else 0)) + d['site'], "%s.ZB_INPUT[0]" % (dsp), + (0 if b_input == "DIRECT" else 1)) autoreset_patdet = str(d['autoreset_patdet']) if autoreset_patdet == "RESET_MATCH": segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) - segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[1]" % (dsp), 0) + segmk.add_site_tag( + d['site'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 1) elif autoreset_patdet == "NO_RESET": segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) - segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[1]" % (dsp), 1) + segmk.add_site_tag( + d['site'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 0) elif autoreset_patdet == "RESET_NOT_MATCH": segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 1) - segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[1]" % (dsp), 0) + segmk.add_site_tag( + d['site'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 1) mask = int(d['mask']) pattern = int(d['pattern']) From 8da263c50256ecce790c197b9b5cb3e996d7b9d5 Mon Sep 17 00:00:00 2001 From: Jake Mercer Date: Thu, 10 Oct 2019 01:06:13 +0100 Subject: [PATCH 05/10] FUZZER - DSP - Refactor for Readability & Extensibility Signed-off-by: Jake Mercer --- fuzzers/100-dsp-mskpat/generate.py | 32 ++++----- fuzzers/100-dsp-mskpat/top.py | 108 +++++++++++++++++------------ 2 files changed, 80 insertions(+), 60 deletions(-) diff --git a/fuzzers/100-dsp-mskpat/generate.py b/fuzzers/100-dsp-mskpat/generate.py index 6376b62a..5bf19e82 100644 --- a/fuzzers/100-dsp-mskpat/generate.py +++ b/fuzzers/100-dsp-mskpat/generate.py @@ -8,40 +8,40 @@ segmk = Segmaker("design.bits", verbose=True) print("Loading tags") with open('params.csv', 'r') as f: for d in csv.DictReader(f): - dsp = "DSP_0" if d['site'][-1] in "02468" else "DSP_1" + dsp = "DSP_0" if d['SITE'][-1] in "02468" else "DSP_1" - a_input = str(d['a_input']) + a_input = str(d['A_INPUT']) segmk.add_site_tag( - d['site'], "%s.ZA_INPUT[0]" % (dsp), + d['SITE'], "%s.ZA_INPUT[0]" % (dsp), (0 if a_input == "DIRECT" else 1)) - b_input = str(d['b_input']) + b_input = str(d['B_INPUT']) segmk.add_site_tag( - d['site'], "%s.ZB_INPUT[0]" % (dsp), + d['SITE'], "%s.ZB_INPUT[0]" % (dsp), (0 if b_input == "DIRECT" else 1)) - autoreset_patdet = str(d['autoreset_patdet']) + autoreset_patdet = str(d['AUTORESET_PATDET']) if autoreset_patdet == "RESET_MATCH": - segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) segmk.add_site_tag( - d['site'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 1) + d['SITE'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 1) elif autoreset_patdet == "NO_RESET": - segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) segmk.add_site_tag( - d['site'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 0) + d['SITE'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 0) elif autoreset_patdet == "RESET_NOT_MATCH": - segmk.add_site_tag(d['site'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 1) + segmk.add_site_tag(d['SITE'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 1) segmk.add_site_tag( - d['site'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 1) + d['SITE'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 1) - mask = int(d['mask']) - pattern = int(d['pattern']) + mask = int(d['MASK']) + pattern = int(d['PATTERN']) for i in range(48): segmk.add_site_tag( - d['site'], "%s.MASK[%d]" % (dsp, i), (mask >> i) & 1) + d['SITE'], "%s.MASK[%d]" % (dsp, i), (mask >> i) & 1) segmk.add_site_tag( - d['site'], "%s.PATTERN[%d]" % (dsp, i), (pattern >> i) & 1) + d['SITE'], "%s.PATTERN[%d]" % (dsp, i), (pattern >> i) & 1) segmk.compile() segmk.write() diff --git a/fuzzers/100-dsp-mskpat/top.py b/fuzzers/100-dsp-mskpat/top.py index d536a91e..288619e1 100644 --- a/fuzzers/100-dsp-mskpat/top.py +++ b/fuzzers/100-dsp-mskpat/top.py @@ -1,71 +1,91 @@ import os import random +import csv random.seed(int(os.getenv("SEED"), 16)) from prjxray import util from prjxray.db import Database -def gen_sites(): +def gen_sites (): db = Database(util.get_db_root()) grid = db.grid() - for tile_name in sorted(grid.tiles()): - loc = grid.loc_of_tilename(tile_name) + for tile in sorted(grid.tiles()): + loc = grid.loc_of_tilename(tile) gridinfo = grid.gridinfo_at_loc(loc) if gridinfo.tile_type in ['DSP_L', 'DSP_R']: for site in sorted(gridinfo.sites.keys()): if gridinfo.sites[site] == 'DSP48E1': - yield tile_name, site + yield tile, site +def fuzz (*args): + if len(args) == 1 and isinstance(args[0], int): + # Argument indicates that we should generate a random integer with + # args[0] number of bits. + return random.getrandbits(args[0]) + else: + # Otherwise make a random choice + return random.choice(*args) -def write_params(lines): - pinstr = 'tile,site,a_input,b_input,autoreset_patdet,mask,pattern\n' - for tile, site, a_input, b_input, autoreset_patdet, mask, pattern in lines: - pinstr += '%s,' % (tile) - pinstr += '%s,' % (site) - pinstr += '%s,' % (a_input) - pinstr += '%s,' % (b_input) - pinstr += '%s,' % (autoreset_patdet) - pinstr += '%s,' % (mask) - pinstr += '%s\n' % (pattern) +def run (): + # Attributes list: + # Attribute name + # Verilog parameter value prefix + # Arguments to `fuzz` + # Verilog parameter value suffix + attributes = [] + attributes.append(('A_INPUT', '"', ('DIRECT', 'CASCADE'), '"')) + attributes.append(('B_INPUT', '"', ('DIRECT', 'CASCADE'), '"')) + attributes.append(('AUTORESET_PATDET', '"',('NO_RESET', 'RESET_MATCH', + 'RESET_NOT_MATCH'), '"')) + attributes.append(('MASK', '48\'d', (48), '')) + attributes.append(('PATTERN', '48\'d', (48), '')) - open('params.csv', 'w').write(pinstr) + # CSV headings + headings = [] + headings.append('TILE') + headings.append('SITE') + for attribute in attributes: + headings.append(attribute[0]) -def run(): - print(''' -module top(); - ''') + # CSV rows + rows = [] + rows.append(headings) - lines = [] + print('module top();') sites = list(gen_sites()) - for (tile_name, site_name) in sites: - mask = random.randint(0, 2**48 - 1) - pattern = random.randint(0, 2**48 - 1) - a_input = random.choice(('DIRECT', 'CASCADE')) - b_input = random.choice(('DIRECT', 'CASCADE')) - autoreset_patdet = random.choice( - ('NO_RESET', 'RESET_MATCH', 'RESET_NOT_MATCH')) - lines.append( - ( - tile_name, site_name, a_input, b_input, autoreset_patdet, mask, - pattern)) - print( - ''' - (* KEEP, DONT_TOUCH, LOC = "{0}" *) - DSP48E1 #( - .A_INPUT("{1}"), - .B_INPUT("{2}"), - .AUTORESET_PATDET("{3}"), - .MASK(48'h{4:x}), - .PATTERN(48'h{5:x}) - ) dsp_{0} ( - ); -'''.format(site_name, a_input, b_input, autoreset_patdet, mask, pattern)) + # For every DSP site: + # Add an instance to top.v with fuzzed attributes + # Add a row for params.csv + for (tile, site) in sites: + row = [] + row.append(tile) + row.append(site) + print('\t(* KEEP, DONT_TOUCH, LOC = "{0}" *)'.format(site)) + print('\tDSP48E1 #(') + + for attr in attributes[:-1]: + val = fuzz(attr[2]) + row.append(val) + print('\t\t.{0}({1}{2}{3}),'.format(attr[0], attr[1], val, attr[3])) + + attr = attributes[-1] + val = fuzz(attr[2]) + row.append(val) + print('\t\t.{0}({1}{2}{3})'.format(attr[0], attr[1], val, attr[3])) + + rows.append(row) + print('\t) dsp_{0} ();\n'.format(site)) print("endmodule") - write_params(lines) + + # Generate params.csv + with open('params.csv', 'w') as writeFile: + writer = csv.writer(writeFile) + writer.writerows(rows) + writeFile.close() if __name__ == '__main__': From 596bb27e3b6d4142e3f7bb45153103ca5bb4f77c Mon Sep 17 00:00:00 2001 From: Jake Mercer Date: Sun, 13 Oct 2019 00:59:28 +0100 Subject: [PATCH 06/10] FUZZER - DSP - Add All Attributes Added the rest of the DSP attributes; there are still some issues with mapping the bits. AREG/BREG mode 2 will require inputs to be connected. Signed-off-by: Jake Mercer --- fuzzers/100-dsp-mskpat/generate.py | 107 +++++++++++++++++++++++++++++ fuzzers/100-dsp-mskpat/top.py | 94 +++++++++++++++++++++++-- 2 files changed, 195 insertions(+), 6 deletions(-) diff --git a/fuzzers/100-dsp-mskpat/generate.py b/fuzzers/100-dsp-mskpat/generate.py index 5bf19e82..63ddb7fb 100644 --- a/fuzzers/100-dsp-mskpat/generate.py +++ b/fuzzers/100-dsp-mskpat/generate.py @@ -10,6 +10,58 @@ with open('params.csv', 'r') as f: for d in csv.DictReader(f): dsp = "DSP_0" if d['SITE'][-1] in "02468" else "DSP_1" + acascreg = int(d['ACASCREG']) + segmk.add_site_tag( + d['SITE'], "%s.ZACASCREG[0]" % (dsp), ~(acascreg >> 0) & 1) + segmk.add_site_tag( + d['SITE'], "%s.ZACASCREG[1]" % (dsp), ~(acascreg >> 1) & 1) + + adreg = int(d['ADREG']) + segmk.add_site_tag(d['SITE'], "%s.ADREG[0]" % (dsp), adreg & 1) + + alumodereg = int(d['ALUMODEREG']) + segmk.add_site_tag( + d['SITE'], "%s.ZALUMODEREG[0]" % (dsp), ~alumodereg & 1) + + areg = int(d['AREG']) + segmk.add_site_tag(d['SITE'], "%s.ZAREG[0]" % (dsp), ~(areg >> 0) & 1) + segmk.add_site_tag(d['SITE'], "%s.ZAREG[1]" % (dsp), ~(areg >> 1) & 1) + + bcascreg = int(d['BCASCREG']) + segmk.add_site_tag( + d['SITE'], "%s.ZBCASCREG[0]" % (dsp), ~(bcascreg >> 0) & 1) + segmk.add_site_tag( + d['SITE'], "%s.ZBCASCREG[1]" % (dsp), ~(bcascreg >> 1) & 1) + + breg = int(d['BREG']) + segmk.add_site_tag(d['SITE'], "%s.ZBREG[0]" % (dsp), ~(breg >> 0) & 1) + segmk.add_site_tag(d['SITE'], "%s.ZBREG[1]" % (dsp), ~(breg >> 1) & 1) + + carryinreg = int(d['CARRYINREG']) + segmk.add_site_tag(d['SITE'], "%s.ZCARRYINREG[0]" % (dsp), ~carryinreg) + + carryinselreg = int(d['CARRYINSELREG']) + segmk.add_site_tag( + d['SITE'], "%s.ZCARRYINSELREG[0]" % (dsp), ~carryinselreg) + + creg = int(d['CREG']) + segmk.add_site_tag(d['SITE'], "%s.ZCREG[0]" % (dsp), ~creg) + + dreg = int(d['DREG']) + segmk.add_site_tag(d['SITE'], "%s.DREG[0]" % (dsp), dreg) + + inmodereg = int(d['INMODEREG']) + segmk.add_site_tag(d['SITE'], "%s.ZINMODEREG[0]" % (dsp), ~inmodereg) + + mreg = int(d['MREG']) + segmk.add_site_tag(d['SITE'], "%s.ZMREG[0]" % (dsp), ~mreg) + + opmodereg = int(d['OPMODEREG']) + segmk.add_site_tag(d['SITE'], "%s.ZOPMODEREG[0]" % (dsp), ~opmodereg) + + preg = int(d['PREG']) + segmk.add_site_tag(d['SITE'], "%s.ZPREG[0]" % (dsp), ~preg) + a_input = str(d['A_INPUT']) segmk.add_site_tag( d['SITE'], "%s.ZA_INPUT[0]" % (dsp), @@ -20,6 +72,33 @@ with open('params.csv', 'r') as f: d['SITE'], "%s.ZB_INPUT[0]" % (dsp), (0 if b_input == "DIRECT" else 1)) + use_dport = str(d['USE_DPORT']) + segmk.add_site_tag( + d['SITE'], "%s.USE_DPORT[0]" % (dsp), + (0 if use_dport == "FALSE" else 1)) + + use_mult = str(d['USE_MULT']) + if use_mult == "NONE": + segmk.add_site_tag(d['SITE'], "%s.USE_MULT[0]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.ZUSE_MULT[1]" % (dsp), ~0) + elif use_mult == "MULTIPLY": + segmk.add_site_tag(d['SITE'], "%s.USE_MULT[0]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.ZUSE_MULT[1]" % (dsp), ~1) + elif use_mult == "DYNAMIC": + segmk.add_site_tag(d['SITE'], "%s.USE_MULT[0]" % (dsp), 1) + segmk.add_site_tag(d['SITE'], "%s.ZUSE_MULT[1]" % (dsp), ~1) + + use_simd = str(d['USE_SIMD']) + if use_simd == "ONE48": + segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[0]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[1]" % (dsp), 0) + elif use_simd == "TWO24": + segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[0]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[1]" % (dsp), 1) + elif use_simd == "FOUR12": + segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[0]" % (dsp), 1) + segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[1]" % (dsp), 1) + autoreset_patdet = str(d['AUTORESET_PATDET']) if autoreset_patdet == "RESET_MATCH": segmk.add_site_tag(d['SITE'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) @@ -43,5 +122,33 @@ with open('params.csv', 'r') as f: segmk.add_site_tag( d['SITE'], "%s.PATTERN[%d]" % (dsp, i), (pattern >> i) & 1) + sel_mask = str(d['SEL_MASK']) + if sel_mask == "MASK": + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[0]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[1]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[2]" % (dsp), 0) + elif sel_mask == "C": + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[0]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[1]" % (dsp), 1) + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[2]" % (dsp), 0) + elif sel_mask == "ROUNDING_MODE1": + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[0]" % (dsp), 1) + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[1]" % (dsp), 1) + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[2]" % (dsp), 0) + elif sel_mask == "ROUNDING_MODE2": + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[0]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[1]" % (dsp), 0) + segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[2]" % (dsp), 1) + + sel_pattern = str(d['SEL_PATTERN']) + segmk.add_site_tag( + d['SITE'], "%s.ZSEL_PATTERN[0]" % (dsp), + (0 if sel_pattern == "PATTERN" else 1)) + + use_pattern_detect = str(d['USE_PATTERN_DETECT']) + segmk.add_site_tag( + d['SITE'], "%s.USE_PATTERN_DETECT[0]" % (dsp), + (0 if use_pattern_detect == "PATDET" else 1)) + segmk.compile() segmk.write() diff --git a/fuzzers/100-dsp-mskpat/top.py b/fuzzers/100-dsp-mskpat/top.py index 288619e1..01c4e42c 100644 --- a/fuzzers/100-dsp-mskpat/top.py +++ b/fuzzers/100-dsp-mskpat/top.py @@ -6,7 +6,7 @@ from prjxray import util from prjxray.db import Database -def gen_sites (): +def gen_sites(): db = Database(util.get_db_root()) grid = db.grid() for tile in sorted(grid.tiles()): @@ -17,7 +17,8 @@ def gen_sites (): if gridinfo.sites[site] == 'DSP48E1': yield tile, site -def fuzz (*args): + +def fuzz(*args): if len(args) == 1 and isinstance(args[0], int): # Argument indicates that we should generate a random integer with # args[0] number of bits. @@ -26,19 +27,44 @@ def fuzz (*args): # Otherwise make a random choice return random.choice(*args) -def run (): + +def run(): # Attributes list: # Attribute name # Verilog parameter value prefix # Arguments to `fuzz` # Verilog parameter value suffix attributes = [] + attributes.append(('ADREG', '', (0, 1), '')) + attributes.append(('ALUMODEREG', '', (0, 1), '')) + # AREG/BREG requires inputs to be connected when configured with a value of + # 2, contstraining to 0 and 1 for now. + attributes.append(('AREG', '', (0, 1), '')) + attributes.append(('BREG', '', (0, 1), '')) + attributes.append(('CARRYINREG', '', (0, 1), '')) + attributes.append(('CARRYINSELREG', '', (0, 1), '')) + attributes.append(('CREG', '', (0, 1), '')) + attributes.append(('DREG', '', (0, 1), '')) + attributes.append(('INMODEREG', '', (0, 1), '')) + attributes.append(('OPMODEREG', '', (0, 1), '')) + attributes.append(('PREG', '', (0, 1), '')) attributes.append(('A_INPUT', '"', ('DIRECT', 'CASCADE'), '"')) attributes.append(('B_INPUT', '"', ('DIRECT', 'CASCADE'), '"')) - attributes.append(('AUTORESET_PATDET', '"',('NO_RESET', 'RESET_MATCH', - 'RESET_NOT_MATCH'), '"')) + attributes.append(('USE_DPORT', '"', ('TRUE', 'FALSE'), '"')) + attributes.append(('USE_SIMD', '"', ('ONE48', 'TWO24', 'FOUR12'), '"')) + attributes.append( + ( + 'AUTORESET_PATDET', '"', + ('NO_RESET', 'RESET_MATCH', 'RESET_NOT_MATCH'), '"')) attributes.append(('MASK', '48\'d', (48), '')) attributes.append(('PATTERN', '48\'d', (48), '')) + attributes.append( + ( + 'SEL_MASK', '"', ('MASK', 'C', 'ROUNDING_MODE1', 'ROUNDING_MODE2'), + '"')) + attributes.append(('SEL_PATTERN', '"', ('PATTERN', 'C'), '"')) + attributes.append( + ('USE_PATTERN_DETECT', '"', ('NO_PATDET', 'PATDET'), '"')) # CSV headings headings = [] @@ -48,6 +74,20 @@ def run (): for attribute in attributes: headings.append(attribute[0]) + # ACASCREG dependent on AREG + if attribute[0] == 'AREG': + headings.append('ACASCREG') + + # BCASCREG dependent on BREG + if attribute[0] == 'BREG': + headings.append('BCASCREG') + + # USE_MULT dependent on USE_SIMD + if attribute[0] == 'USE_SIMD': + headings.append('USE_MULT') + # MREG dependent on USE_MULT + headings.append('MREG') + # CSV rows rows = [] rows.append(headings) @@ -69,7 +109,49 @@ def run (): for attr in attributes[:-1]: val = fuzz(attr[2]) row.append(val) - print('\t\t.{0}({1}{2}{3}),'.format(attr[0], attr[1], val, attr[3])) + print( + '\t\t.{0}({1}{2}{3}),'.format(attr[0], attr[1], val, attr[3])) + + # ACASCREG dependent on AREG + if attr[0] == 'AREG': + if val == 0 or val == 1: + print('\t\t.ACASCREG({0}),'.format(val)) + elif val == 2: + val = fuzz((1, 2)) + print('\t\t.ACASCREG({0}),'.format(val)) + + row.append(val) + + # BCASCREG dependent on BREG + elif attr[0] == 'BREG': + if val == 0 or val == 1: + print('\t\t.BCASCREG({0}),'.format(val)) + elif val == 2: + val = fuzz((1, 2)) + print('\t\t.BCASCREG({0}),'.format(val)) + + row.append(val) + + # USE_MULT dependent on USE_SIMD + elif attr[0] == 'USE_SIMD': + if val != "ONE48": + val = 'NONE' + print('\t\t.USE_MULT("{0}"),'.format(val)) + else: + val = fuzz(('NONE', 'MULTIPLY', 'DYNAMIC')) + print('\t\t.USE_MULT("{0}"),'.format(val)) + + row.append(val) + + # MREG dependent on USE_MULT + if val == 'NONE': + val = 0 + print('\t\t.MREG("{0}"),'.format(val)) + else: + val = fuzz((0, 1)) + print('\t\t.MREG("{0}"),'.format(val)) + + row.append(val) attr = attributes[-1] val = fuzz(attr[2]) From e0fb0c0cb11e2e8c2c9c0bd6ebab8d1e70e3cddb Mon Sep 17 00:00:00 2001 From: Jake Mercer Date: Sun, 27 Oct 2019 12:19:23 +0000 Subject: [PATCH 07/10] FUZZER - DSP - Refactor Refactor the DSP Python scripts to be easier to manage. Use JSON instead of CSV. Signed-off-by: Jake Mercer --- fuzzers/100-dsp-mskpat/generate.py | 213 ++++++++++++----------------- fuzzers/100-dsp-mskpat/top.py | 177 +++++++----------------- prjxray/verilog.py | 30 ++++ 3 files changed, 171 insertions(+), 249 deletions(-) diff --git a/fuzzers/100-dsp-mskpat/generate.py b/fuzzers/100-dsp-mskpat/generate.py index 63ddb7fb..6f879a88 100644 --- a/fuzzers/100-dsp-mskpat/generate.py +++ b/fuzzers/100-dsp-mskpat/generate.py @@ -1,154 +1,123 @@ #!/usr/bin/env python3 from prjxray.segmaker import Segmaker -import csv +from prjxray.verilog import to_int +from prjxray.verilog import quote +import json -segmk = Segmaker("design.bits", verbose=True) +def bits_in(value, width): + bits = [] + for i in range(width): + bits.append(value & 1) + value >>= 1 + return bits -print("Loading tags") -with open('params.csv', 'r') as f: - for d in csv.DictReader(f): - dsp = "DSP_0" if d['SITE'][-1] in "02468" else "DSP_1" - acascreg = int(d['ACASCREG']) - segmk.add_site_tag( - d['SITE'], "%s.ZACASCREG[0]" % (dsp), ~(acascreg >> 0) & 1) - segmk.add_site_tag( - d['SITE'], "%s.ZACASCREG[1]" % (dsp), ~(acascreg >> 1) & 1) +def add(segmk, site, dsp, tag, bit, value, invert): + tag = dsp + '.' + '%s' % ('Z' if invert else '') + tag + '[%u]' % bit + value = (~value if invert else value) + value >>= bit + return segmk.add_site_tag(site, tag, value & 1) - adreg = int(d['ADREG']) - segmk.add_site_tag(d['SITE'], "%s.ADREG[0]" % (dsp), adreg & 1) - alumodereg = int(d['ALUMODEREG']) - segmk.add_site_tag( - d['SITE'], "%s.ZALUMODEREG[0]" % (dsp), ~alumodereg & 1) +def run(): + segmk = Segmaker("design.bits", verbose=True) - areg = int(d['AREG']) - segmk.add_site_tag(d['SITE'], "%s.ZAREG[0]" % (dsp), ~(areg >> 0) & 1) - segmk.add_site_tag(d['SITE'], "%s.ZAREG[1]" % (dsp), ~(areg >> 1) & 1) + print("Loading tags") + with open('params.json', 'r') as fp: + data = json.load(fp) - bcascreg = int(d['BCASCREG']) - segmk.add_site_tag( - d['SITE'], "%s.ZBCASCREG[0]" % (dsp), ~(bcascreg >> 0) & 1) - segmk.add_site_tag( - d['SITE'], "%s.ZBCASCREG[1]" % (dsp), ~(bcascreg >> 1) & 1) + for params in data['instances']: + dsp = "DSP_0" if params['SITE'][-1] in "02468" else "DSP_1" + site = params['SITE'] - breg = int(d['BREG']) - segmk.add_site_tag(d['SITE'], "%s.ZBREG[0]" % (dsp), ~(breg >> 0) & 1) - segmk.add_site_tag(d['SITE'], "%s.ZBREG[1]" % (dsp), ~(breg >> 1) & 1) + add(segmk, site, dsp, 'ADREG', 0, to_int(params['ADREG']), 0) + add(segmk, site, dsp, 'ALUMODEREG', 0, to_int(params['ALUMODEREG']), 1) - carryinreg = int(d['CARRYINREG']) - segmk.add_site_tag(d['SITE'], "%s.ZCARRYINREG[0]" % (dsp), ~carryinreg) + for i in range(2): + add(segmk, site, dsp, 'AREG', i, to_int(params['AREG']), 1) - carryinselreg = int(d['CARRYINSELREG']) - segmk.add_site_tag( - d['SITE'], "%s.ZCARRYINSELREG[0]" % (dsp), ~carryinselreg) + for i in range(2): + add(segmk, site, dsp, 'ACASCREG', i, to_int(params['ACASCREG']), 1) - creg = int(d['CREG']) - segmk.add_site_tag(d['SITE'], "%s.ZCREG[0]" % (dsp), ~creg) + for i in range(2): + add(segmk, site, dsp, 'BREG', i, to_int(params['BREG']), 1) - dreg = int(d['DREG']) - segmk.add_site_tag(d['SITE'], "%s.DREG[0]" % (dsp), dreg) + for i in range(2): + add(segmk, site, dsp, 'BCASCREG', i, to_int(params['BCASCREG']), 1) - inmodereg = int(d['INMODEREG']) - segmk.add_site_tag(d['SITE'], "%s.ZINMODEREG[0]" % (dsp), ~inmodereg) + add(segmk, site, dsp, 'CARRYINREG', 0, to_int(params['CARRYINREG']), 1) + add(segmk, site, dsp, 'CARRYINSELREG', 0, to_int(params['CARRYINSELREG']), 1) + add(segmk, site, dsp, 'CREG', 0, to_int(params['CREG']), 1) - mreg = int(d['MREG']) - segmk.add_site_tag(d['SITE'], "%s.ZMREG[0]" % (dsp), ~mreg) + add(segmk, site, dsp, 'DREG', 0, to_int(params['DREG']), 0) + add(segmk, site, dsp, 'INMODEREG', 0, to_int(params['INMODEREG']), 1) + add(segmk, site, dsp, 'OPMODEREG', 0, to_int(params['OPMODEREG']), 1) + add(segmk, site, dsp, 'PREG', 0, to_int(params['PREG']), 1) - opmodereg = int(d['OPMODEREG']) - segmk.add_site_tag(d['SITE'], "%s.ZOPMODEREG[0]" % (dsp), ~opmodereg) + INPUT = {} + INPUT[quote('DIRECT')] = 0 + INPUT[quote('CASCADE')] = 1 - preg = int(d['PREG']) - segmk.add_site_tag(d['SITE'], "%s.ZPREG[0]" % (dsp), ~preg) + add(segmk, site, dsp, 'A_INPUT', 0, INPUT[params['A_INPUT']], 0) + add(segmk, site, dsp, 'B_INPUT', 0, INPUT[params['B_INPUT']], 0) - a_input = str(d['A_INPUT']) - segmk.add_site_tag( - d['SITE'], "%s.ZA_INPUT[0]" % (dsp), - (0 if a_input == "DIRECT" else 1)) + BOOL = {} + BOOL[quote('FALSE')] = 0 + BOOL[quote('TRUE')] = 1 - b_input = str(d['B_INPUT']) - segmk.add_site_tag( - d['SITE'], "%s.ZB_INPUT[0]" % (dsp), - (0 if b_input == "DIRECT" else 1)) + add(segmk, site, dsp, 'USE_DPORT', 0, BOOL[params['USE_DPORT']], 0) - use_dport = str(d['USE_DPORT']) - segmk.add_site_tag( - d['SITE'], "%s.USE_DPORT[0]" % (dsp), - (0 if use_dport == "FALSE" else 1)) + SIMD = {} + SIMD[quote('ONE48')] = 0 + SIMD[quote('TWO24')] = 1 + SIMD[quote('FOUR12')] = 2 - use_mult = str(d['USE_MULT']) - if use_mult == "NONE": - segmk.add_site_tag(d['SITE'], "%s.USE_MULT[0]" % (dsp), 0) - segmk.add_site_tag(d['SITE'], "%s.ZUSE_MULT[1]" % (dsp), ~0) - elif use_mult == "MULTIPLY": - segmk.add_site_tag(d['SITE'], "%s.USE_MULT[0]" % (dsp), 0) - segmk.add_site_tag(d['SITE'], "%s.ZUSE_MULT[1]" % (dsp), ~1) - elif use_mult == "DYNAMIC": - segmk.add_site_tag(d['SITE'], "%s.USE_MULT[0]" % (dsp), 1) - segmk.add_site_tag(d['SITE'], "%s.ZUSE_MULT[1]" % (dsp), ~1) + for i in range(2): + add(segmk, site, dsp, 'USE_SIMD', i, SIMD[params['USE_SIMD']], 0) - use_simd = str(d['USE_SIMD']) - if use_simd == "ONE48": - segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[0]" % (dsp), 0) - segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[1]" % (dsp), 0) - elif use_simd == "TWO24": - segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[0]" % (dsp), 0) - segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[1]" % (dsp), 1) - elif use_simd == "FOUR12": - segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[0]" % (dsp), 1) - segmk.add_site_tag(d['SITE'], "%s.USE_SIMD[1]" % (dsp), 1) + MULT = {} + MULT[quote('NONE')] = 0 + MULT[quote('MULTIPLY')] = 1 + MULT[quote('DYNAMIC')] = 2 - autoreset_patdet = str(d['AUTORESET_PATDET']) - if autoreset_patdet == "RESET_MATCH": - segmk.add_site_tag(d['SITE'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) - segmk.add_site_tag( - d['SITE'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 1) - elif autoreset_patdet == "NO_RESET": - segmk.add_site_tag(d['SITE'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 0) - segmk.add_site_tag( - d['SITE'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 0) - elif autoreset_patdet == "RESET_NOT_MATCH": - segmk.add_site_tag(d['SITE'], "%s.AUTO_RESET_PATDET[0]" % (dsp), 1) - segmk.add_site_tag( - d['SITE'], "%s.ZAUTO_RESET_PATDET[1]" % (dsp), 1) + for i in range(2): + add(segmk, site, dsp, 'USE_MULT', i, MULT[params['USE_MULT']], 0) - mask = int(d['MASK']) - pattern = int(d['PATTERN']) + add(segmk, site, dsp, 'MREG', 0, to_int(params['MREG']), 1) + + AUTORESET = {} + AUTORESET[quote('NO_RESET')] = 0 + AUTORESET[quote('RESET_NOT_MATCH')] = 1 + AUTORESET[quote('RESET_MATCH')] = 2 + + add(segmk, site, dsp, 'AUTORESET_PATDET', 0, AUTORESET[params['AUTORESET_PATDET']], 0) + add(segmk, site, dsp, 'AUTORESET_PATDET', 1, AUTORESET[params['AUTORESET_PATDET']], 1) for i in range(48): - segmk.add_site_tag( - d['SITE'], "%s.MASK[%d]" % (dsp, i), (mask >> i) & 1) - segmk.add_site_tag( - d['SITE'], "%s.PATTERN[%d]" % (dsp, i), (pattern >> i) & 1) + add(segmk, site, dsp, 'MASK', i, to_int(params['MASK']), 0) - sel_mask = str(d['SEL_MASK']) - if sel_mask == "MASK": - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[0]" % (dsp), 0) - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[1]" % (dsp), 0) - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[2]" % (dsp), 0) - elif sel_mask == "C": - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[0]" % (dsp), 0) - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[1]" % (dsp), 1) - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[2]" % (dsp), 0) - elif sel_mask == "ROUNDING_MODE1": - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[0]" % (dsp), 1) - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[1]" % (dsp), 1) - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[2]" % (dsp), 0) - elif sel_mask == "ROUNDING_MODE2": - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[0]" % (dsp), 0) - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[1]" % (dsp), 0) - segmk.add_site_tag(d['SITE'], "%s.SEL_MASK[2]" % (dsp), 1) + for i in range(48): + add(segmk, site, dsp, 'PATTERN', i, to_int(params['PATTERN']), 0) - sel_pattern = str(d['SEL_PATTERN']) - segmk.add_site_tag( - d['SITE'], "%s.ZSEL_PATTERN[0]" % (dsp), - (0 if sel_pattern == "PATTERN" else 1)) + SEL_MASK = {} + SEL_MASK[quote('MASK')] = 0 + SEL_MASK[quote('C')] = 1 + SEL_MASK[quote('ROUNDING_MODE1')] = 2 + SEL_MASK[quote('ROUNDING_MODE2')] = 3 - use_pattern_detect = str(d['USE_PATTERN_DETECT']) - segmk.add_site_tag( - d['SITE'], "%s.USE_PATTERN_DETECT[0]" % (dsp), - (0 if use_pattern_detect == "PATDET" else 1)) + for i in range(2): + add(segmk, site, dsp, 'SEL_MASK', i, SEL_MASK[params['SEL_MASK']], 0) -segmk.compile() -segmk.write() + USE_PATTERN_DETECT = {} + USE_PATTERN_DETECT[quote('NO_PATDET')] = 0 + USE_PATTERN_DETECT[quote('PATDET')] = 1 + + add(segmk, site, dsp, 'USE_PATTERN_DETECT', 0, USE_PATTERN_DETECT[params['USE_PATTERN_DETECT']], 0) + + segmk.compile() + segmk.write() + + +if __name__ == '__main__': + run() diff --git a/fuzzers/100-dsp-mskpat/top.py b/fuzzers/100-dsp-mskpat/top.py index 01c4e42c..66a119ba 100644 --- a/fuzzers/100-dsp-mskpat/top.py +++ b/fuzzers/100-dsp-mskpat/top.py @@ -1,8 +1,9 @@ import os import random -import csv +import json random.seed(int(os.getenv("SEED"), 16)) from prjxray import util +from prjxray import verilog from prjxray.db import Database @@ -29,146 +30,68 @@ def fuzz(*args): def run(): - # Attributes list: - # Attribute name - # Verilog parameter value prefix - # Arguments to `fuzz` - # Verilog parameter value suffix - attributes = [] - attributes.append(('ADREG', '', (0, 1), '')) - attributes.append(('ALUMODEREG', '', (0, 1), '')) - # AREG/BREG requires inputs to be connected when configured with a value of - # 2, contstraining to 0 and 1 for now. - attributes.append(('AREG', '', (0, 1), '')) - attributes.append(('BREG', '', (0, 1), '')) - attributes.append(('CARRYINREG', '', (0, 1), '')) - attributes.append(('CARRYINSELREG', '', (0, 1), '')) - attributes.append(('CREG', '', (0, 1), '')) - attributes.append(('DREG', '', (0, 1), '')) - attributes.append(('INMODEREG', '', (0, 1), '')) - attributes.append(('OPMODEREG', '', (0, 1), '')) - attributes.append(('PREG', '', (0, 1), '')) - attributes.append(('A_INPUT', '"', ('DIRECT', 'CASCADE'), '"')) - attributes.append(('B_INPUT', '"', ('DIRECT', 'CASCADE'), '"')) - attributes.append(('USE_DPORT', '"', ('TRUE', 'FALSE'), '"')) - attributes.append(('USE_SIMD', '"', ('ONE48', 'TWO24', 'FOUR12'), '"')) - attributes.append( - ( - 'AUTORESET_PATDET', '"', - ('NO_RESET', 'RESET_MATCH', 'RESET_NOT_MATCH'), '"')) - attributes.append(('MASK', '48\'d', (48), '')) - attributes.append(('PATTERN', '48\'d', (48), '')) - attributes.append( - ( - 'SEL_MASK', '"', ('MASK', 'C', 'ROUNDING_MODE1', 'ROUNDING_MODE2'), - '"')) - attributes.append(('SEL_PATTERN', '"', ('PATTERN', 'C'), '"')) - attributes.append( - ('USE_PATTERN_DETECT', '"', ('NO_PATDET', 'PATDET'), '"')) - - # CSV headings - headings = [] - headings.append('TILE') - headings.append('SITE') - - for attribute in attributes: - headings.append(attribute[0]) - - # ACASCREG dependent on AREG - if attribute[0] == 'AREG': - headings.append('ACASCREG') - - # BCASCREG dependent on BREG - if attribute[0] == 'BREG': - headings.append('BCASCREG') - - # USE_MULT dependent on USE_SIMD - if attribute[0] == 'USE_SIMD': - headings.append('USE_MULT') - # MREG dependent on USE_MULT - headings.append('MREG') - - # CSV rows - rows = [] - rows.append(headings) + data = {} + data['instances'] = [] print('module top();') sites = list(gen_sites()) - # For every DSP site: - # Add an instance to top.v with fuzzed attributes - # Add a row for params.csv for (tile, site) in sites: - row = [] - row.append(tile) - row.append(site) - print('\t(* KEEP, DONT_TOUCH, LOC = "{0}" *)'.format(site)) - print('\tDSP48E1 #(') + synthesis = '(* KEEP, DONT_TOUCH, LOC = "%s" *)' % (site) + module = 'DSP48E1' + instance = 'INST_%s' % (site) + ports = {} + params = {} - for attr in attributes[:-1]: - val = fuzz(attr[2]) - row.append(val) - print( - '\t\t.{0}({1}{2}{3}),'.format(attr[0], attr[1], val, attr[3])) + params['ADREG'] = fuzz((0, 1)) + params['ALUMODEREG'] = fuzz((0, 1)) + # AREG/BREG requires inputs to be connected when configured with a value + # of 2, constraining to 0 and 1 for now. + params['AREG'] = fuzz((0, 1)) + params['ACASCREG'] = params['AREG'] if params[ + 'AREG'] == 0 or params['AREG'] == 1 else fuzz((1, 2)) + params['BREG'] = fuzz((0, 1)) + params['BCASCREG'] = params['BREG'] if params[ + 'BREG'] == 0 or params['BREG'] == 1 else fuzz((1, 2)) + params['CARRYINREG'] = fuzz((0, 1)) + params['CARRYINSELREG'] = fuzz((0, 1)) + params['CREG'] = fuzz((0, 1)) + params['DREG'] = fuzz((0, 1)) + params['INMODEREG'] = fuzz((0, 1)) + params['OPMODEREG'] = fuzz((0, 1)) + params['PREG'] = fuzz((0, 1)) + params['A_INPUT'] = verilog.quote(fuzz(('DIRECT', 'CASCADE'))) + params['B_INPUT'] = verilog.quote(fuzz(('DIRECT', 'CASCADE'))) + params['USE_DPORT'] = verilog.quote(fuzz(('TRUE', 'FALSE'))) + params['USE_SIMD'] = verilog.quote( + fuzz(('ONE48', 'TWO24', 'FOUR12'))) + params['USE_MULT'] = verilog.quote( + 'NONE' if params['USE_SIMD'] != verilog.quote('ONE48') else + fuzz(('NONE', 'MULTIPLY', 'DYNAMIC'))) + params['MREG'] = 0 if params['USE_MULT'] == verilog.quote( + 'NONE') else fuzz((0, 1)) + params['AUTORESET_PATDET'] = verilog.quote( + fuzz(('NO_RESET', 'RESET_MATCH', 'RESET_NOT_MATCH'))) + params['MASK'] = '48\'d%s' % fuzz(48) + params['PATTERN'] = '48\'d%s' % fuzz(48) + params['SEL_MASK'] = verilog.quote( + fuzz(('MASK', 'C', 'ROUNDING_MODE1', 'ROUNDING_MODE2'))) + params['USE_PATTERN_DETECT'] = verilog.quote( + fuzz(('NO_PATDET', 'PATDET'))) - # ACASCREG dependent on AREG - if attr[0] == 'AREG': - if val == 0 or val == 1: - print('\t\t.ACASCREG({0}),'.format(val)) - elif val == 2: - val = fuzz((1, 2)) - print('\t\t.ACASCREG({0}),'.format(val)) + verilog.instance(synthesis + ' ' + module, instance, ports, params) - row.append(val) + params['TILE'] = tile + params['SITE'] = site - # BCASCREG dependent on BREG - elif attr[0] == 'BREG': - if val == 0 or val == 1: - print('\t\t.BCASCREG({0}),'.format(val)) - elif val == 2: - val = fuzz((1, 2)) - print('\t\t.BCASCREG({0}),'.format(val)) + data['instances'].append(params) - row.append(val) - - # USE_MULT dependent on USE_SIMD - elif attr[0] == 'USE_SIMD': - if val != "ONE48": - val = 'NONE' - print('\t\t.USE_MULT("{0}"),'.format(val)) - else: - val = fuzz(('NONE', 'MULTIPLY', 'DYNAMIC')) - print('\t\t.USE_MULT("{0}"),'.format(val)) - - row.append(val) - - # MREG dependent on USE_MULT - if val == 'NONE': - val = 0 - print('\t\t.MREG("{0}"),'.format(val)) - else: - val = fuzz((0, 1)) - print('\t\t.MREG("{0}"),'.format(val)) - - row.append(val) - - attr = attributes[-1] - val = fuzz(attr[2]) - row.append(val) - print('\t\t.{0}({1}{2}{3})'.format(attr[0], attr[1], val, attr[3])) - - rows.append(row) - print('\t) dsp_{0} ();\n'.format(site)) + with open('params.json', 'w') as fp: + json.dump(data, fp) print("endmodule") - # Generate params.csv - with open('params.csv', 'w') as writeFile: - writer = csv.writer(writeFile) - writer.writerows(rows) - writeFile.close() - if __name__ == '__main__': run() diff --git a/prjxray/verilog.py b/prjxray/verilog.py index 3e3af277..0ca4f6f4 100644 --- a/prjxray/verilog.py +++ b/prjxray/verilog.py @@ -1,5 +1,6 @@ import sys import random +import re def top_harness(DIN_N, DOUT_N, f=sys.stdout): @@ -64,6 +65,35 @@ def unquote(s): assert s[0] == '"' and s[-1] == '"' return s[1:-1] +def to_int(s): + value = 0 + + match = re.search(r'^(\d+)\'([sS]*)([bBoOdDhH])(.*)', str(s)) + + if match: + width = int(match.group(1)) + signed = match.group(2) + radix = match.group(3) + value = match.group(4) + + # Convert to int type + if re.match(r'[bB]', radix): + value = int(value, 2) + elif re.match(r'[oO]', radix): + value = int(value, 8) + elif re.match(r'[dD]', radix): + value = int(value, 10) + elif re.match(r'[hH]', radix): + value = int(value, 16) + else: + raise ValueError('Don\'t know how to interpret input %s' % (s)) + + # Truncate to `width` bits + value &= 2**width - 1 + else: + value = int(s) + + return value def parsei(s): if s == "1'b0": From 15cfb5bd46e4c9e17cf6b3f6fb8205914cdd4193 Mon Sep 17 00:00:00 2001 From: Jake Mercer Date: Sun, 27 Oct 2019 18:38:29 +0000 Subject: [PATCH 08/10] FUZZER - DSP - Add Ports & ROI Module Added code for ports to the DSP48E1 instances. Moved DSP instances inside an ROI module and using the verilog top harness as in other fuzzers. Signed-off-by: Jake Mercer --- fuzzers/100-dsp-mskpat/generate.py | 23 +++++--- fuzzers/100-dsp-mskpat/generate.tcl | 9 ++++ fuzzers/100-dsp-mskpat/top.py | 83 +++++++++++++++++++++++------ prjxray/verilog.py | 2 + 4 files changed, 96 insertions(+), 21 deletions(-) diff --git a/fuzzers/100-dsp-mskpat/generate.py b/fuzzers/100-dsp-mskpat/generate.py index 6f879a88..7f976dc0 100644 --- a/fuzzers/100-dsp-mskpat/generate.py +++ b/fuzzers/100-dsp-mskpat/generate.py @@ -5,6 +5,7 @@ from prjxray.verilog import to_int from prjxray.verilog import quote import json + def bits_in(value, width): bits = [] for i in range(width): @@ -14,7 +15,7 @@ def bits_in(value, width): def add(segmk, site, dsp, tag, bit, value, invert): - tag = dsp + '.' + '%s' % ('Z' if invert else '') + tag + '[%u]' % bit + tag = dsp + '.' + '%s' % ('Z' if invert else '') + tag + '[%u]' % bit value = (~value if invert else value) value >>= bit return segmk.add_site_tag(site, tag, value & 1) @@ -47,7 +48,9 @@ def run(): add(segmk, site, dsp, 'BCASCREG', i, to_int(params['BCASCREG']), 1) add(segmk, site, dsp, 'CARRYINREG', 0, to_int(params['CARRYINREG']), 1) - add(segmk, site, dsp, 'CARRYINSELREG', 0, to_int(params['CARRYINSELREG']), 1) + add( + segmk, site, dsp, 'CARRYINSELREG', 0, + to_int(params['CARRYINSELREG']), 1) add(segmk, site, dsp, 'CREG', 0, to_int(params['CREG']), 1) add(segmk, site, dsp, 'DREG', 0, to_int(params['DREG']), 0) @@ -91,8 +94,12 @@ def run(): AUTORESET[quote('RESET_NOT_MATCH')] = 1 AUTORESET[quote('RESET_MATCH')] = 2 - add(segmk, site, dsp, 'AUTORESET_PATDET', 0, AUTORESET[params['AUTORESET_PATDET']], 0) - add(segmk, site, dsp, 'AUTORESET_PATDET', 1, AUTORESET[params['AUTORESET_PATDET']], 1) + add( + segmk, site, dsp, 'AUTORESET_PATDET', 0, + AUTORESET[params['AUTORESET_PATDET']], 0) + add( + segmk, site, dsp, 'AUTORESET_PATDET', 1, + AUTORESET[params['AUTORESET_PATDET']], 1) for i in range(48): add(segmk, site, dsp, 'MASK', i, to_int(params['MASK']), 0) @@ -107,13 +114,17 @@ def run(): SEL_MASK[quote('ROUNDING_MODE2')] = 3 for i in range(2): - add(segmk, site, dsp, 'SEL_MASK', i, SEL_MASK[params['SEL_MASK']], 0) + add( + segmk, site, dsp, 'SEL_MASK', i, SEL_MASK[params['SEL_MASK']], + 0) USE_PATTERN_DETECT = {} USE_PATTERN_DETECT[quote('NO_PATDET')] = 0 USE_PATTERN_DETECT[quote('PATDET')] = 1 - add(segmk, site, dsp, 'USE_PATTERN_DETECT', 0, USE_PATTERN_DETECT[params['USE_PATTERN_DETECT']], 0) + add( + segmk, site, dsp, 'USE_PATTERN_DETECT', 0, + USE_PATTERN_DETECT[params['USE_PATTERN_DETECT']], 0) segmk.compile() segmk.write() diff --git a/fuzzers/100-dsp-mskpat/generate.tcl b/fuzzers/100-dsp-mskpat/generate.tcl index 9e8cab8a..ee2542fe 100644 --- a/fuzzers/100-dsp-mskpat/generate.tcl +++ b/fuzzers/100-dsp-mskpat/generate.tcl @@ -5,10 +5,19 @@ proc run {} { read_verilog top.v synth_design -top top + set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports clk] + set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports di] + set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports do] + set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports stb] + set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] + set_param tcl.collectionResultDisplayLimit 0 + + set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF] + place_design route_design diff --git a/fuzzers/100-dsp-mskpat/top.py b/fuzzers/100-dsp-mskpat/top.py index 66a119ba..a480ebb6 100644 --- a/fuzzers/100-dsp-mskpat/top.py +++ b/fuzzers/100-dsp-mskpat/top.py @@ -30,30 +30,84 @@ def fuzz(*args): def run(): + verilog.top_harness(48, 48) + + print('module roi(input clk, input [47:0] din, output [47:0] dout);') + data = {} data['instances'] = [] - print('module top();') - sites = list(gen_sites()) - for (tile, site) in sites: + for i, (tile, site) in enumerate(sites): synthesis = '(* KEEP, DONT_TOUCH, LOC = "%s" *)' % (site) module = 'DSP48E1' instance = 'INST_%s' % (site) ports = {} params = {} + ports['A'] = '{30{1\'b1}}' + ports['ACIN'] = '{30{1\'b1}}' + ports['ACOUT'] = '30\'b0' + ports['ALUMODE'] = '4\'b1' + ports['B'] = '{18{1\'b1}}' + ports['BCIN'] = '{18{1\'b1}}' + ports['BCOUT'] = '18\'b0' + ports['C'] = '{48{1\'b1}}' + ports['CARRYCASCIN'] = '1\'b1' + ports['CARRYCASCOUT'] = '1\'b0' + ports['CARRYIN'] = '1\'b1' + ports['CARRYINSEL'] = '3\'b000' + ports['CARRYOUT'] = '4\'b0' + ports['CEA1'] = '1\'b1' + ports['CEA2'] = '1\'b1' + ports['CEAD'] = '1\'b1' + ports['CEALUMODE'] = '1\'b1' + ports['CEB1'] = '1\'b1' + ports['CEB2'] = '1\'b1' + ports['CEC'] = '1\'b1' + ports['CECARRYIN'] = '1\'b1' + ports['CECTRL'] = '1\'b1' + ports['CED'] = '1\'b1' + ports['CEINMODE'] = '1\'b1' + ports['CEM'] = '1\'b1' + ports['CEP'] = '1\'b1' + ports['CLK'] = '1\'b1' + ports['D'] = '{25{1\'b1}}' + ports['INMODE'] = '5\'b11111' + #ports['MULTISIGNIN'] = '1\'b1' + #ports['MULTISIGNOUT'] = '1\'b0' + ports['OPMODE'] = '7\'b1111111' + ports['OVERFLOW'] = '1\'b0' + ports['P'] = '48\'b0' + ports['PATTERNBDETECT'] = '1\'b0' + ports['PATTERNDETECT'] = '1\'b0' + ports['PCIN'] = '{48{1\'b1}}' + ports['PCOUT'] = '48\'b0' + ports['RSTA'] = '1\'b1' + ports['RSTALLCARRYIN'] = '1\'b1' + ports['RSTALUMODE'] = '1\'b1' + ports['RSTB'] = '1\'b1' + ports['RSTC'] = '1\'b1' + ports['RSTCTRL'] = '1\'b1' + ports['RSTD'] = '1\'b1' + ports['RSTINMODE'] = '1\'b1' + ports['RSTM'] = '1\'b1' + ports['RSTP'] = '1\'b1' + ports['UNDERFLOW'] = '1\'b0' + params['ADREG'] = fuzz((0, 1)) params['ALUMODEREG'] = fuzz((0, 1)) - # AREG/BREG requires inputs to be connected when configured with a value - # of 2, constraining to 0 and 1 for now. - params['AREG'] = fuzz((0, 1)) - params['ACASCREG'] = params['AREG'] if params[ - 'AREG'] == 0 or params['AREG'] == 1 else fuzz((1, 2)) - params['BREG'] = fuzz((0, 1)) - params['BCASCREG'] = params['BREG'] if params[ - 'BREG'] == 0 or params['BREG'] == 1 else fuzz((1, 2)) + params['AREG'] = fuzz((0, 1, 2)) + if params['AREG'] == 0 or params['AREG'] == 1: + params['ACASCREG'] = params['AREG'] + else: + params['ACASCREG'] = fuzz((1, 2)) + params['BREG'] = fuzz((0, 1, 2)) + if params['BREG'] == 0 or params['BREG'] == 1: + params['BCASCREG'] = params['BREG'] + else: + params['BCASCREG'] = fuzz((1, 2)) params['CARRYINREG'] = fuzz((0, 1)) params['CARRYINSELREG'] = fuzz((0, 1)) params['CREG'] = fuzz((0, 1)) @@ -64,11 +118,10 @@ def run(): params['A_INPUT'] = verilog.quote(fuzz(('DIRECT', 'CASCADE'))) params['B_INPUT'] = verilog.quote(fuzz(('DIRECT', 'CASCADE'))) params['USE_DPORT'] = verilog.quote(fuzz(('TRUE', 'FALSE'))) - params['USE_SIMD'] = verilog.quote( - fuzz(('ONE48', 'TWO24', 'FOUR12'))) + params['USE_SIMD'] = verilog.quote(fuzz(('ONE48', 'TWO24', 'FOUR12'))) params['USE_MULT'] = verilog.quote( - 'NONE' if params['USE_SIMD'] != verilog.quote('ONE48') else - fuzz(('NONE', 'MULTIPLY', 'DYNAMIC'))) + 'NONE' if params['USE_SIMD'] != verilog.quote('ONE48') else fuzz( + ('NONE', 'MULTIPLY', 'DYNAMIC'))) params['MREG'] = 0 if params['USE_MULT'] == verilog.quote( 'NONE') else fuzz((0, 1)) params['AUTORESET_PATDET'] = verilog.quote( diff --git a/prjxray/verilog.py b/prjxray/verilog.py index 0ca4f6f4..de3895e9 100644 --- a/prjxray/verilog.py +++ b/prjxray/verilog.py @@ -65,6 +65,7 @@ def unquote(s): assert s[0] == '"' and s[-1] == '"' return s[1:-1] + def to_int(s): value = 0 @@ -95,6 +96,7 @@ def to_int(s): return value + def parsei(s): if s == "1'b0": return 0 From 6a3db24da1869b3f22d426b9c89aaa84c4cdbecc Mon Sep 17 00:00:00 2001 From: Jake Mercer Date: Thu, 31 Oct 2019 23:18:38 +0000 Subject: [PATCH 09/10] FUZZER - DSP - Fixes Following Review Signed-off-by: Jake Mercer --- fuzzers/100-dsp-mskpat/generate.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/fuzzers/100-dsp-mskpat/generate.py b/fuzzers/100-dsp-mskpat/generate.py index 7f976dc0..fe0d3271 100644 --- a/fuzzers/100-dsp-mskpat/generate.py +++ b/fuzzers/100-dsp-mskpat/generate.py @@ -6,16 +6,8 @@ from prjxray.verilog import quote import json -def bits_in(value, width): - bits = [] - for i in range(width): - bits.append(value & 1) - value >>= 1 - return bits - - def add(segmk, site, dsp, tag, bit, value, invert): - tag = dsp + '.' + '%s' % ('Z' if invert else '') + tag + '[%u]' % bit + tag = "%s.%s%s[%u]" % (dsp, ('Z' if invert else ''), tag, bit) value = (~value if invert else value) value >>= bit return segmk.add_site_tag(site, tag, value & 1) From 0a79eb67531b964a3e6a231b4ceb511b891979a8 Mon Sep 17 00:00:00 2001 From: Jake Mercer Date: Sat, 2 Nov 2019 11:45:43 +0000 Subject: [PATCH 10/10] FORMAT - Whitespace Fixes CI is failing due to this. Signed-off-by: Jake Mercer --- minitests/litex_litedram/src.vivado/verilog/VexRiscv.v | 8 ++++---- minitests/litex_litedram/src.yosys/verilog/VexRiscv.v | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/minitests/litex_litedram/src.vivado/verilog/VexRiscv.v b/minitests/litex_litedram/src.vivado/verilog/VexRiscv.v index c1891ed2..10fc8f52 100644 --- a/minitests/litex_litedram/src.vivado/verilog/VexRiscv.v +++ b/minitests/litex_litedram/src.vivado/verilog/VexRiscv.v @@ -2523,7 +2523,7 @@ module VexRiscv ( end end - InstructionCache IBusCachedPlugin_cache ( + InstructionCache IBusCachedPlugin_cache ( .io_flush(_zz_221_), .io_cpu_prefetch_isValid(_zz_222_), .io_cpu_prefetch_haltIt(IBusCachedPlugin_cache_io_cpu_prefetch_haltIt), @@ -2569,9 +2569,9 @@ module VexRiscv ( .io_mem_rsp_payload_data(iBus_rsp_payload_data), .io_mem_rsp_payload_error(iBus_rsp_payload_error), .clk(clk), - .reset(reset) + .reset(reset) ); - DataCache dataCache_1_ ( + DataCache dataCache_1_ ( .io_cpu_execute_isValid(_zz_230_), .io_cpu_execute_address(_zz_231_), .io_cpu_execute_args_wr(execute_MEMORY_WR), @@ -2619,7 +2619,7 @@ module VexRiscv ( .io_mem_rsp_payload_data(dBus_rsp_payload_data), .io_mem_rsp_payload_error(dBus_rsp_payload_error), .clk(clk), - .reset(reset) + .reset(reset) ); always @(*) begin case(_zz_371_) diff --git a/minitests/litex_litedram/src.yosys/verilog/VexRiscv.v b/minitests/litex_litedram/src.yosys/verilog/VexRiscv.v index c1891ed2..10fc8f52 100644 --- a/minitests/litex_litedram/src.yosys/verilog/VexRiscv.v +++ b/minitests/litex_litedram/src.yosys/verilog/VexRiscv.v @@ -2523,7 +2523,7 @@ module VexRiscv ( end end - InstructionCache IBusCachedPlugin_cache ( + InstructionCache IBusCachedPlugin_cache ( .io_flush(_zz_221_), .io_cpu_prefetch_isValid(_zz_222_), .io_cpu_prefetch_haltIt(IBusCachedPlugin_cache_io_cpu_prefetch_haltIt), @@ -2569,9 +2569,9 @@ module VexRiscv ( .io_mem_rsp_payload_data(iBus_rsp_payload_data), .io_mem_rsp_payload_error(iBus_rsp_payload_error), .clk(clk), - .reset(reset) + .reset(reset) ); - DataCache dataCache_1_ ( + DataCache dataCache_1_ ( .io_cpu_execute_isValid(_zz_230_), .io_cpu_execute_address(_zz_231_), .io_cpu_execute_args_wr(execute_MEMORY_WR), @@ -2619,7 +2619,7 @@ module VexRiscv ( .io_mem_rsp_payload_data(dBus_rsp_payload_data), .io_mem_rsp_payload_error(dBus_rsp_payload_error), .clk(clk), - .reset(reset) + .reset(reset) ); always @(*) begin case(_zz_371_)