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
|
||||
__pycache__
|
||||
*.pyc
|
||||
*.swp
|
||||
|
|
|
|||
|
|
@ -1,23 +1,126 @@
|
|||
#!/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)
|
||||
|
||||
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"
|
||||
def add(segmk, site, dsp, tag, bit, value, invert):
|
||||
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)
|
||||
|
||||
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):
|
||||
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)
|
||||
|
||||
segmk.compile()
|
||||
segmk.write()
|
||||
for i in range(48):
|
||||
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
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,55 +1,149 @@
|
|||
import os
|
||||
import random
|
||||
import json
|
||||
random.seed(int(os.getenv("SEED"), 16))
|
||||
from prjxray import util
|
||||
from prjxray import verilog
|
||||
from prjxray.db import Database
|
||||
|
||||
|
||||
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 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)
|
||||
|
||||
open('params.csv', 'w').write(pinstr)
|
||||
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 run():
|
||||
print('''
|
||||
module top();
|
||||
''')
|
||||
verilog.top_harness(48, 48)
|
||||
|
||||
lines = []
|
||||
print('module roi(input clk, input [47:0] din, output [47:0] dout);')
|
||||
|
||||
data = {}
|
||||
data['instances'] = []
|
||||
|
||||
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(
|
||||
'''
|
||||
(* KEEP, DONT_TOUCH, LOC = "{0}" *)
|
||||
DSP48E1 #(
|
||||
.MASK(48'h{1:x}),
|
||||
.PATTERN(48'h{2:x})
|
||||
) dsp_{0} (
|
||||
);
|
||||
'''.format(site_name, mask, pattern))
|
||||
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))
|
||||
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")
|
||||
write_params(lines)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import sys
|
||||
import random
|
||||
import re
|
||||
|
||||
|
||||
def top_harness(DIN_N, DOUT_N, f=sys.stdout):
|
||||
|
|
@ -65,6 +66,37 @@ def unquote(s):
|
|||
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":
|
||||
return 0
|
||||
|
|
|
|||
Loading…
Reference in New Issue