| #!/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 os | 
 | import itertools | 
 | import re | 
 | import random | 
 | random.seed(int(os.getenv("SEED"), 16)) | 
 | from prjxray import util | 
 | from prjxray.db import Database | 
 |  | 
 | XY_RE = re.compile('^BUFHCE_X([0-9]+)Y([0-9]+)$') | 
 | BUFGCTRL_XY_RE = re.compile('^BUFGCTRL_X([0-9]+)Y([0-9]+)$') | 
 | """ | 
 | BUFHCE's can be driven from: | 
 |  | 
 | MMCME2_ADV | 
 | BUFHCE | 
 | PLLE2_ADV | 
 | BUFGCTRL | 
 | """ | 
 |  | 
 |  | 
 | def get_xy(s): | 
 |     m = BUFGCTRL_XY_RE.match(s) | 
 |     x = int(m.group(1)) | 
 |     y = int(m.group(2)) | 
 |     return x, y | 
 |  | 
 |  | 
 | def gen_sites(desired_site_type): | 
 |     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) | 
 |         for site, site_type in gridinfo.sites.items(): | 
 |             if site_type == desired_site_type: | 
 |                 yield site | 
 |  | 
 |  | 
 | def gen_bufhce_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) | 
 |         sites = [] | 
 |  | 
 |         for site, site_type in gridinfo.sites.items(): | 
 |             if site_type == 'BUFHCE': | 
 |                 sites.append(site) | 
 |  | 
 |         if sites: | 
 |             yield tile_name, set(sites) | 
 |  | 
 |  | 
 | def main(): | 
 |     print(''' | 
 | module top(); | 
 |     ''') | 
 |  | 
 |     gclks = [] | 
 |     for site in sorted(gen_sites("BUFGCTRL"), key=get_xy): | 
 |         wire_name = 'clk_{}'.format(site) | 
 |         gclks.append(wire_name) | 
 |  | 
 |         print( | 
 |             """ | 
 |     wire {wire_name}; | 
 |     (* KEEP, DONT_TOUCH, LOC = "{site}" *) | 
 |     BUFG bufg_{site} ( | 
 |         .O({wire_name}) | 
 |         ); | 
 |         """.format( | 
 |                 site=site, | 
 |                 wire_name=wire_name, | 
 |             )) | 
 |  | 
 |     bufhce_sites = list(gen_bufhce_sites()) | 
 |  | 
 |     opts = [] | 
 |     for count in range(len(bufhce_sites)): | 
 |         for opt in itertools.combinations(bufhce_sites, count + 1): | 
 |             opts.append(opt) | 
 |  | 
 |     for gclk in gclks: | 
 |         for tile_name, sites in random.choice(opts): | 
 |             for site in sorted(sites): | 
 |                 print( | 
 |                     """ | 
 |         (* KEEP, DONT_TOUCH, LOC = "{site}" *) | 
 |         BUFHCE buf_{site} ( | 
 |             .I({wire_name}) | 
 |                 );""".format( | 
 |                         site=site, | 
 |                         wire_name=gclk, | 
 |                     )) | 
 |                 sites.remove(site) | 
 |                 break | 
 |  | 
 |     print("endmodule") | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 |     main() |