#!/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 random random.seed(int(os.getenv("SEED"), 16)) from prjxray import util from prjxray.db import Database INT_TILE_TYPES = ['INT_L', 'INT_R'] HCLK_TILE_TYPES = ['HCLK_L', 'HCLK_R', 'HCLK_L_BOT_UTURN', 'HCLK_R_BOT_UTURN'] def get_int_column_roots(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 INT_TILE_TYPES: continue next_gridinfo = grid.gridinfo_at_loc((loc.grid_x, loc.grid_y + 1)) if next_gridinfo.tile_type in INT_TILE_TYPES: continue if next_gridinfo.tile_type in HCLK_TILE_TYPES: continue assert next_gridinfo.tile_type in [ 'B_TERM_INT', 'BRKH_INT', 'BRKH_B_TERM_INT' ], next_gridinfo.tile_type yield tile_name def build_int_columns(grid): int_columns = {} for root_tile_name in get_int_column_roots(grid): assert root_tile_name not in int_columns int_columns[root_tile_name] = [] tile_name = root_tile_name gridinfo = grid.gridinfo_at_tilename(tile_name) # Walk up INT column. while gridinfo.tile_type in INT_TILE_TYPES: int_columns[root_tile_name].append(tile_name) loc = grid.loc_of_tilename(tile_name) tile_name = grid.tilename_at_loc((loc.grid_x, loc.grid_y - 1)) gridinfo = grid.gridinfo_at_tilename(tile_name) if gridinfo.tile_type in HCLK_TILE_TYPES: loc = grid.loc_of_tilename(tile_name) tile_name = grid.tilename_at_loc((loc.grid_x, loc.grid_y - 1)) gridinfo = grid.gridinfo_at_tilename(tile_name) assert gridinfo.tile_type in [ 'T_TERM_INT', 'BRKH_INT', 'BRKH_TERM_INT' ], gridinfo.tile_type return int_columns def pair_int_tiles(grid, int_tiles): tiles_left = set(int_tiles) while tiles_left: tile_name = tiles_left.pop() gridinfo = grid.gridinfo_at_tilename(tile_name) loc = grid.loc_of_tilename(tile_name) assert gridinfo.tile_type in INT_TILE_TYPES if gridinfo.tile_type == 'INT_L': other_int_tile = 'INT_R' other_loc = (loc.grid_x + 1, loc.grid_y) else: other_int_tile = 'INT_L' other_loc = (loc.grid_x - 1, loc.grid_y) paired_tile_name = grid.tilename_at_loc(other_loc) paired_gridinfo = grid.gridinfo_at_tilename(paired_tile_name) assert paired_gridinfo.tile_type == other_int_tile, paired_gridinfo.tile_type tiles_left.remove(paired_tile_name) yield sorted([tile_name, paired_tile_name]) def is_orphan_int_row(grid, int_l, int_r): """ Returns true if given INT pair have no adjcent sites. """ loc = grid.loc_of_tilename(int_l) if grid.gridinfo_at_loc( (loc.grid_x - 1, loc.grid_y)).tile_type != 'INT_INTERFACE_L': return False if grid.gridinfo_at_loc( (loc.grid_x - 2, loc.grid_y)).tile_type != 'VFRAME': return False loc = grid.loc_of_tilename(int_r) if grid.gridinfo_at_loc( (loc.grid_x + 1, loc.grid_y)).tile_type != 'INT_INTERFACE_R': return False if grid.gridinfo_at_loc( (loc.grid_x + 2, loc.grid_y)).tile_type not in ['CLK_FEED', 'CLK_BUFG_REBUF', 'NULL']: return False return True def gen_orphan_ints(grid): int_columns = build_int_columns(grid) for int_l_column, int_r_column in sorted(pair_int_tiles( grid, int_columns.keys())): found_site = False for int_l, int_r in zip(int_columns[int_l_column], int_columns[int_r_column]): if not is_orphan_int_row(grid, int_l, int_r): found_site = True break if not found_site: yield int_columns[int_l_column], int_columns[int_r_column] def write_params(params): pinstr = 'tile,val\n' for tile, (val) in sorted(params.items()): pinstr += '%s,%s\n' % (tile, val) open('params.csv', 'w').write(pinstr) def build_cross_int(params, grid, int_l, int_r): """ Toggles INT_R.ER1BEG1.EE4END0 """ loc = grid.loc_of_tilename(int_r) origin_tile = grid.tilename_at_loc((loc.grid_x - 4, loc.grid_y)) origin_gridinfo = grid.gridinfo_at_tilename(origin_tile) assert origin_gridinfo.tile_type == 'CLBLL_R' origin_site = sorted(origin_gridinfo.sites.keys())[random.randint(0, 1)] dest_tile = grid.tilename_at_loc((loc.grid_x + 4, loc.grid_y)) dest_gridinfo = grid.gridinfo_at_tilename(dest_tile) assert dest_gridinfo.tile_type == 'CLBLL_L' dest_site = sorted(dest_gridinfo.sites.keys())[0] dest2_tile = grid.tilename_at_loc((loc.grid_x + 4, loc.grid_y + 1)) dest2_gridinfo = grid.gridinfo_at_tilename(dest2_tile) assert dest2_gridinfo.tile_type == 'CLBLL_L', dest2_gridinfo.tile_type dest2_site = sorted(dest2_gridinfo.sites.keys())[1] if random.randint(0, 1): dest_wire = 'origin_wire_{origin_site}'.format(origin_site=origin_site) else: dest_wire = '1' if random.randint(0, 1): dest_wire2 = 'origin_wire_{origin_site}'.format( origin_site=origin_site) else: dest_wire2 = '1' if random.randint(0, 1): dest_wire3 = 'origin_wire_{origin_site}'.format( origin_site=origin_site) else: dest_wire3 = '1' if random.randint(0, 1): dest_wire4 = 'origin_wire_{origin_site}'.format( origin_site=origin_site) else: dest_wire4 = '1' # origin_site.AQ -> dest_tile.D6 enables INT_R.ER1BEG1.EE4END0 print( """ // Force origin FF into A position with MUXF7_L and MUXF8 wire origin_wire_{origin_site}; wire f7_to_lo_{origin_site}; wire lut_to_f7_{origin_site}; (* KEEP, DONT_TOUCH, LOC = "{origin_site}" *) LUT6_L #( .INIT(0) ) lut_rom_{origin_site} ( .I0(1), .I1(origin_wire_{origin_site}), .I2(0), .I3(1), .I4(1), .I5(1), .LO(lut_to_f7_{origin_site}) ); (* KEEP, DONT_TOUCH, LOC = "{origin_site}" *) MUXF7_D f7_{origin_site} ( .I0(lut_to_f7_{origin_site}), .LO(f7_to_lo_{origin_site}), .O(origin_wire_{origin_site}) ); (* KEEP, DONT_TOUCH, LOC = "{origin_site}" *) MUXF8 f8_{origin_site} ( .I1(f7_to_lo_{origin_site}) ); wire dest_wire_{dest_site}; wire dest_wire2_{dest_site}; wire d_lut_to_f7_{dest_site}, f7_to_f8_{dest_site}; // Force destination LUT into D position with MUXF7_L and MUXF8 (* KEEP, DONT_TOUCH, LOC = "{dest_site}" *) LUT6_L #( .INIT(0) ) d_lut_rom_{dest_site} ( .I0(1), .I1(1), .I2(0), .I3(1), .I4(1), .I5(dest_wire_{dest_site}), .LO(d_lut_to_f7_{dest_site}) ); wire c_lut_to_f7_{dest_site}; // Force destination LUT into C position with MUXF7_L and MUXF8 (* KEEP, DONT_TOUCH, LOC = "{dest_site}" *) LUT6_L #( .INIT(0) ) c_lut_rom_{dest_site} ( .I0(1), .I1(1), .I2(0), .I3(1), .I4(1), .I5(dest_wire2_{dest_site}), .LO(c_lut_to_f7_{dest_site}) ); (* KEEP, DONT_TOUCH, LOC = "{dest_site}" *) MUXF7_L f7_{dest_site} ( .I0(d_lut_to_f7_{dest_site}), .I1(c_lut_to_f7_{dest_site}), .LO(f7_to_f8_{dest_site}) ); (* KEEP, DONT_TOUCH, LOC = "{dest_site}" *) MUXF8 f8_{dest_site} ( .I0(f7_to_f8_{dest_site}) ); assign dest_wire_{dest_site} = {dest_wire}; assign dest_wire2_{dest_site} = {dest_wire2}; wire dest_wire3_{dest_site2}; wire dest_wire4_{dest_site2}; wire lut_to_f7_{dest_site2}, f7_to_f8_{dest_site2}; // Force destination LUT into D position with MUXF7_L and MUXF8 (* KEEP, DONT_TOUCH, LOC = "{dest_site2}" *) LUT6_L #( .INIT(0) ) d_lut_rom_{dest_site2} ( .I0(dest_wire3_{dest_site2}), .I1(1), .I2(0), .I3(1), .I4(1), .I5(), .LO(lut_to_f7_{dest_site2}) ); // Force destination LUT into C position with MUXF7_L and MUXF8 wire c_lut_to_f7_{dest_site2}; (* KEEP, DONT_TOUCH, LOC = "{dest_site2}" *) LUT6_L #( .INIT(0) ) c_lut_rom_{dest_site2} ( .I0(dest_wire4_{dest_site2}), .I1(1), .I2(0), .I3(1), .I4(1), .I5(1), .LO(c_lut_to_f7_{dest_site2}) ); (* KEEP, DONT_TOUCH, LOC = "{dest_site2}" *) MUXF7_L f7_{dest_site2} ( .I0(lut_to_f7_{dest_site2}), .I1(c_lut_to_f7_{dest_site2}), .LO(f7_to_f8_{dest_site2}) ); (* KEEP, DONT_TOUCH, LOC = "{dest_site2}" *) MUXF8 f8_{dest_site2} ( .I0(f7_to_f8_{dest_site2}) ); assign dest_wire3_{dest_site2} = {dest_wire3}; assign dest_wire4_{dest_site2} = {dest_wire4}; """.format( dest_site=dest_site, dest_site2=dest2_site, origin_site=origin_site, dest_wire=dest_wire, dest_wire2=dest_wire2, dest_wire3=dest_wire3, dest_wire4=dest_wire4, )) def run(): print(''' module top(); ''') int_tiles = [] db = Database(util.get_db_root(), util.get_part()) grid = db.grid() params = {} for int_l_column, int_r_column in gen_orphan_ints(grid): for int_l, int_r in zip(int_l_column[1:6:2], int_r_column[1:6:2]): build_cross_int(params, grid, int_l, int_r) int_tiles.append(int_l) print("endmodule") with open('top.txt', 'w') as f: for tile in int_tiles: print(tile, file=f) if __name__ == '__main__': run()