def main(): """ HCLK_IOI has the following inputs: 12 (east) BUFH from the right side of the HROW 12 (west) Bounce PIPs from one BUFH to any of 6 GCLK_BOT and 6 GCLK_TOP 4 (east) PHSR_PERFCLK (IOCLK_PLL) from HCLK_CLB to input of BUFIO 8 (4 north and 4 south) BUFR CLR and CE 2 (south) I2IOCLK to input of BUFR 2 (north) I2IOCLK to input of BUFR 2 RCLK IMUX (IMUX0 and IMUX1) choosing input of BUFR outputs: 4 (east) BUFRCLK - from BUFR to HROW 4 (north) BUFR2IO - from BUFR 4 (north) IOCLK from BUFIO """ global_clock_sources = ClockSources() cmt_clock_sources = ClockSources() cmt_fast_clock_sources = ClockSources(4) bufr_clock_sources = ClockSources() bufio_clock_sources = ClockSources() site_to_cmt = dict(read_site_to_cmt()) clock_region_limit = dict() clock_region_serdes_location = dict() db = Database(util.get_db_root(), util.get_part()) grid = db.grid() def gen_sites(desired_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(): if site_type == desired_site_type: yield tile_name, site def serdes_relative_location(tile, site): (serdes_loc_x, serdes_loc_y) = grid.loc_of_tilename(tile) serdes_clk_reg = site_to_cmt[site] for tile_name in sorted(grid.tiles()): if 'HCLK_IOI3' in tile_name: (hclk_tile_loc_x, hclk_tile_loc_y) = grid.loc_of_tilename(tile_name) if hclk_tile_loc_x == serdes_loc_x: gridinfo = grid.gridinfo_at_loc( (hclk_tile_loc_x, hclk_tile_loc_y)) random_site = next(iter(gridinfo.sites.keys())) hclk_clk_reg = site_to_cmt[random_site] if hclk_clk_reg == serdes_clk_reg: if serdes_loc_y < hclk_tile_loc_y: return "TOP" elif serdes_loc_y > hclk_tile_loc_y: return "BOTTOM" else: assert False clock_region_sites = set() def get_clock_region_site(site_type, clk_reg): for site_name, reg in site_to_cmt.items(): if site_name.startswith(site_type) and reg in clk_reg: if site_name not in clock_region_sites: clock_region_sites.add(site_name) return site_name print(''' module top(); (* KEEP, DONT_TOUCH *) LUT6 dummy(); ''') luts = LutMaker() bufs = StringIO() for _, site in gen_sites('MMCME2_ADV'): mmcm_clocks = [ 'mmcm_clock_{site}_{idx}'.format(site=site, idx=idx) for idx in range(13) ] for idx, clk in enumerate(mmcm_clocks): if idx < 4: cmt_fast_clock_sources.add_clock_source(clk, site_to_cmt[site]) else: cmt_clock_sources.add_clock_source(clk, site_to_cmt[site]) print(""" wire cin1_{site}, cin2_{site}, clkfbin_{site}, {c0}, {c1}, {c2}, {c3}, {c4}, {c5}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) MMCME2_ADV pll_{site} ( .CLKIN1(cin1_{site}), .CLKIN2(cin2_{site}), .CLKFBIN(clkfbin_{site}), .CLKOUT0({c0}), .CLKOUT0B({c4}), .CLKOUT1({c1}), .CLKOUT1B({c5}), .CLKOUT2({c2}), .CLKOUT2B({c6}), .CLKOUT3({c3}), .CLKOUT3B({c7}), .CLKOUT4({c8}), .CLKOUT5({c9}), .CLKOUT6({c10}), .CLKFBOUT({c11}), .CLKFBOUTB({c12}) ); """.format( site=site, c0=mmcm_clocks[0], c1=mmcm_clocks[1], c2=mmcm_clocks[2], c3=mmcm_clocks[3], c4=mmcm_clocks[4], c5=mmcm_clocks[5], c6=mmcm_clocks[6], c7=mmcm_clocks[7], c8=mmcm_clocks[8], c9=mmcm_clocks[9], c10=mmcm_clocks[10], c11=mmcm_clocks[11], c12=mmcm_clocks[12], )) for _, site in gen_sites('PLLE2_ADV'): pll_clocks = [ 'pll_clock_{site}_{idx}'.format(site=site, idx=idx) for idx in range(7) ] for clk in pll_clocks: cmt_clock_sources.add_clock_source(clk, site_to_cmt[site]) print(""" wire cin1_{site}, cin2_{site}, clkfbin_{site}, {c0}, {c1}, {c2}, {c3}, {c4}, {c5}, {c6}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) PLLE2_ADV pll_{site} ( .CLKIN1(cin1_{site}), .CLKIN2(cin2_{site}), .CLKFBIN(clkfbin_{site}), .CLKOUT0({c0}), .CLKOUT1({c1}), .CLKOUT2({c2}), .CLKOUT3({c3}), .CLKOUT4({c4}), .CLKOUT5({c5}), .CLKFBOUT({c6}) ); """.format( site=site, c0=pll_clocks[0], c1=pll_clocks[1], c2=pll_clocks[2], c3=pll_clocks[3], c4=pll_clocks[4], c5=pll_clocks[5], c6=pll_clocks[6], )) for tile_name, site in gen_sites('BUFHCE'): print(""" wire I_{site}; wire O_{site}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFHCE buf_{site} ( .I(I_{site}), .O(O_{site}) );""".format(site=site), file=bufs) global_clock_sources.add_clock_source('O_{site}'.format(site=site), site_to_cmt[site]) hclks_used_by_clock_region = {} for cmt in site_to_cmt.values(): hclks_used_by_clock_region[cmt] = set() def check_hclk_src(src, src_cmt): if len(hclks_used_by_clock_region[src_cmt] ) >= 12 and src not in hclks_used_by_clock_region[src_cmt]: return None else: hclks_used_by_clock_region[src_cmt].add(src) return src cmt_clks_used_by_clock_region = {} for cmt in site_to_cmt.values(): cmt_clks_used_by_clock_region[cmt] = list() def check_cmt_clk_src(src, src_clock_region): print("//src: {}, clk_reg: {}, len {}".format( src, src_clock_region, len(cmt_clks_used_by_clock_region[src_clock_region]))) if len(cmt_clks_used_by_clock_region[src_clock_region]) >= 4: return None else: cmt_clks_used_by_clock_region[src_clock_region].append(src) return src #Add IDELAYCTRL idelayctrl_in_clock_region = {} for cmt in site_to_cmt.values(): idelayctrl_in_clock_region[cmt] = False for _, site in gen_sites('IDELAYCTRL'): if random.random() < 0.5: wire_name = global_clock_sources.get_random_source( site_to_cmt[site], no_repeats=False) if wire_name is None: continue src_cmt = global_clock_sources.source_to_cmt[wire_name] wire_name = check_hclk_src(wire_name, src_cmt) if wire_name is None: continue idelayctrl_in_clock_region[src_cmt] = True print(""" assign I_{site} = {clock_source}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) IDELAYCTRL idelay_ctrl_{site} ( .RDY(), .REFCLK(I_{site}), .RST() );""".format(site=site, clock_source=wire_name)) # Add SERDES driven by BUFH or MMCM for tile, site in gen_sites('ILOGICE3'): wire_name = None clock_region = site_to_cmt[site] if clock_region not in clock_region_limit: # Select serdes limit and relative location per clock region serdes_location = random.choice(["TOP", "BOTTOM", "ANY"]) if serdes_location in "ANY": #We want TOP and BOTTOM IGCLK PIPs occupied but leave one slot for IDELAYCTRL if idelayctrl_in_clock_region[clock_region]: clock_region_limit[clock_region] = 0 if random.random( ) < 0.2 else 11 else: clock_region_limit[clock_region] = 0 if random.random( ) < 0.2 else 12 else: if idelayctrl_in_clock_region[clock_region]: clock_region_limit[clock_region] = 0 if random.random( ) < 0.2 else 5 else: clock_region_limit[clock_region] = 0 if random.random( ) < 0.2 else 6 clock_region_serdes_location[clock_region] = serdes_location # We reached the limit of hclks in this clock region if clock_region_limit[clock_region] == 0: continue # Add a serdes if it's located at the correct side from the HCLK_IOI tile if clock_region_serdes_location[clock_region] not in "ANY" and \ serdes_relative_location(tile, site) != clock_region_serdes_location[clock_region]: continue if random.random() > 0.1: wire_name = global_clock_sources.get_random_source( site_to_cmt[site], no_repeats=True) if wire_name is None: continue src_cmt = global_clock_sources.source_to_cmt[wire_name] wire_name = check_hclk_src(wire_name, src_cmt) if wire_name is None: print("//wire is None") continue clock_region_limit[clock_region] -= 1 print(""" assign serdes_clk_{site} = {clock_source};""".format( site=site, clock_source=wire_name)) else: wire_name = cmt_fast_clock_sources.get_random_source( site_to_cmt[site], no_repeats=False) if wire_name is None: continue src_cmt = cmt_fast_clock_sources.source_to_cmt[wire_name] wire_name = check_cmt_clk_src(wire_name, src_cmt) if wire_name is None: continue bufio_site = get_clock_region_site("BUFIO", clock_region) if bufio_site is None: continue print(""" assign serdes_clk_{serdes_loc} = O_{site}; assign I_{site} = {clock_source}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFIO bufio_{site} ( .O(O_{site}), .I(I_{site}) );""".format(site=bufio_site, clock_source=wire_name, serdes_loc=site)) print("// clock_region: {} {}".format( clock_region, clock_region_serdes_location[clock_region])) print(""" (* KEEP, DONT_TOUCH, LOC = "{loc}" *) ISERDESE2 #( .DATA_RATE("SDR"), .DATA_WIDTH(4), .DYN_CLKDIV_INV_EN("FALSE"), .DYN_CLK_INV_EN("FALSE"), .INIT_Q1(1'b0), .INIT_Q2(1'b0), .INIT_Q3(1'b0), .INIT_Q4(1'b0), .INTERFACE_TYPE("OVERSAMPLE"), .IOBDELAY("NONE"), .NUM_CE(2), .OFB_USED("FALSE"), .SERDES_MODE("MASTER"), .SRVAL_Q1(1'b0), .SRVAL_Q2(1'b0), .SRVAL_Q3(1'b0), .SRVAL_Q4(1'b0) ) ISERDESE2_inst_{loc} ( .CLK(serdes_clk_{loc}), .CLKB(), .CLKDIV(), .D(1'b0), .DDLY(), .OFB(), .OCLKB(), .RST(), .SHIFTIN1(), .SHIFTIN2() ); """.format(loc=site, clock_source=wire_name)) # BUFRs for _, site in gen_sites('BUFR'): if random.random() < 0.6: if random.random() < 0.5: wire_name = luts.get_next_output_net() else: wire_name = cmt_fast_clock_sources.get_random_source( site_to_cmt[site], no_repeats=False) if wire_name is None: continue src_cmt = cmt_fast_clock_sources.source_to_cmt[wire_name] wire_name = check_cmt_clk_src(wire_name, src_cmt) if wire_name is None: continue bufr_clock_sources.add_clock_source('O_{site}'.format(site=site), site_to_cmt[site]) # Add DIVIDE divide = "BYPASS" if random.random() < 0.5: divide = "".format(random.randint(2, 8)) print(""" assign I_{site} = {clock_source}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFR #(.BUFR_DIVIDE("{divide}")) bufr_{site} ( .O(O_{site}), .I(I_{site}) );""".format(site=site, clock_source=wire_name, divide=divide), file=bufs) for _, site in gen_sites('MMCME2_ADV'): wire_name = bufr_clock_sources.get_random_source(site_to_cmt[site], no_repeats=True) if wire_name is None: continue print(""" assign cin1_{site} = {wire_name};""".format(site=site, wire_name=wire_name)) print(bufs.getvalue()) for l in luts.create_wires_and_luts(): print(l) print("endmodule")
def main(): print(''' module top( input wire in, output wire out ); assign out = in; ''') luts = LutMaker() params_dict = {"tile_type": None} params_list = list() clkswing_cfg_tiles = dict() ibufds_out_wires = dict() for tile_name, _, site_name, _ in gen_sites("GTP_COMMON", "IBUFDS_GTE2"): # Both the IBUFDS_GTE2 in the same tile need to have # the same CLKSWING_CFG parameter if tile_name not in clkswing_cfg_tiles: clkswing_cfg = random.randint(0, 3) clkswing_cfg_tiles[tile_name] = clkswing_cfg else: clkswing_cfg = clkswing_cfg_tiles[tile_name] in_use = bool(random.randint(0, 9)) params = { "site": site_name, "tile": tile_name, "IN_USE": in_use, "CLKRCV_TRST": verilog.quote("TRUE" if random.randint(0, 1) else "FALSE"), "CLKCM_CFG": verilog.quote("TRUE" if random.randint(0, 1) else "FALSE"), "CLKSWING_CFG": clkswing_cfg, } if in_use: ibufds_out_wire = "{}_O".format(site_name) if tile_name not in ibufds_out_wires: ibufds_out_wires[tile_name] = list() ibufds_out_wires[tile_name].append( (ibufds_out_wire, int(site_name[-1]) % 2)) print("wire {};".format(ibufds_out_wire)) print("(* KEEP, DONT_TOUCH, LOC=\"{}\" *)".format(site_name)) print(""" IBUFDS_GTE2 #( .CLKRCV_TRST({CLKRCV_TRST}), .CLKCM_CFG({CLKCM_CFG}), .CLKSWING_CFG({CLKSWING_CFG}) ) {site} ( .O({out}) );""".format(**params, out=ibufds_out_wire)) params_list.append(params) DRP_PORTS = [("DRPCLK", "clk"), ("DRPEN", "in"), ("DRPWE", "in"), ("DRPRDY", "out")] for tile_name, tile_type, site_name, cmt in gen_sites( "GTP_COMMON", "GTPE2_COMMON"): params_dict["tile_type"] = tile_type params = dict() params['site'] = site_name params['tile'] = tile_name verilog_attr = "" verilog_attr = "#(" fuz_dir = os.getenv("FUZDIR", None) assert fuz_dir with open(os.path.join(fuz_dir, "attrs.json"), "r") as attrs_file: attrs = json.load(attrs_file) in_use = bool(random.randint(0, 9)) params["IN_USE"] = in_use if in_use: for param, param_info in attrs.items(): param_type = param_info["type"] param_values = param_info["values"] param_digits = param_info["digits"] if param_type == INT: value = random.choice(param_values) value_str = value else: assert param_type == BIN value = random.randint(0, param_values[0]) value_str = "{digits}'b{value:0{digits}b}".format( value=value, digits=param_digits) params[param] = value verilog_attr += """ .{}({}),""".format(param, value_str) for param in ["PLL0LOCKDETCLK", "PLL1LOCKDETCLK", "DRPCLK"]: is_inverted = random.randint(0, 1) params[param] = is_inverted verilog_attr += """ .IS_{}_INVERTED({}),""".format(param, is_inverted) verilog_attr = verilog_attr.rstrip(",") verilog_attr += "\n)" verilog_ports = "" for param in [ "GTREFCLK0_USED", "GTREFCLK1_USED", "BOTH_GTREFCLK_USED" ]: params[param] = 0 if tile_name in ibufds_out_wires: gtrefclk_ports_used = 0 for wire, location in ibufds_out_wires[tile_name]: if random.random() < 0.5: continue verilog_ports += """ .GTREFCLK{}({}),""".format(location, wire) gtrefclk_ports_used += 1 params["GTREFCLK{}_USED".format(location)] = 1 if gtrefclk_ports_used == 2: params["BOTH_GTREFCLK_USED"] = 1 enable_drp = random.randint(0, 1) params["ENABLE_DRP"] = enable_drp for _, _, channel_site_name, _ in gen_sites( "GTP_CHANNEL", "GTPE2_CHANNEL", cmt): if not enable_drp: break verilog_ports_channel = "" for port, direction in DRP_PORTS: if direction == "in": verilog_ports_channel += """ .{}({}),""".format(port, luts.get_next_output_net()) elif direction == "clk": # DRPCLK needs to come from a clock source print(""" wire clk_bufg_{site}; (* KEEP, DONT_TOUCH *) BUFG bufg_{site} (.O(clk_bufg_{site}));""".format(site=channel_site_name)) verilog_ports_channel += """ .{}(clk_bufg_{}),""".format(port, channel_site_name) elif direction == "out": verilog_ports_channel += """ .{}({}),""".format(port, luts.get_next_input_net()) print(""" (* KEEP, DONT_TOUCH, LOC=\"{site}\" *) GTPE2_CHANNEL {site} ( {ports} );""".format(ports=verilog_ports_channel.rstrip(","), site=channel_site_name)) print(""" (* KEEP, DONT_TOUCH, LOC=\"{site}\" *) GTPE2_COMMON {attrs} {site} ( {ports} );""".format(attrs=verilog_attr, ports=verilog_ports.rstrip(","), site=site_name)) params_list.append(params) for l in luts.create_wires_and_luts(): print(l) print("endmodule") params_dict["params"] = params_list with open('params.json', 'w') as f: json.dump(params_dict, f, indent=2)
def main(): params_list = [] num_clocks = 0 outputs = [] luts = LutMaker() for tile_name, x_min, y_min, sites, iobs in gen_sites(): ioclks = [] for iob in iobs: ioclk = 'clk_{}'.format(iob) ioclks.append(ioclk) idx = num_clocks num_clocks += 1 outputs.append(''' wire {ioclk}; (* KEEP, DONT_TOUCH, LOC="{site}" *) IBUF #( .IOSTANDARD("LVCMOS33") ) ibuf_{site} ( .I(clks[{idx}]), .O({ioclk}) );'''.format( ioclk=ioclk, site=iob, idx=idx, )) for site, x, y in sites: params = {} params['tile'] = tile_name params['site'] = site params['IN_USE'] = random.randint(0, 1) params['x'] = x - x_min params['y'] = y - y_min if params['IN_USE']: params['BUFR_DIVIDE'] = random.choice(( '"BYPASS"', '1', '2', '3', '4', '5', '6', '7', '8', )) params['I'] = random.choice(ioclks) if params['BUFR_DIVIDE'] == '"BYPASS"': params['CE'] = '1' params['CLR'] = '0' else: params['CE'] = luts.get_next_output_net() params['CLR'] = luts.get_next_output_net() outputs.append(''' (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFR #( .BUFR_DIVIDE({BUFR_DIVIDE}) ) buf_{site} ( .CE({CE}), .CLR({CLR}), .I({I}) ); '''.format(**params)) params_list.append(params) print(''' module top(input [{n1}:0] clks); '''.format(n1=num_clocks - 1)) print(""" (* KEEP, DONT_TOUCH *) LUT6 dummy ( );""") for l in luts.create_wires_and_luts(): print(l) for l in outputs: print(l) print("endmodule") with open('params.json', 'w') as f: json.dump(params_list, f, indent=2)
def main(): """ BUFHCE's can be driven from: MMCME2_ADV PLLE2_ADV BUFGCTRL Local INT connect PS7 (Zynq) """ print(''' // SEED={} module top(); '''.format(os.getenv('SEED'))) is_zynq = os.getenv('XRAY_DATABASE') == 'zynq7' clock_sources = ClockSources() site_to_cmt = dict(read_site_to_cmt()) if is_zynq: pss_clocks = list(read_pss_clocks()) # To ensure that all left or right sources are used, sometimes only MMCM/PLL # sources are allowed. The force of ODD/EVEN/BOTH further biases the # clock sources to the left or right column inputs. mmcm_pll_only = random.randint(0, 1) mmcm_pll_dir = random.choice(('ODD', 'EVEN', 'BOTH', 'NONE')) todos = read_todo() if only_gclk_left(todos): mmcm_pll_dir = 'NONE' if not mmcm_pll_only: if need_int_connections(todos): for _ in range(10): clock_sources.add_clock_source('one', 'ANY') clock_sources.add_clock_source('zero', 'ANY') print(""" wire zero = 0; wire one = 1;""") for loc, _, site in gen_sites('MMCME2_ADV'): mmcm_clocks = [ 'mmcm_clock_{site}_{idx}'.format(site=site, idx=idx) for idx in range(13) ] if check_allowed(mmcm_pll_dir, site_to_cmt[site]): for clk in mmcm_clocks: clock_sources.add_clock_source(clk, site_to_cmt[site], loc) print(""" wire {c0}, {c1}, {c2}, {c3}, {c4}, {c5}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) MMCME2_ADV pll_{site} ( .CLKOUT0({c0}), .CLKOUT0B({c1}), .CLKOUT1({c2}), .CLKOUT1B({c3}), .CLKOUT2({c4}), .CLKOUT2B({c5}), .CLKOUT3({c6}), .CLKOUT3B({c7}), .CLKOUT4({c8}), .CLKOUT5({c9}), .CLKOUT6({c10}), .CLKFBOUT({c11}), .CLKFBOUTB({c12}) ); """.format( site=site, c0=mmcm_clocks[0], c1=mmcm_clocks[1], c2=mmcm_clocks[2], c3=mmcm_clocks[3], c4=mmcm_clocks[4], c5=mmcm_clocks[5], c6=mmcm_clocks[6], c7=mmcm_clocks[7], c8=mmcm_clocks[8], c9=mmcm_clocks[9], c10=mmcm_clocks[10], c11=mmcm_clocks[11], c12=mmcm_clocks[12], )) for loc, _, site in gen_sites('PLLE2_ADV'): pll_clocks = [ 'pll_clock_{site}_{idx}'.format(site=site, idx=idx) for idx in range(6) ] if check_allowed(mmcm_pll_dir, site_to_cmt[site]): for clk in pll_clocks: clock_sources.add_clock_source(clk, site_to_cmt[site], loc) print(""" wire {c0}, {c1}, {c2}, {c3}, {c4}, {c5}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) PLLE2_ADV pll_{site} ( .CLKOUT0({c0}), .CLKOUT1({c1}), .CLKOUT2({c2}), .CLKOUT3({c3}), .CLKOUT4({c4}), .CLKOUT5({c5}) ); """.format( site=site, c0=pll_clocks[0], c1=pll_clocks[1], c2=pll_clocks[2], c3=pll_clocks[3], c4=pll_clocks[4], c5=pll_clocks[5], )) for loc, _, site in gen_sites('BUFR'): clock_sources.add_bufg_clock_source('O_{site}'.format(site=site), site_to_cmt[site], loc) print(""" wire O_{site}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFR bufr_{site} ( .O(O_{site}) );""".format(site=site)) if is_zynq: # FCLK clocks. Those are generated by the PS and go directly to one of # the CLK_HROW tile. clocks = [ "PSS_FCLKCLK0", "PSS_FCLKCLK1", "PSS_FCLKCLK2", "PSS_FCLKCLK3", ] loc, _, site = next(gen_sites('PS7')) print("") # Add clock sources and generate wires for wire in clocks: clock_info = [d for d in pss_clocks if d["pin"] == wire][0] # CMT tile cmt_tile = clock_info["tile"] cmt_loc = get_cmt_loc(cmt_tile) # Add only if the input wire is in the todo list dsts = [k for k, v in todos.items() if clock_info["wire"] in v] if len(dsts) > 0: # Wire source clock region. The PS7 is always left of the # CLK_HROW tile, but it does not matter here. regions = clock_info["clock_regions"].split() regions = sorted([(int(r[1]), int(r[3])) for r in regions]) # Add the clock source cmt = "X{}Y{}".format(regions[0][0], regions[0][1]) clock_sources.add_clock_source(wire, cmt, cmt_loc) print(" wire {};".format(wire)) print(""" (* KEEP, DONT_TOUCH, LOC = "{site}" *) PS7 ps7_{site} ( .FCLKCLK({{{fclk3}, {fclk2}, {fclk1}, {fclk0}}}) ); """.format(site=site, fclk0=clocks[0], fclk1=clocks[1], fclk2=clocks[2], fclk3=clocks[3])) luts = LutMaker() bufhs = StringIO() bufgs = StringIO() gclks = [] for _, _, site in sorted(gen_sites("BUFGCTRL"), key=lambda x: BUFGCTRL_XY_FUN(x[2])): wire_name = 'gclk_{}'.format(site) gclks.append(wire_name) include_source = True if mmcm_pll_only: include_source = False elif only_gclk_left(todos): include_source = need_gclk_connection(todos, site) if include_source: clock_sources.add_clock_source(wire_name, 'ANY') print(""" wire {wire_name}; """.format(wire_name=wire_name)) print(""" wire I1_{site}; wire I0_{site}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFGCTRL bufg_{site} ( .O({wire_name}), .S1({s1net}), .S0({s0net}), .IGNORE1({ignore1net}), .IGNORE0({ignore0net}), .I1(I1_{site}), .I0(I0_{site}), .CE1({ce1net}), .CE0({ce0net}) ); """.format( site=site, wire_name=wire_name, s1net=luts.get_next_output_net(), s0net=luts.get_next_output_net(), ignore1net=luts.get_next_output_net(), ignore0net=luts.get_next_output_net(), ce1net=luts.get_next_output_net(), ce0net=luts.get_next_output_net(), ), file=bufgs) any_bufhce = False for tile_name, sites in gen_bufhce_sites(): for site in sites: if not bufhce_in_todo(todos, site): continue any_bufhce = True print(""" wire I_{site}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFHCE buf_{site} ( .I(I_{site}) ); """.format(site=site, ), file=bufhs) if random.random() > .05: wire_name = clock_sources.get_random_source(site_to_cmt[site]) if wire_name is None: continue print(""" assign I_{site} = {wire_name};""".format( site=site, wire_name=wire_name, ), file=bufhs) if not any_bufhce: for tile_name, sites in gen_bufhce_sites(): for site in sites: print(""" (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFHCE #( .INIT_OUT({INIT_OUT}), .CE_TYPE({CE_TYPE}), .IS_CE_INVERTED({IS_CE_INVERTED}) ) buf_{site} ( .I({wire_name}) ); """.format( INIT_OUT=random.randint(0, 1), CE_TYPE=verilog.quote(random.choice(('SYNC', 'ASYNC'))), IS_CE_INVERTED=random.randint(0, 1), site=site, wire_name=gclks[0], )) break break for l in luts.create_wires_and_luts(): print(l) print(bufhs.getvalue()) print(bufgs.getvalue()) used_only = random.random() < .25 for loc, tile_type, site in sorted(gen_sites("BUFGCTRL"), key=lambda x: BUFGCTRL_XY_FUN(x[2])): if random.randint(0, 1): wire_name = clock_sources.get_bufg_source(loc, tile_type, site, todos, 1, used_only) if wire_name is not None: print(""" assign I1_{site} = {wire_name};""".format( site=site, wire_name=wire_name, )) if random.randint(0, 1): wire_name = clock_sources.get_bufg_source(loc, tile_type, site, todos, 0, used_only) if wire_name is not None: print(""" assign I0_{site} = {wire_name};""".format( site=site, wire_name=wire_name, )) print("endmodule")
def main(): print(''' module top( input wire in, output wire out ); assign out = in; ''') luts = LutMaker() primitives_list = list() for tile_name, tile_type, site_name, site_type in gen_sites( "GTPE2_CHANNEL"): params_list = list() params_dict = dict() params_dict["tile_type"] = tile_type params = dict() params['site'] = site_name verilog_attr = "" verilog_attr = "#(" fuz_dir = os.getenv("FUZDIR", None) assert fuz_dir with open(os.path.join(fuz_dir, "attrs.json"), "r") as attrs_file: attrs = json.load(attrs_file) in_use = bool(random.randint(0, 9)) params["IN_USE"] = in_use if in_use: for param, param_info in attrs.items(): param_type = param_info["type"] param_values = param_info["values"] param_digits = param_info["digits"] if param_type == INT: value = random.choice(param_values) value_str = value elif param_type == BIN: value = random.randint(0, param_values[0]) value_str = "{digits}'b{value:0{digits}b}".format( value=value, digits=param_digits) elif param_type in [BOOL, STR]: value = random.choice(param_values) value_str = verilog.quote(value) params[param] = value verilog_attr += """ .{}({}),""".format(param, value_str) verilog_ports = "" for param in [ "TXUSRCLK", "TXUSRCLK2", "TXPHDLYTSTCLK", "SIGVALIDCLK", "RXUSRCLK", "RXUSRCLK2", "DRPCLK", "DMONITORCLK", "CLKRSVD0", "CLKRSVD1" ]: is_inverted = random.randint(0, 1) params[param] = is_inverted verilog_attr += """ .IS_{}_INVERTED({}),""".format(param, is_inverted) verilog_ports += """ .{}({}),""".format(param, luts.get_next_output_net()) verilog_attr = verilog_attr.rstrip(",") verilog_attr += "\n)" print("(* KEEP, DONT_TOUCH, LOC=\"{}\" *)".format(site_name)) print("""GTPE2_CHANNEL {attrs} {site} ( {ports} ); """.format(attrs=verilog_attr, site=tile_type.lower(), ports=verilog_ports.rstrip(","))) params_list.append(params) params_dict["params"] = params_list primitives_list.append(params_dict) for l in luts.create_wires_and_luts(): print(l) print("endmodule") with open('params.json', 'w') as f: json.dump(primitives_list, f, indent=2)
def main(): """ BUFG's can be driven from: Interconnect HROW cascade """ print(''' module top(); (* KEEP, DONT_TOUCH *) LUT6 dummy(); ''') site_to_cmt = dict(read_site_to_cmt()) luts = LutMaker() wires = StringIO() bufgs = StringIO() clock_sources = ClockSources() db = Database(util.get_db_root(), util.get_part()) grid = db.grid() def gen_sites(desired_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(): if site_type == desired_site_type: yield tile_name, site for _, site in gen_sites('MMCME2_ADV'): mmcm_clocks = [ 'mmcm_clock_{site}_{idx}'.format(site=site, idx=idx) for idx in range(13) ] for clk in mmcm_clocks: clock_sources.add_clock_source(clk, site_to_cmt[site]) print(""" wire {c0}, {c1}, {c2}, {c3}, {c4}, {c5}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) MMCME2_ADV pll_{site} ( .CLKOUT0({c0}), .CLKOUT0B({c1}), .CLKOUT1({c2}), .CLKOUT1B({c3}), .CLKOUT2({c4}), .CLKOUT2B({c5}), .CLKOUT3({c6}), .CLKOUT3B({c7}), .CLKOUT4({c8}), .CLKOUT5({c9}), .CLKOUT6({c10}), .CLKFBOUT({c11}), .CLKFBOUTB({c12}) ); """.format( site=site, c0=mmcm_clocks[0], c1=mmcm_clocks[1], c2=mmcm_clocks[2], c3=mmcm_clocks[3], c4=mmcm_clocks[4], c5=mmcm_clocks[5], c6=mmcm_clocks[6], c7=mmcm_clocks[7], c8=mmcm_clocks[8], c9=mmcm_clocks[9], c10=mmcm_clocks[10], c11=mmcm_clocks[11], c12=mmcm_clocks[12], )) for _, site in sorted(gen_sites("BUFGCTRL"), key=lambda x: BUFGCTRL_XY_FUN(x[1])): print(""" wire O_{site}; wire S1_{site}; wire S0_{site}; wire IGNORE1_{site}; wire IGNORE0_{site}; wire I1_{site}; wire I0_{site}; wire CE1_{site}; wire CE0_{site}; """.format(site=site), file=wires) print(""" (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFGCTRL bufg_{site} ( .O(O_{site}), .S1(S1_{site}), .S0(S0_{site}), .IGNORE1(IGNORE1_{site}), .IGNORE0(IGNORE0_{site}), .I1(I1_{site}), .I0(I0_{site}), .CE1(CE1_{site}), .CE0(CE0_{site}) ); """.format(site=site), file=bufgs) """ BUFG clock sources: 2 from interconnect Output of BUFG +/- 1 Cascade in (e.g. PLL, MMCM) """ CLOCK_CHOICES = ( 'LUT', 'BUFG_+1', 'BUFG_-1', 'CASCADE', ) def find_bufg_cmt(tile): if '_BOT_' in tile: inc = 1 else: inc = -1 loc = grid.loc_of_tilename(tile) offset = 1 while True: gridinfo = grid.gridinfo_at_loc( (loc.grid_x, loc.grid_y + offset * inc)) if gridinfo.tile_type.startswith('CLK_HROW_'): return site_to_cmt[list(gridinfo.sites.keys())[0]] offset += 1 def get_clock_net(tile, site, source_type): if source_type == 'LUT': return luts.get_next_output_net() elif source_type == 'BUFG_+1': x, y = BUFGCTRL_XY_FUN(site) target_y = y + 1 max_y = ((y // 16) + 1) * 16 if target_y >= max_y: target_y -= 16 return 'O_BUFGCTRL_X{x}Y{y}'.format(x=x, y=target_y) elif source_type == 'BUFG_-1': x, y = BUFGCTRL_XY_FUN(site) target_y = y - 1 min_y = (y // 16) * 16 if target_y < min_y: target_y += 16 return 'O_BUFGCTRL_X{x}Y{y}'.format(x=x, y=target_y) elif source_type == 'CASCADE': cmt = find_bufg_cmt(tile) return clock_sources.get_random_source(cmt) else: assert False, source_type for tile, site in sorted(gen_sites("BUFGCTRL"), key=lambda x: BUFGCTRL_XY_FUN(x[1])): if random.randint(0, 1): print(""" assign I0_{site} = {i0_net};""".format(site=site, i0_net=get_clock_net( tile, site, random.choice(CLOCK_CHOICES))), file=bufgs) if random.randint(0, 1): print(""" assign I1_{site} = {i1_net};""".format(site=site, i1_net=get_clock_net( tile, site, random.choice(CLOCK_CHOICES))), file=bufgs) print(""" assign S0_{site} = {s0_net}; assign S1_{site} = {s1_net}; assign IGNORE0_{site} = {ignore0_net}; assign IGNORE1_{site} = {ignore1_net}; assign CE0_{site} = {ce0_net}; assign CE1_{site} = {ce1_net}; """.format( site=site, s0_net=luts.get_next_output_net(), s1_net=luts.get_next_output_net(), ignore0_net=luts.get_next_output_net(), ignore1_net=luts.get_next_output_net(), ce0_net=luts.get_next_output_net(), ce1_net=luts.get_next_output_net(), ), file=bufgs) for l in luts.create_wires_and_luts(): print(l) print(wires.getvalue()) print(bufgs.getvalue()) itr = iter(gen_sites('BUFHCE')) for tile, site in sorted(gen_sites("BUFGCTRL"), key=lambda x: BUFGCTRL_XY_FUN(x[1])): if random.randint(0, 1): _, bufhce_site = next(itr) print(""" (* KEEP, DONT_TOUCH, LOC = "{bufhce_site}" *) BUFHCE bufhce_{bufhce_site} ( .I(O_{site}) );""".format( site=site, bufhce_site=bufhce_site, )) print("endmodule")
def main(): """ BUFHCE's can be driven from: MMCME2_ADV PLLE2_ADV BUFGCTRL Local INT connect """ print(''' module top(); ''') site_to_cmt = dict(read_site_to_cmt()) clock_sources = ClockSources() # To ensure that all left or right sources are used, sometimes only MMCM/PLL # sources are allowed. The force of ODD/EVEN/BOTH further biases the # clock sources to the left or right column inputs. mmcm_pll_only = random.randint(0, 1) mmcm_pll_dir = random.choice(('ODD', 'EVEN', 'BOTH', 'NONE')) todos = read_todo() if only_gclk_left(todos): mmcm_pll_dir = 'NONE' if not mmcm_pll_only: if need_int_connections(todos): for _ in range(10): clock_sources.add_clock_source('one', 'ANY') clock_sources.add_clock_source('zero', 'ANY') print(""" wire zero = 0; wire one = 1;""") for loc, _, site in gen_sites('MMCME2_ADV'): mmcm_clocks = [ 'mmcm_clock_{site}_{idx}'.format(site=site, idx=idx) for idx in range(13) ] if check_allowed(mmcm_pll_dir, site_to_cmt[site]): for clk in mmcm_clocks: clock_sources.add_clock_source(clk, site_to_cmt[site], loc) print(""" wire {c0}, {c1}, {c2}, {c3}, {c4}, {c5}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) MMCME2_ADV pll_{site} ( .CLKOUT0({c0}), .CLKOUT0B({c1}), .CLKOUT1({c2}), .CLKOUT1B({c3}), .CLKOUT2({c4}), .CLKOUT2B({c5}), .CLKOUT3({c6}), .CLKOUT3B({c7}), .CLKOUT4({c8}), .CLKOUT5({c9}), .CLKOUT6({c10}), .CLKFBOUT({c11}), .CLKFBOUTB({c12}) ); """.format( site=site, c0=mmcm_clocks[0], c1=mmcm_clocks[1], c2=mmcm_clocks[2], c3=mmcm_clocks[3], c4=mmcm_clocks[4], c5=mmcm_clocks[5], c6=mmcm_clocks[6], c7=mmcm_clocks[7], c8=mmcm_clocks[8], c9=mmcm_clocks[9], c10=mmcm_clocks[10], c11=mmcm_clocks[11], c12=mmcm_clocks[12], )) for loc, _, site in gen_sites('PLLE2_ADV'): pll_clocks = [ 'pll_clock_{site}_{idx}'.format(site=site, idx=idx) for idx in range(6) ] if check_allowed(mmcm_pll_dir, site_to_cmt[site]): for clk in pll_clocks: clock_sources.add_clock_source(clk, site_to_cmt[site], loc) print(""" wire {c0}, {c1}, {c2}, {c3}, {c4}, {c5}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) PLLE2_ADV pll_{site} ( .CLKOUT0({c0}), .CLKOUT1({c1}), .CLKOUT2({c2}), .CLKOUT3({c3}), .CLKOUT4({c4}), .CLKOUT5({c5}) ); """.format( site=site, c0=pll_clocks[0], c1=pll_clocks[1], c2=pll_clocks[2], c3=pll_clocks[3], c4=pll_clocks[4], c5=pll_clocks[5], )) for loc, _, site in gen_sites('BUFR'): clock_sources.add_bufg_clock_source('O_{site}'.format(site=site), site_to_cmt[site], loc) print(""" wire O_{site}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFR bufr_{site} ( .O(O_{site}) );""".format(site=site)) luts = LutMaker() bufhs = StringIO() bufgs = StringIO() gclks = [] for _, _, site in sorted(gen_sites("BUFGCTRL"), key=lambda x: BUFGCTRL_XY_FUN(x[2])): wire_name = 'gclk_{}'.format(site) gclks.append(wire_name) include_source = True if mmcm_pll_only: include_source = False elif only_gclk_left(todos): include_source = need_gclk_connection(todos, site) if include_source: clock_sources.add_clock_source(wire_name, 'ANY') print(""" wire {wire_name}; """.format(wire_name=wire_name)) print(""" wire I1_{site}; wire I0_{site}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFGCTRL bufg_{site} ( .O({wire_name}), .S1({s1net}), .S0({s0net}), .IGNORE1({ignore1net}), .IGNORE0({ignore0net}), .I1(I1_{site}), .I0(I0_{site}), .CE1({ce1net}), .CE0({ce0net}) ); """.format( site=site, wire_name=wire_name, s1net=luts.get_next_output_net(), s0net=luts.get_next_output_net(), ignore1net=luts.get_next_output_net(), ignore0net=luts.get_next_output_net(), ce1net=luts.get_next_output_net(), ce0net=luts.get_next_output_net(), ), file=bufgs) any_bufhce = False for tile_name, sites in gen_bufhce_sites(): for site in sites: if not bufhce_in_todo(todos, site): continue any_bufhce = True print(""" wire I_{site}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFHCE buf_{site} ( .I(I_{site}) ); """.format(site=site, ), file=bufhs) if random.random() > .05: wire_name = clock_sources.get_random_source(site_to_cmt[site]) if wire_name is None: continue print(""" assign I_{site} = {wire_name};""".format( site=site, wire_name=wire_name, ), file=bufhs) if not any_bufhce: for tile_name, sites in gen_bufhce_sites(): for site in sites: print(""" (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFHCE #( .INIT_OUT({INIT_OUT}), .CE_TYPE({CE_TYPE}), .IS_CE_INVERTED({IS_CE_INVERTED}) ) buf_{site} ( .I({wire_name}) ); """.format( INIT_OUT=random.randint(0, 1), CE_TYPE=verilog.quote(random.choice(('SYNC', 'ASYNC'))), IS_CE_INVERTED=random.randint(0, 1), site=site, wire_name=gclks[0], )) break break for l in luts.create_wires_and_luts(): print(l) print(bufhs.getvalue()) print(bufgs.getvalue()) used_only = random.random() < .25 for loc, tile_type, site in sorted(gen_sites("BUFGCTRL"), key=lambda x: BUFGCTRL_XY_FUN(x[2])): if random.randint(0, 1): wire_name = clock_sources.get_bufg_source(loc, tile_type, site, todos, 1, used_only) if wire_name is not None: print(""" assign I1_{site} = {wire_name};""".format( site=site, wire_name=wire_name, )) if random.randint(0, 1): wire_name = clock_sources.get_bufg_source(loc, tile_type, site, todos, 0, used_only) if wire_name is not None: print(""" assign I0_{site} = {wire_name};""".format( site=site, wire_name=wire_name, )) print("endmodule")