Esempio n. 1
0
def main():
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    luts = LutMaker()

    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

    print('''
module top();

    (* KEEP, DONT_TOUCH *)
    LUT6 dummy();
''')

    for site_type in ["PCIE_2_1"]:
        for _, site in gen_sites(site_type):
            print_site(ports[site_type], luts, site, site_type)

    for l in luts.create_wires_and_luts():
        print(l)

    print('endmodule')
Esempio n. 2
0
def run():
    luts = LutMaker()
    count = bram_count()

    max_bram_count = random.randint(1, 200)

    modules = []
    lines = []

    idx = 0
    while count > MAX_BRAM:
        width, address_bits, bits = random_sdp_bram(luts, "ram{}".format(idx),
                                                    modules, lines)

        brams = math.ceil(bits / float(36 * 1024))

        count -= brams

        print(width, address_bits, bits, brams, count, file=sys.stderr)
        idx += 1

        if idx >= max_bram_count:
            break

    for module in modules:
        print(module)

    print('''
module top();
''')

    for lut in luts.create_wires_and_luts():
        print(lut)

    for l in lines:
        print(l)

    print("endmodule")
Esempio n. 3
0
def main():
    print('''
module top();
    ''')

    luts = LutMaker()
    lines = []

    params_list = []
    for tile_name, sites in gen_sites():
        gen_fun = random.choice(
            (ramb18, ramb18_2x, ramb36, fifo18, fifo18_ramb18, fifo36))
        params_list.append(gen_fun(tile_name, luts, lines, sites))

    for lut in luts.create_wires_and_luts():
        print(lut)

    for l in lines:
        print(l)

    print("endmodule")

    with open('params.json', 'w') as f:
        json.dump(params_list, f, indent=2)
Esempio n. 4
0
def main():
    """
    HCLK_CMT switch box has the follow inputs:

    4 IOBs above and below
    14 MMCM outputs
    8 PLL outputs
    4 PHASER_IN outputs
    2 INT connections

    and the following outputs:

    3 PLLE2 inputs
    2 BUFMR inputs
    3 MMCM inputs
    ~2 MMCM -> BUFR???
    """

    clock_sources = ClockSources()
    adv_clock_sources = ClockSources()
    site_to_cmt = dict(read_site_to_cmt())

    db = Database(util.get_db_root())
    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

    hclk_cmts = set()
    ins = []
    iobs = StringIO()

    hclk_cmt_tiles = set()
    for tile_name, site in gen_sites('BUFMRCE'):
        cmt = site_to_cmt[site]
        hclk_cmts.add(cmt)
        hclk_cmt_tiles.add(tile_name)

    mmcm_pll_only = random.randint(0, 1)
    mmcm_pll_dir = random.choice(('ODD', 'EVEN', 'BOTH'))

    print(
        '// mmcm_pll_only {} mmcm_pll_dir {}'.format(
            mmcm_pll_only, mmcm_pll_dir))

    have_iob_clocks = random.random() > .1

    iob_clks = {}
    for tile_name in sorted(hclk_cmt_tiles):
        for _, site, volt in get_paired_iobs(db, grid, tile_name):
            iob_clock = 'clock_IBUF_{site}'.format(site=site)

            cmt = site_to_cmt[site]

            if cmt not in iob_clks:
                iob_clks[cmt] = ['']

            iob_clks[cmt].append(iob_clock)

            ins.append('input clk_{site}'.format(site=site))

            if have_iob_clocks:
                if check_allowed(mmcm_pll_dir, cmt):
                    clock_sources.add_clock_source(iob_clock, cmt)
                adv_clock_sources.add_clock_source(iob_clock, cmt)

            print(
                """
    (* KEEP, DONT_TOUCH, LOC = "{site}" *)
    wire clock_IBUF_{site};
    IBUF #( .IOSTANDARD("LVCMOS{volt}") ) ibuf_{site} (
        .I(clk_{site}),
        .O(clock_IBUF_{site})
        );
                    """.format(volt=volt, site=site),
                file=iobs)

    print(
        '''
module top({inputs});
    (* KEEP, DONT_TOUCH *)
    LUT6 dummy();
    '''.format(inputs=', '.join(ins)))

    print(iobs.getvalue())

    luts = LutMaker()
    wires = StringIO()
    bufhs = StringIO()

    for _, 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])

        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({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 gen_sites('PLLE2_ADV'):
        pll_clocks = [
            'pll_clock_{site}_{idx}'.format(site=site, idx=idx)
            for idx in range(7)
        ]

        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])

        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=bufhs)

        if site_to_cmt[site] in hclk_cmts:
            if not mmcm_pll_only:
                clock_sources.add_clock_source(
                    'O_{site}'.format(site=site), site_to_cmt[site])
            adv_clock_sources.add_clock_source(
                'O_{site}'.format(site=site), site_to_cmt[site])

    hclks_used_by_cmt = {}
    for cmt in site_to_cmt.values():
        hclks_used_by_cmt[cmt] = set()

    def check_hclk_src(src, src_cmt):
        if len(hclks_used_by_cmt[src_cmt]
               ) >= 12 and src not in hclks_used_by_cmt[src_cmt]:
            return None
        else:
            hclks_used_by_cmt[src_cmt].add(src)
            return src

    if random.random() > .10:
        for tile_name, site in gen_sites('BUFHCE'):
            wire_name = clock_sources.get_random_source(
                site_to_cmt[site],
                uses_left_right_routing=True,
                no_repeats=mmcm_pll_only)

            if wire_name is not None and 'BUFHCE' in wire_name:
                # Looping a BUFHCE to a BUFHCE requires using a hclk in the
                # CMT of the source
                src_cmt = clock_sources.source_to_cmt[wire_name]

                wire_name = check_hclk_src(wire_name, src_cmt)

            if wire_name is None:
                continue

            print(
                """
        assign I_{site} = {wire_name};""".format(
                    site=site,
                    wire_name=wire_name,
                ),
                file=bufhs)

    for tile_name, site in gen_sites('BUFMRCE'):
        pass

    for l in luts.create_wires_and_luts():
        print(l)

    print(wires.getvalue())
    print(bufhs.getvalue())

    for _, site in gen_sites('BUFR'):
        adv_clock_sources.add_clock_source(
            'O_{site}'.format(site=site), site_to_cmt[site])
        print(
            """
    wire O_{site};
    (* KEEP, DONT_TOUCH, LOC = "{site}" *)
    BUFR bufr_{site} (
        .I({I}),
        .O(O_{site})
        );""".format(I=random.choice(iob_clks[site_to_cmt[site]]), site=site))

    for _, site in gen_sites('PLLE2_ADV'):
        for cin in ('cin1', 'cin2', 'clkfbin'):
            if random.random() > .2:
                src = adv_clock_sources.get_random_source(site_to_cmt[site])

                src_cmt = adv_clock_sources.source_to_cmt[src]

                if 'IBUF' not in src and 'BUFR' not in src:
                    # Clocks from input pins do not require HCLK's, all other
                    # sources route from a global row clock.
                    src = check_hclk_src(src, src_cmt)

                if src is None:
                    continue

                print(
                    """
        assign {cin}_{site} = {csrc};
            """.format(cin=cin, site=site, csrc=src))

    for _, site in gen_sites('MMCME2_ADV'):
        for cin in ('cin1', 'cin2', 'clkfbin'):
            if random.random() > .2:
                src = adv_clock_sources.get_random_source(site_to_cmt[site])

                src_cmt = adv_clock_sources.source_to_cmt[src]
                if 'IBUF' not in src and 'BUFR' not in src:
                    # Clocks from input pins do not require HCLK's, all other
                    # sources route from a global row clock.
                    src = check_hclk_src(src, src_cmt)

                if src is None:
                    continue

                print(
                    """
        assign {cin}_{site} = {csrc};
            """.format(cin=cin, site=site, csrc=src))

    print("endmodule")
Esempio n. 5
0
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)
Esempio n. 6
0
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")
Esempio n. 7
0
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)
Esempio n. 8
0
def main():
    """
    HCLK_CMT switch box has the follow inputs:

    4 IOBs above and below
    14 MMCM outputs
    8 PLL outputs
    4 PHASER_IN outputs
    2 INT connections

    and the following outputs:

    3 PLLE2 inputs
    2 BUFMR inputs
    3 MMCM inputs
    ~2 MMCM -> BUFR???
    """

    clock_sources = ClockSources()
    adv_clock_sources = ClockSources()

    tile_site_cmt = list(read_site_to_cmt())
    site_to_cmt = {tsc[1]: tsc[2] for tsc in tile_site_cmt}
    cmt_to_hclk = {
        tsc[2]: tsc[0]
        for tsc in tile_site_cmt if tsc[0].startswith("HCLK_CMT_")
    }

    ccio_route_options = make_ccio_route_options()

    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

    hclk_cmts = set()
    ins = []
    iobs = StringIO()

    hclk_cmt_tiles = set()
    for tile_name, site in gen_sites('BUFMRCE'):
        cmt = site_to_cmt[site]
        hclk_cmts.add(cmt)
        hclk_cmt_tiles.add(tile_name)

    mmcm_pll_only = random.randint(0, 1)
    mmcm_pll_dir = random.choice(('ODD', 'EVEN', 'BOTH'))

    print('// mmcm_pll_only {} mmcm_pll_dir {}'.format(mmcm_pll_only,
                                                       mmcm_pll_dir))

    have_iob_clocks = random.random() > .1

    iob_to_hclk = {}
    iob_clks = {}
    for tile_name in sorted(hclk_cmt_tiles):
        for _, site, volt, ccio in get_paired_iobs(db, grid, tile_name):
            iob_clock = 'clock_IBUF_{site}'.format(site=site)

            iob_to_hclk[site] = (tile_name, ccio)
            cmt = site_to_cmt[site]

            if cmt not in iob_clks:
                iob_clks[cmt] = ['']

            iob_clks[cmt].append(iob_clock)

            ins.append('input clk_{site}'.format(site=site))

            if have_iob_clocks:
                if check_allowed(mmcm_pll_dir, cmt):
                    clock_sources.add_clock_source(iob_clock, cmt)
                adv_clock_sources.add_clock_source(iob_clock, cmt)

            print("""
    (* KEEP, DONT_TOUCH, LOC = "{site}" *)
    wire clock_IBUF_{site};
    IBUF #( .IOSTANDARD("LVCMOS{volt}") ) ibuf_{site} (
        .I(clk_{site}),
        .O(clock_IBUF_{site})
        );
                    """.format(volt=volt, site=site),
                  file=iobs)

    print('''
module top({inputs});
    (* KEEP, DONT_TOUCH *)
    LUT6 dummy();
    '''.format(inputs=', '.join(ins)))

    print(iobs.getvalue())

    luts = LutMaker()
    wires = StringIO()
    bufhs = StringIO()

    for _, 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])

        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({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 gen_sites('PLLE2_ADV'):
        pll_clocks = [
            'pll_clock_{site}_{idx}'.format(site=site, idx=idx)
            for idx in range(7)
        ]

        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])

        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=bufhs)

        if site_to_cmt[site] in hclk_cmts:
            if not mmcm_pll_only:
                clock_sources.add_clock_source('O_{site}'.format(site=site),
                                               site_to_cmt[site])
            adv_clock_sources.add_clock_source('O_{site}'.format(site=site),
                                               site_to_cmt[site])

    hclks_used_by_cmt = {}
    for cmt in site_to_cmt.values():
        hclks_used_by_cmt[cmt] = set()

    def check_hclk_src(src, src_cmt):
        if len(hclks_used_by_cmt[src_cmt]
               ) >= 12 and src not in hclks_used_by_cmt[src_cmt]:
            return None
        else:
            hclks_used_by_cmt[src_cmt].add(src)
            return src

    # Track used IOB sources
    used_iob_clks = set()

    if random.random() > .10:
        for tile_name, site in gen_sites('BUFHCE'):

            wire_name = clock_sources.get_random_source(
                site_to_cmt[site],
                uses_left_right_routing=True,
                no_repeats=mmcm_pll_only)

            if wire_name is not None and 'BUFHCE' in wire_name:
                # Looping a BUFHCE to a BUFHCE requires using a hclk in the
                # CMT of the source
                src_cmt = clock_sources.source_to_cmt[wire_name]

                wire_name = check_hclk_src(wire_name, src_cmt)

            if wire_name is None:
                continue

            if "IBUF" in wire_name:
                used_iob_clks.add(wire_name)
                clock_sources.remove_clock_source(wire_name)
                adv_clock_sources.remove_clock_source(wire_name)

            print("""
        assign I_{site} = {wire_name};""".format(
                site=site,
                wire_name=wire_name,
            ),
                  file=bufhs)

    for tile_name, site in gen_sites('BUFMRCE'):
        pass

    for l in luts.create_wires_and_luts():
        print(l)

    print(wires.getvalue())
    print(bufhs.getvalue())

    for _, site in gen_sites('BUFR'):

        # Do not use BUFR always
        if random.random() < 0.50:
            continue

        available_srcs = set(iob_clks[site_to_cmt[site]]) - used_iob_clks
        if len(available_srcs) == 0:
            continue

        src = random.choice(list(available_srcs))

        if src != "":
            used_iob_clks.add(src)
            clock_sources.remove_clock_source(src)
            adv_clock_sources.remove_clock_source(src)

        adv_clock_sources.add_clock_source('O_{site}'.format(site=site),
                                           site_to_cmt[site])

        print("""
    wire O_{site};
    (* KEEP, DONT_TOUCH, LOC = "{site}" *)
    BUFR bufr_{site} (
        .I({I}),
        .O(O_{site})
        );""".format(I=src, site=site))

    route_file = open("routes.txt", "w")

    def fix_ccio_route(net):

        # Get the IOB site name
        match = re.match(r".*_IBUF_(.*)", net)
        assert match is not None, net
        iob_site = match.group(1)

        # Get associated HCLK_CMT tile and CCIO wire index
        hclk_tile_name, ccio = iob_to_hclk[iob_site]

        # Get HCLK_CMT tile type
        hclk_tile = hclk_tile_name.rsplit("_", maxsplit=1)[0]

        # Pick a random route option
        opts = list(ccio_route_options[hclk_tile][ccio])
        route = random.choice(opts)
        route = "{}/{}".format(hclk_tile_name, route)
        route_file.write("{} {}\n".format(net, route))

    for _, site in gen_sites('PLLE2_ADV'):
        for cin in ('cin1', 'cin2', 'clkfbin'):
            if random.random() > .2:

                src = adv_clock_sources.get_random_source(site_to_cmt[site])

                src_cmt = adv_clock_sources.source_to_cmt[src]

                if 'IBUF' not in src and 'BUFR' not in src:
                    # Clocks from input pins do not require HCLK's, all other
                    # sources route from a global row clock.
                    src = check_hclk_src(src, src_cmt)

                if src is None:
                    continue

                if "IBUF" in src:
                    clock_sources.remove_clock_source(src)
                    adv_clock_sources.remove_clock_source(src)
                    fix_ccio_route(src)

                print("""
        assign {cin}_{site} = {csrc};
            """.format(cin=cin, site=site, csrc=src))

    for _, site in gen_sites('MMCME2_ADV'):
        for cin in ('cin1', 'cin2', 'clkfbin'):
            if random.random() > .2:

                src = adv_clock_sources.get_random_source(site_to_cmt[site])

                src_cmt = adv_clock_sources.source_to_cmt[src]
                if 'IBUF' not in src and 'BUFR' not in src:
                    # Clocks from input pins do not require HCLK's, all other
                    # sources route from a global row clock.
                    src = check_hclk_src(src, src_cmt)

                if src is None:
                    continue

                if "IBUF" in src:
                    clock_sources.remove_clock_source(src)
                    adv_clock_sources.remove_clock_source(src)
                    fix_ccio_route(src)

                print("""
        assign {cin}_{site} = {csrc};
            """.format(cin=cin, site=site, csrc=src))

    print("endmodule")
Esempio n. 9
0
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")
Esempio n. 10
0
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)
Esempio n. 11
0
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")
Esempio n. 12
0
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")