blob: faaa224a48f189a2985d4ecb1429719b2372d037 [file] [log] [blame]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2017-2020 The Project X-Ray Authors.
#
# Use of this source code is governed by a ISC-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/ISC
#
# SPDX-License-Identifier: ISC
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(), util.get_part())
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['tile'] = tile_name
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()