|  | #!/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() |