mirror of https://github.com/openXC7/prjxray.git
Merge pull request #1080 from JakeMercer/dsp
DSP - Add Attribute Fuzzing
This commit is contained in:
commit
4cec0817ab
|
|
@ -8,3 +8,4 @@ database
|
||||||
run.ok
|
run.ok
|
||||||
__pycache__
|
__pycache__
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,126 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from prjxray.segmaker import Segmaker
|
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)
|
|
||||||
|
|
||||||
print("Loading tags")
|
def add(segmk, site, dsp, tag, bit, value, invert):
|
||||||
with open('params.csv', 'r') as f:
|
tag = "%s.%s%s[%u]" % (dsp, ('Z' if invert else ''), tag, bit)
|
||||||
for d in csv.DictReader(f):
|
value = (~value if invert else value)
|
||||||
dsp = "DSP_0" if d['site'][-1] in "02468" else "DSP_1"
|
value >>= bit
|
||||||
|
return segmk.add_site_tag(site, tag, value & 1)
|
||||||
|
|
||||||
mask = int(d['mask'])
|
|
||||||
pattern = int(d['pattern'])
|
def run():
|
||||||
|
segmk = Segmaker("design.bits", verbose=True)
|
||||||
|
|
||||||
|
print("Loading tags")
|
||||||
|
with open('params.json', 'r') as fp:
|
||||||
|
data = json.load(fp)
|
||||||
|
|
||||||
|
for params in data['instances']:
|
||||||
|
dsp = "DSP_0" if params['SITE'][-1] in "02468" else "DSP_1"
|
||||||
|
site = params['SITE']
|
||||||
|
|
||||||
|
add(segmk, site, dsp, 'ADREG', 0, to_int(params['ADREG']), 0)
|
||||||
|
add(segmk, site, dsp, 'ALUMODEREG', 0, to_int(params['ALUMODEREG']), 1)
|
||||||
|
|
||||||
|
for i in range(2):
|
||||||
|
add(segmk, site, dsp, 'AREG', i, to_int(params['AREG']), 1)
|
||||||
|
|
||||||
|
for i in range(2):
|
||||||
|
add(segmk, site, dsp, 'ACASCREG', i, to_int(params['ACASCREG']), 1)
|
||||||
|
|
||||||
|
for i in range(2):
|
||||||
|
add(segmk, site, dsp, 'BREG', i, to_int(params['BREG']), 1)
|
||||||
|
|
||||||
|
for i in range(2):
|
||||||
|
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, 'CREG', 0, to_int(params['CREG']), 1)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
INPUT = {}
|
||||||
|
INPUT[quote('DIRECT')] = 0
|
||||||
|
INPUT[quote('CASCADE')] = 1
|
||||||
|
|
||||||
|
add(segmk, site, dsp, 'A_INPUT', 0, INPUT[params['A_INPUT']], 0)
|
||||||
|
add(segmk, site, dsp, 'B_INPUT', 0, INPUT[params['B_INPUT']], 0)
|
||||||
|
|
||||||
|
BOOL = {}
|
||||||
|
BOOL[quote('FALSE')] = 0
|
||||||
|
BOOL[quote('TRUE')] = 1
|
||||||
|
|
||||||
|
add(segmk, site, dsp, 'USE_DPORT', 0, BOOL[params['USE_DPORT']], 0)
|
||||||
|
|
||||||
|
SIMD = {}
|
||||||
|
SIMD[quote('ONE48')] = 0
|
||||||
|
SIMD[quote('TWO24')] = 1
|
||||||
|
SIMD[quote('FOUR12')] = 2
|
||||||
|
|
||||||
|
for i in range(2):
|
||||||
|
add(segmk, site, dsp, 'USE_SIMD', i, SIMD[params['USE_SIMD']], 0)
|
||||||
|
|
||||||
|
MULT = {}
|
||||||
|
MULT[quote('NONE')] = 0
|
||||||
|
MULT[quote('MULTIPLY')] = 1
|
||||||
|
MULT[quote('DYNAMIC')] = 2
|
||||||
|
|
||||||
|
for i in range(2):
|
||||||
|
add(segmk, site, dsp, 'USE_MULT', i, MULT[params['USE_MULT']], 0)
|
||||||
|
|
||||||
|
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):
|
for i in range(48):
|
||||||
segmk.add_site_tag(
|
add(segmk, site, dsp, 'MASK', i, to_int(params['MASK']), 0)
|
||||||
d['site'], "%s.MASK[%d]" % (dsp, i), (mask >> i) & 1)
|
|
||||||
segmk.add_site_tag(
|
|
||||||
d['site'], "%s.PATTERN[%d]" % (dsp, i), (pattern >> i) & 1)
|
|
||||||
|
|
||||||
segmk.compile()
|
for i in range(48):
|
||||||
segmk.write()
|
add(segmk, site, dsp, 'PATTERN', i, to_int(params['PATTERN']), 0)
|
||||||
|
|
||||||
|
SEL_MASK = {}
|
||||||
|
SEL_MASK[quote('MASK')] = 0
|
||||||
|
SEL_MASK[quote('C')] = 1
|
||||||
|
SEL_MASK[quote('ROUNDING_MODE1')] = 2
|
||||||
|
SEL_MASK[quote('ROUNDING_MODE2')] = 3
|
||||||
|
|
||||||
|
for i in range(2):
|
||||||
|
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)
|
||||||
|
|
||||||
|
segmk.compile()
|
||||||
|
segmk.write()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,19 @@ proc run {} {
|
||||||
read_verilog top.v
|
read_verilog top.v
|
||||||
synth_design -top top
|
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 CFGBVS VCCO [current_design]
|
||||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||||
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [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
|
place_design
|
||||||
route_design
|
route_design
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,55 +1,149 @@
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
import json
|
||||||
random.seed(int(os.getenv("SEED"), 16))
|
random.seed(int(os.getenv("SEED"), 16))
|
||||||
from prjxray import util
|
from prjxray import util
|
||||||
|
from prjxray import verilog
|
||||||
from prjxray.db import Database
|
from prjxray.db import Database
|
||||||
|
|
||||||
|
|
||||||
def gen_sites():
|
def gen_sites():
|
||||||
db = Database(util.get_db_root())
|
db = Database(util.get_db_root())
|
||||||
grid = db.grid()
|
grid = db.grid()
|
||||||
for tile_name in sorted(grid.tiles()):
|
for tile in sorted(grid.tiles()):
|
||||||
loc = grid.loc_of_tilename(tile_name)
|
loc = grid.loc_of_tilename(tile)
|
||||||
gridinfo = grid.gridinfo_at_loc(loc)
|
gridinfo = grid.gridinfo_at_loc(loc)
|
||||||
if gridinfo.tile_type in ['DSP_L', 'DSP_R']:
|
if gridinfo.tile_type in ['DSP_L', 'DSP_R']:
|
||||||
for site in sorted(gridinfo.sites.keys()):
|
for site in sorted(gridinfo.sites.keys()):
|
||||||
if gridinfo.sites[site] == 'DSP48E1':
|
if gridinfo.sites[site] == 'DSP48E1':
|
||||||
yield tile_name, site
|
yield tile, site
|
||||||
|
|
||||||
|
|
||||||
def write_params(lines):
|
def fuzz(*args):
|
||||||
pinstr = 'tile,site,mask,pattern\n'
|
if len(args) == 1 and isinstance(args[0], int):
|
||||||
for tile, site, mask, pattern in lines:
|
# Argument indicates that we should generate a random integer with
|
||||||
pinstr += '%s,%s,%s,%s\n' % (tile, site, mask, pattern)
|
# args[0] number of bits.
|
||||||
|
return random.getrandbits(args[0])
|
||||||
open('params.csv', 'w').write(pinstr)
|
else:
|
||||||
|
# Otherwise make a random choice
|
||||||
|
return random.choice(*args)
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
print('''
|
verilog.top_harness(48, 48)
|
||||||
module top();
|
|
||||||
''')
|
|
||||||
|
|
||||||
lines = []
|
print('module roi(input clk, input [47:0] din, output [47:0] dout);')
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
data['instances'] = []
|
||||||
|
|
||||||
sites = list(gen_sites())
|
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)
|
|
||||||
lines.append((tile_name, site_name, mask, pattern))
|
|
||||||
|
|
||||||
print(
|
for i, (tile, site) in enumerate(sites):
|
||||||
'''
|
synthesis = '(* KEEP, DONT_TOUCH, LOC = "%s" *)' % (site)
|
||||||
(* KEEP, DONT_TOUCH, LOC = "{0}" *)
|
module = 'DSP48E1'
|
||||||
DSP48E1 #(
|
instance = 'INST_%s' % (site)
|
||||||
.MASK(48'h{1:x}),
|
ports = {}
|
||||||
.PATTERN(48'h{2:x})
|
params = {}
|
||||||
) dsp_{0} (
|
|
||||||
);
|
ports['A'] = '{30{1\'b1}}'
|
||||||
'''.format(site_name, mask, pattern))
|
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))
|
||||||
|
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))
|
||||||
|
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')))
|
||||||
|
|
||||||
|
verilog.instance(synthesis + ' ' + module, instance, ports, params)
|
||||||
|
|
||||||
|
params['TILE'] = tile
|
||||||
|
params['SITE'] = site
|
||||||
|
|
||||||
|
data['instances'].append(params)
|
||||||
|
|
||||||
|
with open('params.json', 'w') as fp:
|
||||||
|
json.dump(data, fp)
|
||||||
|
|
||||||
print("endmodule")
|
print("endmodule")
|
||||||
write_params(lines)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import sys
|
import sys
|
||||||
import random
|
import random
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
def top_harness(DIN_N, DOUT_N, f=sys.stdout):
|
def top_harness(DIN_N, DOUT_N, f=sys.stdout):
|
||||||
|
|
@ -65,6 +66,37 @@ def unquote(s):
|
||||||
return s[1:-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):
|
def parsei(s):
|
||||||
if s == "1'b0":
|
if s == "1'b0":
|
||||||
return 0
|
return 0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue