def __init__(self, bitsfile, verbose=False, db_root=None, part=None, bits_per_word=32): self.db_root = db_root if self.db_root is None: self.db_root = util.get_db_root() self.part = part if self.part is None: self.part = util.get_part() assert self.part, "No part specified." self.verbose = verbose if verbose is not None else os.getenv( 'VERBOSE', 'N') == 'Y' self.bits_per_word = bits_per_word self.load_grid() self.load_bits(bitsfile) ''' self.tags[site][name] = value Where: -site: ex 'SLICE_X13Y101' -name: ex 'CLB.SLICE_X0.AFF.DMUX.CY' ''' self.site_tags = dict() self.tile_tags = dict() # output after compiling self.segments_by_type = None # hacky...improve if we encounter this more self.def_bt = 'CLB_IO_CLK' self.index_sites()
def gen_sites(tile_type): o = {} db = Database(util.get_db_root(), util.get_part()) grid = db.grid() allowed_sites = read_allowed_sites() for tile_name in sorted(grid.tiles()): loc = grid.loc_of_tilename(tile_name) gridinfo = grid.gridinfo_at_loc(loc) if gridinfo.tile_type != tile_type: continue for site_name, site_type in gridinfo.sites.items(): if site_type in ['HPIOB_S', 'HPIOB_M', 'HDIOB_S', 'HDIOB_M' ] and site_name in allowed_sites: if tile_name not in o: o[tile_name] = [] o[tile_name].append(site_name) for tile_name in o: o[tile_name].sort(key=util.create_xy_fun('IOB_')) return o
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) tile_type = gridinfo.tile_type if tile_type in ['CLEL_L', 'CLEL_R']: # Don't fuzz the top and bottom of the grid, the interconnect # there behaves differently. _, _, y_min, y_max = grid.dims() if loc.grid_y <= y_min + 1 or loc.grid_y >= y_max - 1: continue site_name = sorted(gridinfo.sites.keys())[0] if gridinfo.tile_type[-1] == 'L': int_tile_loc = (loc.grid_x + 1, loc.grid_y) else: int_tile_loc = (loc.grid_x - 1, loc.grid_y) int_tile_name = grid.tilename_at_loc(int_tile_loc) if not int_tile_name.startswith('INT_'): continue yield int_tile_name, site_name
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 in ['CLEM_R']: site_name = sorted(gridinfo.sites.keys())[0] yield tile_name, site_name
def gen_bufgs(): 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 "BUFGCE" in site and "HDIO" not in site and "DIV" not in site: yield site
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) for site_name, site_type in gridinfo.sites.items(): if site_type in ['RAMBFIFO18']: yield tile_name, site_name
def gen_sites(): """ Generates all possible SLICE 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 in ['CLEL_L', 'CLEL_R', 'CLEM', 'CLEM_R']: site_name = sorted(gridinfo.sites.keys())[0] yield site_name
def gen_sites(): """ Generates all possible SLICE sites """ SLICE_RE = re.compile(r"SLICE_X([0-9]+)Y([0-9]+)") 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 in ['CLEL_L', 'CLEL_R', 'CLEM', 'CLEM_R']: site_name = sorted(gridinfo.sites.keys())[0] match = SLICE_RE.match(site_name) if match is not None: site_loc = int(match.group(1)), int(match.group(2)) yield Site(tile_name, site_name, site_loc)
def gen_bufgs(): bufgces_by_tile = {} db = Database(util.get_db_root(), util.get_part()) grid = db.grid() for tile in sorted(grid.tiles()): loc = grid.loc_of_tilename(tile) gridinfo = grid.gridinfo_at_loc(loc) for site, site_type in gridinfo.sites.items(): if ("BUFGCE" in site or "BUFGCTRL" in site) and "HDIO" not in site: if tile not in bufgces_by_tile: bufgces_by_tile[tile] = [] bufgces_by_tile[tile].append((site, site_type)) return bufgces_by_tile
def gen_sites(): db = Database(util.get_db_root(), util.get_part()) grid = db.grid() o = {} for tile_name in sorted(grid.tiles()): loc = grid.loc_of_tilename(tile_name) gridinfo = grid.gridinfo_at_loc(loc) for site_name, site_type in gridinfo.sites.items(): if site_type == 'BUFCE_LEAF': if tile_name not in o: o[tile_name] = [] o[tile_name].append(site_name) return o
def gen_sites(): db = Database(util.get_db_root(), util.get_part()) grid = db.grid() tiles = {} 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 in ['SLICEM', 'SLICEL']: if gridinfo.tile_type not in tiles: tiles[gridinfo.tile_type] = set() tiles[gridinfo.tile_type].add(site) return tiles
def gen_sites(): db = Database(util.get_db_root(), util.get_part()) grid = db.grid() bufgces = [] slices = [] 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 "BUFGCE" in site and "HDIO" not in site: bufgces.append(site) if "SLICEM" in site or "SLICEL" in site: slices.append(site) return bufgces, slices
def gen_sites(): db = Database(util.get_db_root(), util.get_part()) grid = db.grid() xy_fun = util.create_xy_fun('BITSLICE_RX_TX_') o = {} for tile_name in sorted(grid.tiles()): loc = grid.loc_of_tilename(tile_name) gridinfo = grid.gridinfo_at_loc(loc) for site_name, site_type in gridinfo.sites.items(): if site_type == 'BITSLICE_RX_TX': if tile_name not in o: o[tile_name] = [] o[tile_name].append(site_name) if tile_name in o: o[tile_name].sort(key=lambda site: xy_fun(site)) return o
def print_top(seed): np.random.seed(seed) db = Database(util.get_db_root(), util.get_part()) grid = db.grid() slices = sorted(gen_sites(grid)) np.random.shuffle(slices) print(""" module top(); """) print(""" (* BEL="A6LUT", LOC="{loc}", KEEP, DONT_TOUCH *) LUT5 lut (); """.format(loc=slices.pop())) print('endmodule') leafs = populate_leafs(grid) site_to_site_type = {} site_to_tile = {} 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(): site_to_site_type[site] = site_type site_to_tile[site] = tile_name bufgs = GlobalClockBuffers('../bufg_outputs.csv') clock_column = sorted(leafs.keys()) np.random.shuffle(clock_column) bufg_leaf = util.create_xy_fun(prefix='BUFCE_LEAF_') delays = [0, 1, 2, 4, 8] global_clocks = list(range(MAX_GLOBAL_CLOCKS)) np.random.shuffle(global_clocks) with open('complete_top.tcl', 'w') as f: print('place_design -directive Quick', file=f) print('source $::env(URAY_UTILS_DIR)/utils.tcl', file=f) for idx, global_clock in enumerate(global_clocks): bufg_list = [ bufg for bufg in bufgs.bufgs[global_clock] if bufg.startswith('BUFGCE_X') ] bufg_list.sort() np.random.shuffle(bufg_list) bufg = bufg_list.pop() loc, column_direction = clock_column.pop() print('# {} {}'.format(loc, column_direction), file=f) gridinfo = grid.gridinfo_at_loc(loc) coords = [] for site in gridinfo.sites.keys(): x, y = bufg_leaf(site) coords.append((x, y)) coords.sort() y_min = coords[0][1] buf_leafs = [] for site in gridinfo.sites.keys(): _, y = bufg_leaf(site) if y - y_min < 2 and column_direction > 0: buf_leafs.append(site) if y - y_min >= 2 and column_direction < 0: buf_leafs.append(site) buf_leafs.sort() np.random.shuffle(buf_leafs) bufce_leaf = buf_leafs.pop() slices = list(leafs[loc, column_direction]) slices.sort() np.random.shuffle(slices) slice_site = slices.pop() delay = np.random.choice(delays) print( "create_leaf_delay {idx} {delay} {bufgce_site} {bufce_leaf_site} {slice_site}" .format( idx=idx, delay=delay, bufgce_site=bufg, bufce_leaf_site=bufce_leaf, slice_site=slice_site, ), file=f) print('route_design -directive Quick', file=f) print('set_property IS_ENABLED 0 [get_drc_checks {RTRES-2}]', file=f)
def print_top(seed): np.random.seed(seed) db = Database(util.get_db_root(), util.get_part()) grid = db.grid() clocks = ClockColumns(grid) disabled_columns = set() for key in clocks.columns(): if np.random.choice([1, 0], p=[.25, .75]): disabled_columns.add(key) clocks.remove_column(disabled_columns) print(""" module top(input clk, stb, di, output do); """) bufg_by_tile = gen_bufgs(grid) tile = np.random.choice(sorted(bufg_by_tile.keys())) bufgs = bufg_by_tile[tile] assert len(bufgs) > 0 bufgs.sort() np.random.shuffle(bufgs) slices = sorted(clocks.sites.keys()) np.random.shuffle(slices) num_bufgs = np.random.randint(1, min(len(bufgs) + 1, 25)) assert num_bufgs > 0 print(' wire [{}:0] bufg_clk;'.format(num_bufgs)) for idx, site in enumerate(bufgs): if idx >= num_bufgs: break print( ' (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFGCE bufg_{i} ( .CE(1\'b1), .O(bufg_clk[{i}]) );' .format(i=idx, loc=site)) num_slices = np.random.randint(1, len(slices) + 1) for idx, slice_loc in enumerate(slices): if idx >= num_slices: break all_clocks = list(range(0, num_bufgs)) np.random.shuffle(all_clocks) while True: clock_str = 'bufg_clk[{}]'.format(all_clocks.pop()) if clocks.add_clock(slice_loc, clock_str): print( ' (* LOC="{loc}", KEEP, DONT_TOUCH *) FDCE ff_{i}(.C({clock_str}));' .format(loc=slice_loc, i=idx, clock_str=clock_str)) break print('endmodule') with open('top.tcl', 'w') as f: print("set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]", file=f)
def print_top(seed): np.random.seed(seed) db = Database(util.get_db_root(), util.get_part()) grid = db.grid() site_to_site_type = {} site_to_tile = {} 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(): site_to_site_type[site] = site_type site_to_tile[site] = tile_name slices = sorted(gen_sites(grid)) np.random.shuffle(slices) with open('../active_bufce_row.csv') as f: bufce_rows = [row for row in DictReader(f)] np.random.shuffle(bufce_rows) with open('../bufce_leaf_clock_regions.csv') as f: bufce_leafs = [row for row in DictReader(f)] bufgs = GlobalClockBuffers('../bufg_outputs.csv') with open('complete_top.tcl', 'w') as f: #print('place_design -directive Quick', file=f) print(""" write_checkpoint -force design_reset.dcp close_design open_checkpoint design_reset.dcp route_design set route_status [struct::set union [get_property ROUTE_STATUS [get_nets -hierarchical ]] []] if { [llength $route_status] > 1 } { set_property ROUTE "" [get_nets -hierarchical] route_design -nets [get_nets bufce_row_out_*] route_design -nets [concat [get_nets lut_*] [get_nets -filter "TYPE == POWER || TYPE == GROUND"]] route_design } """, file=f) print(""" module top(); """) N_LUTS = 3 ce_inputs = [0, 1] for idx in range(N_LUTS): print(""" wire lut_o_{idx}; (* BEL="A6LUT", LOC="{loc}", KEEP, DONT_TOUCH *) LUT5 lut{idx} (.O(lut_o_{idx})); """.format(idx=idx, loc=slices.pop())) ce_inputs.append('lut_o_{}'.format(idx)) clock_resource_in_use = set() bufg_for_hroute = {} bufce_rows_by_cmt = {} for idx, bufce_row in enumerate(bufce_rows): if np.random.choice([0, 1], p=[.75, .25]): continue clock_region = bufce_row['site_clock_region'] if clock_region not in bufce_rows_by_cmt: bufce_rows_by_cmt[clock_region] = [] # Don't overuse HDISTR resources! key = (bufce_row['site_clock_region'], bufce_row['hdistr_number']) if key in clock_resource_in_use: continue hdistr_number = int(bufce_row['hdistr_number']) if hdistr_number not in bufg_for_hroute: while True: site = np.random.choice(bufgs.bufgs[hdistr_number]) site_type = site_to_site_type[site] if site_type == 'BUFGCE': break s, bufg_for_hroute[hdistr_number] = make_bufg( site=site, site_type=site_type, idx=len(bufg_for_hroute), ce_inputs=['1'], randlib=np.random) print(s) clock_resource_in_use.add(key) bufce_rows_by_cmt[clock_region].append(idx) if np.random.choice([0, 1], p=[.9, .1]): bufg_in = '1' ce_type = 'ASYNC' else: bufg_in = bufg_for_hroute[hdistr_number] ce_type = np.random.choice(["SYNC", "ASYNC"]) print(""" wire bufce_row_out_{idx}; (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFCE_ROW #( .IS_I_INVERTED({invert_i}), .IS_CE_INVERTED({invert_ce}), .CE_TYPE("{ce_type}") ) bufce_row_{idx} ( .I({bufg_in}), .O(bufce_row_out_{idx}), .CE({ce}) );""".format(loc=bufce_row['site'], invert_i=np.random.randint(2), invert_ce=np.random.randint(2), ce_type=ce_type, ce=np.random.choice(ce_inputs), bufg_in=bufg_in, idx=idx)) for idx, bufce_leaf in enumerate(bufce_leafs): if np.random.choice([0, 1], p=[.75, .25]): continue clock_region = bufce_leaf['clock_region'] if clock_region not in bufce_rows_by_cmt: continue clock_in_idx = np.random.choice(bufce_rows_by_cmt[clock_region]) print(""" (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFCE_LEAF #( .IS_I_INVERTED({invert_i}), .IS_CE_INVERTED({invert_ce}), .CE_TYPE("{ce_type}") ) bufce_leaf_{idx} ( .I({clock_in}), .CE({ce}) );""".format(loc=bufce_leaf['site'], invert_i=np.random.randint(2), invert_ce=np.random.randint(2), ce_type=np.random.choice(["SYNC", "ASYNC"]), ce=np.random.choice(ce_inputs), idx=idx, clock_in='bufce_row_out_{}'.format(clock_in_idx))) print('endmodule')
def run(): parser = argparse.ArgumentParser() parser.add_argument('--bits_file', default='design.bits') parser.add_argument('--features_file', default='design.features') parser.add_argument('--extent_features_file', default=None) parser.add_argument('--block_type', default='CLB_IO_CLK') parser.add_argument( '--zero_feature_enums', help= "File containing features that are zero enums, and which parameter is the zero." ) args = parser.parse_args() zero_features = {} if args.zero_feature_enums: with open(args.zero_feature_enums) as f: for l in f: parts = l.strip().split('=') assert len(parts) == 2, "Expected line with =" zero_features[parts[0]] = parts[1] db = Database(util.get_db_root(), util.get_part()) grid = db.grid() feature_data = {} feature_trees = {} if args.extent_features_file: with open(args.extent_features_file) as f: tile_type = None for l in f: l = l.strip() if l.startswith('.tiletype'): tile_type = l.split(' ')[1] assert tile_type not in feature_data feature_data[tile_type] = set() feature_data[tile_type].add(l.strip()) for tile_type in feature_data: features = feature_data[tile_type] split_features = [] for feature in features: split_features.append(feature.split('.')) split_features.sort(key=lambda x: -len(x)) tree = FeatureTree(part=tile_type) for split_feature in split_features: child = tree for part in split_feature: child = child[part] tree.coalesce() feature_trees[tile_type] = tree all_features = read_features(args.features_file) tile_types = set() for _, tile_type in all_features.keys(): tile_types.add(tile_type) for tile_type in tile_types: segmk = Segmaker(args.bits_file, bits_per_word=16) segmk.set_def_bt(args.block_type) tree = feature_trees[tile_type] pip_active = {} pip_sources = {} pip_active_per_tile = {} for pip_feature in tree.pip_features(): dest = pip_feature.part assert dest not in pip_active assert dest not in pip_sources pip_active[dest] = 0 sources = [] for child in pip_feature: child_feature = pip_feature[child] parts = child_feature.full_feature().split('.') assert parts[1] == 'PIP' if child_feature.is_leaf(): sources.append(parts[-1]) else: src = child_feature.part children = set(child for child in child_feature) assert len(set(('FWD', 'REV')) | children) == 2, children sources.extend([ '{}.FWD'.format(src), '{}.REV'.format(src), ]) pip_sources[dest] = sources proto_pip_active = pip_active for (tile, a_type), features in all_features.items(): if tile_type != a_type: continue loc = grid.loc_of_tilename(tile) gridinfo = grid.gridinfo_at_loc(loc) if BlockType.CLB_IO_CLK not in gridinfo.bits: print('*** WARNING *** Tile {} is missing bits!'.format(tile)) continue pip_active = dict(proto_pip_active) indicies = {} for l in features: parts = l.split('.') feature = tree.find_feature(l) # Mark active indices on vector features if feature.index is not None and len(feature.index) > 1: current_index = int(parts[-1].split('[')[1][:-1]) if id(feature) not in indicies: indicies[id(feature)] = (feature, set()) indicies[id(feature)][1].add(current_index) segmk.add_tile_tag(tile, l, 1) if parts[0] == "PIP": assert feature.is_leaf() assert parts[1] in pip_active pip_active[parts[1]] = 1 elif feature.is_leaf() and feature.index is None: parent = feature.parent should_emit_enum_zero = True # Only emit 0 tags if this is not a zero feature, or if # this is feature is the zero enum. if parent.part in zero_features: if zero_features[parent.part] != feature.part: should_emit_enum_zero = False parts = parent.full_feature().split('.')[1:] parts.append(zero_features[parent.part]) s = '.'.join(parts) segmk.add_tile_tag(tile, s, 0) if should_emit_enum_zero: for child in parent: child_feature = parent[child] if child_feature is not feature: if not child_feature.is_leaf(): continue parts = child_feature.full_feature().split( '.')[1:] s = '.'.join(parts) segmk.add_tile_tag(tile, s, 0) for feature, active_indicies in indicies.values(): min_index = min(active_indicies) if min(feature.index) + 1 == min_index: min_index = min(feature.index) max_index = max(active_indicies) if max(feature.index) - 1 == max_index: max_index = max(feature.index) s = '.'.join(feature.full_feature().split('.')[1:]) s = '['.join(s.split('[')[:-1]) for idx in range(min_index, max_index + 1): if idx in active_indicies: continue segmk.add_tile_tag(tile, '{}[{}]'.format(s, idx), 0) # Output disable features for pips. pip_active_per_tile[tile] = pip_active segmk.compile() segmk.write(allow_empty=True, extra_tags=output_empty_pips(tree, pip_sources, pip_active_per_tile))
def print_top(seed, f=sys.stdout): np.random.seed(seed) db = Database(util.get_db_root(), util.get_part()) grid = db.grid() bufgces_by_tile = {} rclk_int_l = [] slices_by_tile = {} for tile in sorted(grid.tiles()): loc = grid.loc_of_tilename(tile) if tile.startswith("RCLK_INT_L"): rclk_int_l.append((loc.grid_x, loc.grid_y, tile)) gridinfo = grid.gridinfo_at_loc(loc) for site, site_type in gridinfo.sites.items(): if ("BUFGCE" in site or "BUFGCTRL" in site) and "HDIO" not in site: if tile not in bufgces_by_tile: bufgces_by_tile[tile] = [] bufgces_by_tile[tile].append((site, site_type)) elif "SLICE_" in site: slices_by_tile[loc.grid_x, loc.grid_y] = site halfcolumn_slices_by_row = {} for x, y, rclk in rclk_int_l: hc_up = [] hc_down = [] if y not in halfcolumn_slices_by_row: halfcolumn_slices_by_row[y] = [] for yplus in range(y + 1, y + 31): if (x, yplus) not in grid.loc: continue tile = grid.tilename_at_loc((x, yplus)) if not tile.startswith("INT_"): break slice_x = x + np.random.choice([+1, -1]) if (slice_x, yplus) not in slices_by_tile: continue hc_up.append(slices_by_tile[slice_x, yplus]) for yminus in range(y - 1, y - 31, -1): if (x, yminus) not in grid.loc: continue tile = grid.tilename_at_loc((x, yminus)) if not tile.startswith("INT_"): break slice_x = x + np.random.choice([+1, -1]) if (slice_x, yminus) not in slices_by_tile: continue hc_down.append(slices_by_tile[slice_x, yminus]) halfcolumn_slices_by_row[y].append(hc_up) halfcolumn_slices_by_row[y].append(hc_down) buffers = [] tiles = list(sorted(bufgces_by_tile.keys())) np.random.shuffle(tiles) for tile in tiles: shuffled_bufs = list(bufgces_by_tile[tile]) np.random.shuffle(shuffled_bufs) target_type = np.random.choice( ["BUFGCE", "BUFGCE_DIV", "BUFGCTRL"] if len(buffers) > 0 else ["BUFGCE", "BUFGCE_DIV"]) tile_buffers = np.random.randint(6) found_buffers = 0 for buf, buftype in shuffled_bufs: if found_buffers >= tile_buffers: break if buftype != target_type: continue buffers.append((buf, buftype)) found_buffers += 1 def random_inversion(pins): return ", ".join( [".IS_%s_INVERTED(%d)" % (p, np.random.randint(2)) for p in pins]) def random_control(pins): return ", ".join( [".%s(aux[%d])" % (p, np.random.randint(10)) for p in pins]) CCIO_CLKS = 24 print( "module top(input [{CCIO_CLKS}-1:0] i, input [9:0] aux, input d, output o, q);" .format(CCIO_CLKS=CCIO_CLKS), file=f) print(" wire [71:0] r;", file=f) # print(" assign r[0] = i;", file=f) # print(" assign o = r[%d];" % N, file=f) # for i in range(N): # bg, buftype = buffers[i] # #print("(* LOC=\"%s\" *)" % bg, file=f) # if "BUFGCTRL" in buftype: # print(" BUFGCTRL #(", file=f) # print(" %s," % random_inversion(["I0", "I1", "S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f) # print(" .INIT_OUT(%d), .PRESELECT_I0(\"%s\"), .PRESELECT_I1(\"%s\")" % # (np.random.randint(2), np.random.choice(["TRUE", "FALSE"]), np.random.choice(["TRUE", "FALSE"])), file=f) # print(" ) bufgctrl_%d (" % i, file=f) # print(" .I0(r[%d]), .I1(r[%d]), " % (i, np.random.randint(i+1)), file=f) # print(" %s," % random_control(["S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f) # print(" .O(r[%d])" % (i+1), file=f) # print(" );", file=f) print( " assign r[{CCIO_CLKS}-1:0] = i;".format(CCIO_CLKS=CCIO_CLKS), file=f) for i in range(12): print(" BUFGCE_DIV #(", file=f) print(" .BUFGCE_DIVIDE(%d)," % np.random.randint(1, 9), file=f) print(" %s" % random_inversion(["I", "CE", "CLR"]), file=f) print(" ) bufgce_div_%d (" % i, file=f) print(" .I(i[%d])," % i, file=f) print(" %s," % random_control(["CE", "CLR"]), file=f) print(" .O(r[%d])" % (CCIO_CLKS + i), file=f) print(" );", file=f) for i in range(12): print(" BUFGCE #(", file=f) print( " .CE_TYPE(\"%s\")," % np.random.choice(["SYNC", "ASYNC"]), file=f) print(" %s" % random_inversion(["I", "CE"]), file=f) print(" ) bufgce_%d (" % i, file=f) print(" .I(i[%d])," % np.random.randint(CCIO_CLKS), file=f) print(" %s," % random_control(["CE"]), file=f) print(" .O(r[%d])" % (i + 36), file=f) print(" );", file=f) R2 = 0 NS = 64 ffs = "" for row, hcs in sorted(halfcolumn_slices_by_row.items()): row_clks = np.random.randint(20, 25) clks = [np.random.randint(48) for k in range(row_clks)] samples = min(len(hcs), NS) hi = np.random.choice(range(len(hcs)), size=samples, replace=False) halfs = [hcs[hi[k]] for k in range(samples)] for h in halfs: half_clks = np.random.randint(13, 17) rclks = [np.random.choice(clks) for k in range(half_clks)] for sl in h: ffs += "(* LOC=\"%s\" *) FDCE ff_%d (.C(r[%d]), .CE(aux[%d]), .CLR(~aux[%d]), .D(r2[%d]), .Q(r2[%d]));\n" % ( sl, R2, rclks[R2 % len(rclks)], np.random.randint(10), np.random.randint(10), R2, R2 + 1) R2 += 1 print(" wire [%d:0] r2;" % R2, file=f) print(" assign r2[0] = d;", file=f) print(" assign q = r2[%d];" % R2, file=f) print(ffs, file=f) print("endmodule", file=f) with open("top.tcl", "w") as f: print('opt_design', file=f)
def main(): parser = argparse.ArgumentParser( description= "Reduces raw database dump into prototype tiles, grid, and connections." ) parser.add_argument('--root_dir', required=True) parser.add_argument('--output_dir', required=True) parser.add_argument('--verify_only', action='store_true') parser.add_argument('--ignored_wires') parser.add_argument('--max_cpu', type=int, default=10) args = parser.parse_args() now = datetime.datetime.now tiles, nodes = lib.read_root_csv(args.root_dir) processes = min(multiprocessing.cpu_count(), args.max_cpu) print('{} Running {} processes'.format(now(), processes)) pool = multiprocessing.Pool(processes=processes) tileconn_file = os.path.join(args.output_dir, 'tileconn.json') wire_map_file = os.path.join(args.output_dir, 'wiremap.pickle') print('{} Reading tilegrid'.format(now())) with open( os.path.join(util.get_db_root(), util.get_part(), 'tilegrid.json')) as f: grid = json.load(f) if not args.verify_only: print('{} Creating tile map'.format(now())) grid2, wire_map = generate_tilegrid(pool, tiles) # Make sure tilegrid from 005-tilegrid matches tilegrid from # generate_tilegrid. db_grid_keys = set(grid.keys()) generated_grid_keys = set(grid2.keys()) assert db_grid_keys == generated_grid_keys, (db_grid_keys ^ generated_grid_keys) for tile in db_grid_keys: for k in grid2[tile]: assert k in grid[tile], k assert grid[tile][k] == grid2[tile][k], (tile, k, grid[tile][k], grid2[tile][k]) print('{} Estimating tile sizes'.format(now())) tile_type_sizes = tile_sizes.guess_tile_type_sizes(grid) with open(wire_map_file, 'wb') as f: pickle.dump(wire_map, f) print('{} Creating tile connections'.format(now())) tileconn, raw_node_data = generate_tileconn(pool, nodes, wire_map, grid, tile_type_sizes) for data in tileconn: data['wire_pairs'] = tuple( sorted(data['wire_pairs'], key=lambda x: tuple(extract_numbers(s) for s in x))) tileconn = tuple( sorted(tileconn, key=lambda x: (x['tile_types'], x['grid_deltas']))) print('{} Writing tileconn'.format(now())) with open(tileconn_file, 'w') as f: json.dump(tileconn, f, indent=2, sort_keys=True) else: with open(wire_map_file, 'rb') as f: wire_map = pickle.load(f) print('{} Reading raw_node_data'.format(now())) raw_node_data = [] for node_file in progressbar.progressbar(nodes): with open(node_file) as f: raw_node_data.extend(json.load(f)[:-1]) print('{} Reading tileconn'.format(now())) with open(tileconn_file) as f: tileconn = json.load(f) wire_nodes_file = os.path.join(args.output_dir, 'wire_nodes.pickle') if os.path.exists(wire_nodes_file) and args.verify_only: with open(wire_nodes_file, 'rb') as f: wire_nodes = pickle.load(f) else: print("{} Connecting wires to verify tileconn".format(now())) wire_nodes = connect_wires(grid, tileconn, wire_map) with open(wire_nodes_file, 'wb') as f: pickle.dump(wire_nodes, f) print('{} Verifing tileconn'.format(now())) error_nodes = [] lib.verify_nodes( [(node['node'], tuple(wire['wire'] for wire in node['wires'][:-1])) for node in raw_node_data], wire_nodes, error_nodes) if len(error_nodes) > 0: error_nodes_file = os.path.join(args.output_dir, 'error_nodes.json') with open(error_nodes_file, 'w') as f: json.dump(error_nodes, f, indent=2, sort_keys=True) ignored_wires = [] ignored_wires_file = args.ignored_wires if os.path.exists(ignored_wires_file): with open(ignored_wires_file) as f: ignored_wires = set(l.strip() for l in f) if not lib.check_errors(error_nodes, ignored_wires): print('{} errors detected, see {} for details.'.format( len(error_nodes), error_nodes_file)) sys.exit(1) else: print( '{} errors ignored because of {}\nSee {} for details.'.format( len(error_nodes), ignored_wires_file, error_nodes_file))
def print_top(seed): np.random.seed(seed) db = Database(util.get_db_root(), util.get_part()) grid = db.grid() clocks = ClockColumns(grid) disabled_columns = set() for key in clocks.columns(): if np.random.choice([1, 0], p=[.25, .75]): disabled_columns.add(key) clocks.remove_column(disabled_columns) site_to_site_type = {} site_to_tile = {} 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(): site_to_site_type[site] = site_type site_to_tile[site] = tile_name bufgs = GlobalClockBuffers('../bufg_outputs.csv') slices = sorted(gen_sites(grid)) np.random.shuffle(slices) with open('complete_top.tcl', 'w') as f: #print('place_design -directive Quick', file=f) print(""" set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets] place_design route_design """, file=f) print(""" module top(); """) N_LUTS = 4 ce_inputs = [0, 1] for idx in range(N_LUTS): print(""" wire lut_o_{idx}; (* BEL="A6LUT", LOC="{loc}", KEEP, DONT_TOUCH *) LUT5 lut{idx} (.O(lut_o_{idx})); """.format(idx=idx, loc=slices.pop())) ce_inputs.append('lut_o_{}'.format(idx)) N_GCLK = 1 bufg_wires = {} bufg_str = {} for idx in range(N_GCLK): bufg, hroute_number = bufgs.random_bufg(np.random.choice) site_type = site_to_site_type[bufg] if site_type in ['BUFGCE', 'BUFGCE_HDIO']: s = """ wire bufg_o_{idx}; (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFGCE #( .IS_CE_INVERTED({invert_ce}), .CE_TYPE("{ce_type}") ) bufg_{idx} ( .CE({ce}), .O(bufg_o_{idx}) );""".format(loc=bufg, idx=idx, invert_ce=np.random.randint(2), ce_type=np.random.choice(["SYNC", "ASYNC"]), ce=np.random.choice(ce_inputs)) elif site_type == 'BUFGCE_DIV': s = """ wire bufg_o_{idx}; (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFGCE_DIV #( .IS_CE_INVERTED({invert_ce}), .CE_TYPE("{ce_type}"), .BUFGCE_DIVIDE({bufce_divide}) ) bufg_{idx} ( .CE({ce}), .CLR({clr}), .O(bufg_o_{idx}) );""".format(loc=bufg, idx=idx, invert_ce=np.random.randint(2), ce_type=np.random.choice(["SYNC", "ASYNC"]), ce=np.random.choice(ce_inputs), clr=np.random.choice(ce_inputs), bufce_divide=np.random.choice(range(1, 9))) elif site_type == 'BUFG_PS': s = """ wire bufg_o_{idx}; (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFG_PS #( ) bufg_{idx} ( .O(bufg_o_{idx}) );""".format(loc=bufg, idx=idx) elif site_type == 'BUFGCTRL': preselect_i0 = np.random.randint(2) if not preselect_i0: preselect_i1 = np.random.randint(2) else: preselect_i1 = 0 s0 = np.random.choice(ce_inputs) s1 = np.random.choice(ce_inputs) if s0 == '0': while s1 == '0': s1 = np.random.choice(ce_inputs) if s0 == '0' and s1 == '1': invert_s0 = np.random.randint(2) invert_s1 = 0 elif s0 == '1' and s1 == '0': invert_s1 = np.random.randint(2) invert_s0 = 0 elif s0 == '1' and s1 == '1': invert_s0 = np.random.randint(2) if invert_s0: invert_s1 = 0 else: invert_s0 = np.random.randint(2) invert_s1 = np.random.randint(2) s = """ wire bufg_o_{idx}; (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFGCTRL #( .INIT_OUT({init_out}), .IS_CE0_INVERTED({invert_ce0}), .IS_CE1_INVERTED({invert_ce1}), .IS_S0_INVERTED({invert_s0}), .IS_S1_INVERTED({invert_s1}), .IS_IGNORE0_INVERTED({invert_ignore0}), .IS_IGNORE1_INVERTED({invert_ignore1}), .PRESELECT_I0({preselect_i0}), .PRESELECT_I1({preselect_i1}) ) bufg_{idx} ( .IGNORE0({ignore0}), .IGNORE1({ignore1}), .S0({s0}), .S1({s1}), .CE0({ce0}), .CE1({ce1}), .O(bufg_o_{idx}) );""".format( loc=bufg, idx=idx, init_out=np.random.randint(2), s0=s0, s1=s1, ce0=np.random.choice(ce_inputs), ce1=np.random.choice(ce_inputs), ignore0=np.random.choice(ce_inputs), ignore1=np.random.choice(ce_inputs), invert_ce0=np.random.randint(2), invert_ce1=np.random.randint(2), invert_s0=invert_s0, invert_s1=invert_s1, invert_ignore0=np.random.randint(2), invert_ignore1=np.random.randint(2), preselect_i0=preselect_i0, preselect_i1=preselect_i1, ) else: assert False, site_type bufg_wires[hroute_number] = 'bufg_o_{idx}'.format(idx=idx) bufg_str[hroute_number] = s bufg_used = set() slices = sorted(clocks.sites.keys()) num_slices = np.random.randint(1, len(slices) + 1) for idx, slice_loc in enumerate(slices): if idx >= num_slices: break all_clocks = list(bufg_wires.keys()) np.random.shuffle(all_clocks) while True: hroute_number = all_clocks.pop() clock_str = bufg_wires[hroute_number] if clocks.add_clock(slice_loc, clock_str): if hroute_number not in bufg_used: print(bufg_str[hroute_number]) bufg_used.add(hroute_number) print( ' (* LOC="{loc}", KEEP, DONT_TOUCH *) FDCE ff_{i}(.C({clock_str}));' .format(loc=slice_loc, i=idx, clock_str=clock_str)) break print('endmodule')
def print_top(seed): np.random.seed(seed) options_by_tile = {} with open('../permutations.csv') as f: for row in csv.DictReader(f): tile = row['tile'] opt = {} for bufg_idx in range(MAX_GLOBAL_CLOCKS): input_idx = row['bufg{}_input'.format(bufg_idx)] if input_idx == "": continue opt[bufg_idx] = int(input_idx) if tile not in options_by_tile: options_by_tile[tile] = [] options_by_tile[tile].append(opt) ps8_pins = sorted(get_ps8_pin_map()) bus_widths = {} for pin in ps8_pins: parts = pin.split('/')[-1].split('[') if len(parts) == 1: bus_widths[parts[0]] = 1 elif len(parts) == 2: if parts[0] not in bus_widths: bus_widths[parts[0]] = 0 width = int(parts[1][:-1]) + 1 if width > bus_widths[parts[0]]: bus_widths[parts[0]] = width else: assert False, pin tiles = ps8_bufg_pin_map_by_tile() for tile in tiles: tiles[tile].sort() db = Database(util.get_db_root(), util.get_part()) grid = db.grid() bufgs_by_tile = {} for tile in tiles: bufgs_by_tile[tile] = [] gridinfo = grid.gridinfo_at_tilename(tile) for site, site_type in gridinfo.sites.items(): if site_type == 'BUFG_PS': bufgs_by_tile[tile].append(site) for tile in tiles: bufgs_by_tile[tile].sort() assert len(bufgs_by_tile[tile]) == MAX_GLOBAL_CLOCKS, tile opins = [] sinks = [] print(''' module top(); ''') spec_num = util.specn() - 1 for tile in tiles: opts = options_by_tile[tile] if spec_num < len(opts): # Use permutation from permutations.csv opt = opts[spec_num] else: # Use a random permutation. opt = {} bufgs = set(range(MAX_GLOBAL_CLOCKS)) for input_idx in range(len(tiles[tile])): bufg_idx = np.random.choice(sorted(bufgs)) bufgs.remove(bufg_idx) opt[bufg_idx] = input_idx for bufg_idx, input_idx in opt.items(): bufg = bufgs_by_tile[tile][bufg_idx] input_pin = tiles[tile][input_idx] idx = len(opins) print(""" wire bufg_{idx}; (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFG_PS bufg_{idx} ( .I(bufg_{idx}) ); """.format(loc=bufg, idx=idx)) sinks.append('bufg_{idx}'.format(idx=idx)) opins.append(input_pin) busses = set() for pin in opins: busses.add(pin.split('[')[0]) for bus in busses: print('wire [{width}-1:0] {bus};'.format( bus=bus, width=bus_widths[bus])) print('PS8 ps8 (') connections = [] for bus in busses: connections.append(' .{bus}({bus})'.format(bus=bus)) print(',\n'.join(connections)) print('\n);') for pin, sink in zip(opins, sinks): print('assign {sink} = {pin};'.format(pin=pin, sink=sink)) print('endmodule')
def gen_sites(): """ RCLK_DSP_INTF_CLKBUF_L connects HDISTR and HROUTE clock resources from neighbooring left/right clock regions. gen_sites finds RCLK_DSP_INTF_CLKBUF_L tiles, and then locates a BUFCE_ROW driver from the left side, and then finds a BUFCE_ROW driver from the right side that drives the same HDISTR. A BUFCE_ROW only drives a particular HDISTR node within the clock region (0-23). A random BUFCE_LEAF from both the left and the right of RCLK_DSP_INTF_CLKBUF_L are chosen. This randomness decouples non-RCLK_DSP_INTF_CLKBUF_L bits from the solution. """ db = Database(util.get_db_root(), util.get_part()) grid = db.grid() # Create a mapping from site to tile site_to_tile = {} for tile_name in grid.tiles(): loc = grid.loc_of_tilename(tile_name) gridinfo = grid.gridinfo_at_loc(loc) for site in gridinfo.sites: site_to_tile[site] = tile_name # Load BUFCE_ROW site data, which includes: # - The BUFCE_ROW site name # - The clock region the BUFCE_ROW participates in # - Which HDISTR wire is driven by the BUFCE_ROW. loc_to_bufce_row = {} with open('../active_bufce_row.csv') as f: for bufce_row in csv.DictReader(f): site = bufce_row['site'] tile = site_to_tile[site] loc = grid.loc_of_tilename(tile) if loc not in loc_to_bufce_row: loc_to_bufce_row[loc] = [] loc_to_bufce_row[loc].append(bufce_row) o = [] for tile_name in sorted(grid.tiles()): loc = grid.loc_of_tilename(tile_name) gridinfo = grid.gridinfo_at_loc(loc) if gridinfo.tile_type != "RCLK_DSP_INTF_CLKBUF_L": continue # Find a BUFCE_ROW driver that is left of the current # RCLK_DSP_INTF_CLKBUF_L tile. x, y = loc left_bufce_out = None hdistr_number = None while left_bufce_out is None: x -= 1 if (x, y) in loc_to_bufce_row: left_bufce_out = loc_to_bufce_row[(x, y)][0]['site'] hdistr_number = loc_to_bufce_row[(x, y)][0]['hdistr_number'] break # Find a BUFCE_ROW driver that is right of the current # RCLK_DSP_INTF_CLKBUF_L tile, and is on the same HDISTR wire. x, y = loc right_bufce_out = None while right_bufce_out is None: x += 1 if (x, y) in loc_to_bufce_row: for bufce_row in loc_to_bufce_row[(x, y)]: if hdistr_number == bufce_row['hdistr_number']: right_bufce_out = bufce_row['site'] break # Find a random BUFCE_LEAF driver that is to the left of the current # RCLK_DSP_INTF_CLKBUF_L. x, y = loc left_site = None while left_site is None: x -= 1 gridinfo = grid.gridinfo_at_loc((x, y)) for site, site_type in gridinfo.sites.items(): if site_type == 'BUFCE_LEAF': left_site = get_random_leaf(gridinfo) break # Find a random BUFCE_LEAF driver that is to the right of the current # RCLK_DSP_INTF_CLKBUF_L. x, y = loc right_site = None while right_site is None: x += 1 gridinfo = grid.gridinfo_at_loc((x, y)) for site, site_type in gridinfo.sites.items(): if site_type == 'BUFCE_LEAF': right_site = get_random_leaf(gridinfo) break assert left_bufce_out is not None assert right_bufce_out is not None assert left_site is not None assert right_site is not None o.append((tile_name, left_bufce_out, right_bufce_out, left_site, right_site)) return o
def print_top(seed): np.random.seed(seed) db = Database(util.get_db_root(), util.get_part()) grid = db.grid() site_to_tile = {} site_to_site_type = {} 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(): site_to_site_type[site] = site_type site_to_tile[site] = tile_name bufce_row_drivers = {} with open('../active_bufce_row.csv') as f: for row in csv.DictReader(f): tile = site_to_tile[row['site']] gridinfo = grid.gridinfo_at_tilename(tile) if gridinfo.tile_type == 'CMT_RIGHT': continue clock_region = CMT_XY_FUN(row['site_clock_region']) key = clock_region, int(row['hdistr_number']) assert key not in bufce_row_drivers bufce_row_drivers[key] = row['site'] bufg_drivers = {} with open('../bufg_outputs.csv') as f: for row in csv.DictReader(f): if site_to_site_type[row['site']] != 'BUFGCE_HDIO': continue clock_region = CMT_XY_FUN(row['clock_region']) if clock_region not in bufg_drivers: bufg_drivers[clock_region] = [] bufg_drivers[clock_region].append(row['site']) for clock_region in bufg_drivers: bufg_drivers[clock_region].sort() np.random.shuffle(bufg_drivers[clock_region]) clock_regions = set() for clock_region, _ in bufce_row_drivers.keys(): clock_regions.add(clock_region) for clock_region in bufg_drivers.keys(): clock_regions.add(clock_region) print(""" module top(); """) bufg_routes = [] for hroute in range(MAX_GLOBAL_CLOCKS): if np.random.randint(2): continue select_clock_regions = sorted(clock_regions) np.random.shuffle(select_clock_regions) bufg = None while len(select_clock_regions) > 0: clock_region = select_clock_regions.pop() if clock_region not in bufg_drivers: continue if len(bufg_drivers[clock_region]) > 0: bufg = bufg_drivers[clock_region].pop() break if bufg is None: continue sel_x, sel_y = clock_region clock_regions_for_bufg = [] for x, y in clock_regions: if y == sel_y: clock_regions_for_bufg.append((x, y)) clock_regions_for_bufg.sort() np.random.shuffle(clock_regions_for_bufg) bufce_row = None while True: clock_region = clock_regions_for_bufg.pop() key = clock_region, hroute if key in bufce_row_drivers: bufce_row = bufce_row_drivers[key] break if bufce_row is None: continue bufg_s, bufg_o_wire = make_bufg( site=bufg, site_type=site_to_site_type[bufg], idx=hroute, ce_inputs=['1'], randlib=np.random) print(bufg_s) print(""" (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFCE_ROW row{idx} ( .I({bufg_o_wire}) );""".format( loc=bufce_row, idx=hroute, bufg_o_wire=bufg_o_wire, )) bufg_routes.append((bufg, bufce_row, hroute)) print('endmodule') with open('complete_top.tcl', 'w') as f: print( """ source $::env(URAY_UTILS_DIR)/utils.tcl write_checkpoint -force design_reset.dcp close_design open_checkpoint design_reset.dcp """, file=f) for bufg, bufce_row, hroute in bufg_routes: if np.random.randint(2): print( "route_bufg_to_bufce_row_via_opposite_wire {bufg} {bufce_row} {hroute}" .format(bufg=bufg, bufce_row=bufce_row, hroute=hroute), file=f) print(""" route_design """, file=f)
def print_top(seed): np.random.seed(seed) db = Database(util.get_db_root(), util.get_part()) grid = db.grid() clocks = ClockColumns(grid) disabled_columns = set() for key in clocks.columns(): if np.random.choice([1, 0], p=[.25, .75]): disabled_columns.add(key) clocks.remove_column(disabled_columns) site_to_site_type = {} site_to_tile = {} 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(): site_to_site_type[site] = site_type site_to_tile[site] = tile_name bufgs = GlobalClockBuffers('../bufg_outputs.csv') slices = sorted(gen_sites(grid)) np.random.shuffle(slices) with open('complete_top.tcl', 'w') as f: print(""" set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets] place_design route_design """, file=f) print(""" module top(); """) N_LUTS = 4 ce_inputs = [0, 1] for idx in range(N_LUTS): print(""" wire lut_o_{idx}; (* BEL="A6LUT", LOC="{loc}", KEEP, DONT_TOUCH *) LUT5 lut{idx} (.O(lut_o_{idx})); """.format(idx=idx, loc=slices.pop())) ce_inputs.append('lut_o_{}'.format(idx)) N_GCLK = np.random.randint(1, MAX_GLOBAL_CLOCKS) assert N_GCLK <= MAX_GLOBAL_CLOCKS assert N_GCLK >= 1 bufg_wires = {} bufg_str = {} for idx in range(N_GCLK): bufg, hroute_number = bufgs.random_bufg(np.random.choice) site_type = site_to_site_type[bufg] bufg_str[hroute_number], bufg_wires[hroute_number] = make_bufg( bufg, site_type, idx, ce_inputs, np.random) bufg_used = set() slices = sorted(clocks.sites.keys()) num_slices = np.random.randint(1, len(slices) + 1) for idx, slice_loc in enumerate(slices): if idx >= num_slices: break all_clocks = list(bufg_wires.keys()) np.random.shuffle(all_clocks) while True: hroute_number = all_clocks.pop() clock_str = bufg_wires[hroute_number] if clocks.add_clock(slice_loc, clock_str): if hroute_number not in bufg_used: print(bufg_str[hroute_number]) bufg_used.add(hroute_number) print( ' (* LOC="{loc}", KEEP, DONT_TOUCH *) FDCE ff_{i}(.C({clock_str}));' .format(loc=slice_loc, i=idx, clock_str=clock_str)) break print('endmodule')
def print_top(seed): np.random.seed(seed) db = Database(util.get_db_root(), util.get_part()) grid = db.grid() site_to_tile = {} site_to_site_type = {} 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(): site_to_site_type[site] = site_type site_to_tile[site] = tile_name bufce_leaf_drivers = {} with open('../bufce_leaf_clock_regions.csv') as f: for row in csv.DictReader(f): clock_region = CMT_XY_FUN(row['clock_region']) if clock_region not in bufce_leaf_drivers: bufce_leaf_drivers[clock_region] = [] bufce_leaf_drivers[clock_region].append(row['site']) for clock_region in bufce_leaf_drivers: bufce_leaf_drivers[clock_region].sort() np.random.shuffle(bufce_leaf_drivers[clock_region]) bufg_drivers = {} with open('../bufg_outputs.csv') as f: for row in csv.DictReader(f): if site_to_site_type[row['site']] != 'BUFGCE_HDIO': continue clock_region = CMT_XY_FUN(row['clock_region']) if clock_region not in bufg_drivers: bufg_drivers[clock_region] = [] bufg_drivers[clock_region].append(row['site']) for clock_region in bufg_drivers: bufg_drivers[clock_region].sort() np.random.shuffle(bufg_drivers[clock_region]) clock_regions = set() for clock_region in bufg_drivers.keys(): clock_regions.add(clock_region) print(""" module top(); """) pair_idx = 0 bufg_hdistr_sets = [] for clock_region in bufg_drivers.keys(): hdistrs_avail = list(range(MAX_GLOBAL_CLOCKS)) np.random.shuffle(hdistrs_avail) for bufg in bufg_drivers[clock_region]: hdistr = hdistrs_avail.pop() bufg_s, bufg_o_wire = make_bufg(site=bufg, site_type=site_to_site_type[bufg], idx=pair_idx, ce_inputs=['1'], randlib=np.random) print(bufg_s) bufce_leaf = bufce_leaf_drivers[clock_region].pop() print(""" (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFCE_LEAF bufce_leaf_{idx} ( .I({clock_in}) );""".format(loc=bufce_leaf, idx=pair_idx, clock_in=bufg_o_wire)) bufg_hdistr_sets.append((bufg, bufce_leaf, hdistr)) pair_idx += 1 print('endmodule') with open('complete_top.tcl', 'w') as f: print(""" source $::env(URAY_UTILS_DIR)/utils.tcl write_checkpoint -force design_reset.dcp close_design open_checkpoint design_reset.dcp """, file=f) for (bufg, bufce_leaf, hdistr) in bufg_hdistr_sets: print( 'route_bufg_to_bufce_leaf {bufg} {bufce_leaf} {hdistr}'.format( bufg=bufg, bufce_leaf=bufce_leaf, hdistr=hdistr), file=f) print(""" route_design """, file=f)