Add initial FIFO configuration.

Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
Keith Rothman 2019-02-01 13:33:57 -08:00
parent 055ed637ed
commit 0edc3facde
7 changed files with 289 additions and 8 deletions

View File

@ -0,0 +1,22 @@
# read/write width is relatively slow to resolve
# Even slower with multi bit masks...
N ?= 20
include ../fuzzer.mk
database: build/segbits_bramx.db
build/segbits_bramx.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} -o build/segbits_bramx.rdb $(addsuffix /segdata_bram_[lr].txt,$(SPECIMENS))
build/segbits_bramx.db: build/segbits_bramx.rdb
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@
${XRAY_MASKMERGE} build/mask_bramx.db $(addsuffix /segdata_bram_[lr].txt,$(SPECIMENS))
pushdb:
${XRAY_MERGEDB} bram_l build/segbits_bramx.db
${XRAY_MERGEDB} bram_r build/segbits_bramx.db
${XRAY_MERGEDB} mask_bram_l build/mask_bramx.db
${XRAY_MERGEDB} mask_bram_r build/mask_bramx.db
.PHONY: database pushdb

View File

View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
import json
from prjxray.segmaker import Segmaker
from prjxray import verilog
def add_enum_bits(segmk, params, key, options):
for opt in options:
segmk.add_site_tag(params['site'], '{}_{}'.format(key, opt), params[key] == opt)
def output_integer_tags(segmk, params, key, invert=False):
site = params['site']
bits = verilog.parse_bitstr(params[key])
for bit, tag_val in enumerate(bits):
if not invert:
segmk.add_site_tag(site, "{}[{}]".format(key, len(bits)-bit-1), tag_val)
else:
segmk.add_site_tag(site, "Z{}[{}]".format(key, len(bits)-bit-1), 0 if tag_val else 1)
def main():
segmk = Segmaker("design.bits")
print("Loading tags")
with open('params.json') as f:
params = json.load(f)
for tile_param in params:
#add_enum_bits(segmk, tile_param, 'DATA_WIDTH', [4, 9, 18, 36])
#add_enum_bits(segmk, tile_param, 'FIFO_MODE', ['FIFO18', 'FIFO18_36'])
if tile_param['EN_SYN'] and tile_param['DATA_WIDTH'] == 4:
output_integer_tags(segmk, tile_param, 'ALMOST_EMPTY_OFFSET', invert=True)
output_integer_tags(segmk, tile_param, 'ALMOST_FULL_OFFSET', invert=True)
#output_integer_tags(segmk, tile_param, 'INIT', 36, invert=True)
#output_integer_tags(segmk, tile_param, 'SRVAL', 36, invert=True)
for param in ('EN_SYN', 'FIRST_WORD_FALL_THROUGH'):
segmk.add_site_tag(
tile_param['site'], param, tile_param[param])
segmk.compile()
segmk.write()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,18 @@
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_property IS_ENABLED 0 [get_drc_checks {REQP-38}]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,191 @@
import json
import math
import os
import functools
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray import verilog
from prjxray.verilog import vrandbits
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)
gridinfo = grid.gridinfo_at_loc(loc)
if gridinfo.tile_type not in ['BRAM_L', 'BRAM_R']:
continue
sites = {}
for site_name, site_type in gridinfo.sites.items():
sites[site_type] = site_name
yield tile_name, sites
@functools.lru_cache(maxsize=None)
def prepare_rand_int_choices(minval, maxval):
""" Creates list ints between minval and maxval to allow fuzzer to uniquely identify all bits."""
assert minval >= 0
assert maxval >= minval
min_p2 = math.floor(math.log(max(minval, 1), 2))
max_p2 = math.ceil(math.log(maxval+1, 2))
if 2**max_p2 > maxval:
max_search_p2 = max_p2 - 1
else:
max_search_p2 = max_p2
choices = set([minval, maxval, 2**(min_p2+1)-1, 2**(max_search_p2)-1])
lb = min_p2
ub = max_search_p2
while lb < ub:
ub = int(round(ub / 2.))
val = 2**ub - 1
lowval = val
if lowval < minval:
lowval |= (1 << max_search_p2)
assert lowval >= minval, (val, ub)
choices.add(lowval)
highval = val << (max_search_p2 - ub)
if highval > minval:
assert highval <= maxval, (val, ub)
choices.add(highval)
for bit in range(max_search_p2):
if 2**bit > minval:
choices.add(2**bit)
else:
choices.add(2**bit | 2**max_search_p2)
choices.add(2**bit | 2**(max_search_p2-1))
zeros = set()
ones = set()
for choice in choices:
assert choice >= minval, choice
assert choice <= maxval, choice
for bit in range(max_p2):
if (1 << bit) & choice:
ones.add(bit)
else:
zeros.add(bit)
assert len(ones) == max_p2
assert len(zeros) == max_p2
return tuple(sorted(choices))
def rand_int(minval, maxval):
return random.choice(prepare_rand_int_choices(minval, maxval))
def main():
print('''
module top();
''')
params_list = []
for tile_name, sites in gen_sites():
params = {}
params['site'] = sites['RAMBFIFO36E1']
params['DATA_WIDTH'] = random.choice([4, 9, 18, 36, 72])
params['EN_SYN'] = random.randint(0, 1)
params['DO_REG'] = 1
if params['EN_SYN']:
params['FIRST_WORD_FALL_THROUGH'] = 0
else:
params['FIRST_WORD_FALL_THROUGH'] = random.randint(0, 1)
if params['EN_SYN']:
MIN_ALMOST_FULL_OFFSET = 1
if params['DATA_WIDTH'] == 4:
MAX_ALMOST_FULL_OFFSET = 8190
elif params['DATA_WIDTH'] == 9:
MAX_ALMOST_FULL_OFFSET = 4094
elif params['DATA_WIDTH'] == 18:
MAX_ALMOST_FULL_OFFSET = 2046
elif params['DATA_WIDTH'] == 36:
MAX_ALMOST_FULL_OFFSET = 1022
elif params['DATA_WIDTH'] == 72:
MAX_ALMOST_FULL_OFFSET = 510
else:
assert False
MIN_ALMOST_EMPTY_OFFSET = MIN_ALMOST_FULL_OFFSET
MAX_ALMOST_EMPTY_OFFSET = MAX_ALMOST_FULL_OFFSET
else:
MIN_ALMOST_FULL_OFFSET = 4
if params['DATA_WIDTH'] == 4:
MAX_ALMOST_FULL_OFFSET = 8185
elif params['DATA_WIDTH'] == 9:
MAX_ALMOST_FULL_OFFSET = 4089
elif params['DATA_WIDTH'] == 18:
MAX_ALMOST_FULL_OFFSET = 2041
elif params['DATA_WIDTH'] == 36:
MAX_ALMOST_FULL_OFFSET = 1017
elif params['DATA_WIDTH'] == 72:
MAX_ALMOST_FULL_OFFSET = 505
else:
assert False
if params['FIRST_WORD_FALL_THROUGH']:
MIN_ALMOST_EMPTY_OFFSET = MIN_ALMOST_FULL_OFFSET + 2
MAX_ALMOST_EMPTY_OFFSET = MAX_ALMOST_FULL_OFFSET + 2
else:
MIN_ALMOST_EMPTY_OFFSET = MIN_ALMOST_FULL_OFFSET + 1
MAX_ALMOST_EMPTY_OFFSET = MAX_ALMOST_FULL_OFFSET + 1
ALMOST_EMPTY_OFFSET = rand_int(MIN_ALMOST_EMPTY_OFFSET, MAX_ALMOST_EMPTY_OFFSET)
ALMOST_FULL_OFFSET = rand_int(MIN_ALMOST_FULL_OFFSET, MAX_ALMOST_FULL_OFFSET)
params['ALMOST_EMPTY_OFFSET'] = "13'b{:013b}".format(ALMOST_EMPTY_OFFSET)
params['ALMOST_FULL_OFFSET'] = "13'b{:013b}".format(ALMOST_FULL_OFFSET)
if params['DATA_WIDTH'] == 36:
params['FIFO_MODE'] = verilog.quote('FIFO36_72')
else:
params['FIFO_MODE'] = verilog.quote('FIFO36_72')#verilog.quote('FIFO18') #verilog.quote(random.choice(('FIFO18', 'FIFO18_36')))
params['INIT'] = '0' #vrandbits(36)
params['SRVAL'] = '0' #vrandbits(36)
print(
'''
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
FIFO36E1 #(
.ALMOST_EMPTY_OFFSET({ALMOST_EMPTY_OFFSET}),
.ALMOST_FULL_OFFSET({ALMOST_FULL_OFFSET}),
.DATA_WIDTH({DATA_WIDTH}),
.DO_REG({DO_REG}),
.EN_SYN({EN_SYN}),
.FIFO_MODE({FIFO_MODE}),
.FIRST_WORD_FALL_THROUGH({FIRST_WORD_FALL_THROUGH}),
.INIT({INIT}),
.SRVAL({SRVAL})
) fifo_{site} (
);
'''.format(
**params,
))
params['FIFO_MODE'] = verilog.unquote(params['FIFO_MODE'])
params_list.append(params)
print("endmodule")
with open('params.json', 'w') as f:
json.dump(params_list, f, indent=2)
if __name__ == '__main__':
main()

View File

@ -70,13 +70,13 @@ proc write_bram_ppips_db {filename tile} {
if {[get_pips -uphill -of_objects [get_nodes -of_objects $dst_wire]] == $pip} {
set src_wire [get_wires -uphill -of_objects $pip]
puts $fp "${tile_type}.[regsub {.*/} $dst_wire ""].[regsub {.*/} $src_wire ""] always"
}
# LOGIC_OUTS pips appear to be always, even thought multiple inputs to
# the pip junction. Best guess is that the underlying hardware is
# actually just one wire, and there is no actually junction.
if [string match "*LOGIC_OUTS*" dst_wire] {
puts $fp "${tile_type}.[regsub {.*/} $dst_wire ""].[regsub {.*/} $src_wire ""] always"
} elseif [string match "*LOGIC_OUTS*" $dst_wire] {
# LOGIC_OUTS pips appear to be always, even thought multiple inputs to
# the pip junction. Best guess is that the underlying hardware is
# actually just one wire, and there is no actually junction.
foreach src_wire [get_wires -uphill -of_objects $pip] {
puts $fp "${tile_type}.[regsub {.*/} $dst_wire ""].[regsub {.*/} $src_wire ""] always"
}
}
}

View File

@ -38,6 +38,8 @@ $(eval $(call fuzzer,018-clb-ram,005-tilegrid))
$(eval $(call fuzzer,019-clb-ndi1mux,005-tilegrid))
$(eval $(call fuzzer,025-bram-config,005-tilegrid))
$(eval $(call fuzzer,026-bram-data,005-tilegrid))
$(eval $(call fuzzer,027-bram36-config,005-tilegrid))
$(eval $(call fuzzer,028-fifo-config,005-tilegrid))
$(eval $(call fuzzer,050-pip-seed,005-tilegrid))
$(eval $(call fuzzer,051-pip-imuxlout-bypalts,050-pip-seed))
$(eval $(call fuzzer,052-pip-clkin,050-pip-seed))
@ -47,7 +49,8 @@ $(eval $(call fuzzer,056-pip-rem,051-pip-imuxlout-bypalts 052-pip-clkin 053-pip-
$(eval $(call fuzzer,057-pip-bi,056-pip-rem))
ifneq ($(QUICK),Y)
$(eval $(call fuzzer,058-pip-hclk,056-pip-rem))
$(eval $(call fuzzer,071-ppips,057-pip-bi 058-pip-hclk))
$(eval $(call fuzzer,060-bram-cascades,005-tilegrid))
$(eval $(call fuzzer,071-ppips,057-pip-bi 058-pip-hclk 060-bram-cascades))
ifneq ($(BITONLY),Y)
$(eval $(call fuzzer,072-ordered_wires,))
$(eval $(call fuzzer,073-get_counts,))