|  | #!/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 io | 
|  | import os | 
|  | import random | 
|  | import re | 
|  | random.seed(int(os.getenv("SEED"), 16)) | 
|  | from prjxray import util | 
|  | from prjxray import lut_maker | 
|  | from prjxray import verilog | 
|  | 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.endswith("_SING"): | 
|  | continue | 
|  | # Y9 tiles have frame address 1 frame higher than the rest | 
|  | # Need to investigate what is so special about them | 
|  | if tile_name.endswith("Y9"): | 
|  | continue | 
|  |  | 
|  | sites = [] | 
|  | for site_name, site_type in gridinfo.sites.items(): | 
|  | if site_type == 'IDELAYE2': | 
|  | yield tile_name, site_name | 
|  |  | 
|  |  | 
|  | def write_params(params): | 
|  | pinstr = 'tile,isone,site\n' | 
|  | for vals in params: | 
|  | pinstr += ','.join(map(str, vals)) + '\n' | 
|  |  | 
|  | open('params.csv', 'w').write(pinstr) | 
|  |  | 
|  |  | 
|  | def use_idelay(p, luts, connects): | 
|  | print( | 
|  | ''' | 
|  | wire idelay_{site}; | 
|  |  | 
|  | (* KEEP, DONT_TOUCH, LOC = "{site}" *) | 
|  | IDELAYE2 #( | 
|  | .HIGH_PERFORMANCE_MODE("{param}"), | 
|  | .DELAY_SRC("DATAIN") | 
|  | ) idelay_site_{site} ( | 
|  | .DATAIN({onet}), | 
|  | .DATAOUT(idelay_{site}) | 
|  | ); | 
|  | assign {net} = idelay_{site}; | 
|  | '''.format( | 
|  | onet=luts.get_next_output_net(), | 
|  | net=luts.get_next_input_net(), | 
|  | param="TRUE" if p['isone'] else "FALSE", | 
|  | **p), | 
|  | file=connects) | 
|  |  | 
|  |  | 
|  | def run(): | 
|  | luts = lut_maker.LutMaker() | 
|  | connects = io.StringIO() | 
|  |  | 
|  | tile_params = [] | 
|  | params = [] | 
|  | sites = sorted(list(gen_sites())) | 
|  | for idx, ((tile, site), isone) in enumerate(zip( | 
|  | sites, util.gen_fuzz_states(len(sites)))): | 
|  |  | 
|  | p = {} | 
|  | p['tile'] = tile | 
|  | p['site'] = site | 
|  | p['isone'] = isone | 
|  | params.append(p) | 
|  | tile_params.append((tile, p['isone'], site)) | 
|  |  | 
|  | write_params(tile_params) | 
|  |  | 
|  | print(''' | 
|  | module top(); | 
|  | ''') | 
|  |  | 
|  | # Always output a LUT6 to make placer happy. | 
|  | print(''' | 
|  | (* KEEP, DONT_TOUCH *) | 
|  | LUT6 dummy_lut(); | 
|  | ''') | 
|  |  | 
|  | # Need IDELAYCTRL for IDEALAYs | 
|  | print(''' | 
|  | (* KEEP, DONT_TOUCH *) | 
|  | IDELAYCTRL(); | 
|  | ''') | 
|  |  | 
|  | for p in params: | 
|  | use_idelay(p, luts, connects) | 
|  |  | 
|  | for l in luts.create_wires_and_luts(): | 
|  | print(l) | 
|  |  | 
|  | print(connects.getvalue()) | 
|  |  | 
|  | print("endmodule") | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | run() |