예제 #1
0
    def __init__(self,
                 bitsfile,
                 verbose=False,
                 db_root=None,
                 part=None,
                 bits_per_word=32):
        self.db_root = db_root
        if self.db_root is None:
            self.db_root = util.get_db_root()

        self.part = part
        if self.part is None:
            self.part = util.get_part()
            assert self.part, "No part specified."

        self.verbose = verbose if verbose is not None else os.getenv(
            'VERBOSE', 'N') == 'Y'
        self.bits_per_word = bits_per_word
        self.load_grid()
        self.load_bits(bitsfile)
        '''
        self.tags[site][name] = value
        Where:
        -site: ex 'SLICE_X13Y101'
        -name: ex 'CLB.SLICE_X0.AFF.DMUX.CY'
        '''
        self.site_tags = dict()
        self.tile_tags = dict()

        # output after compiling
        self.segments_by_type = None

        # hacky...improve if we encounter this more
        self.def_bt = 'CLB_IO_CLK'
        self.index_sites()
예제 #2
0
def gen_sites(tile_type):
    o = {}

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    allowed_sites = read_allowed_sites()

    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        if gridinfo.tile_type != tile_type:
            continue

        for site_name, site_type in gridinfo.sites.items():
            if site_type in ['HPIOB_S', 'HPIOB_M', 'HDIOB_S', 'HDIOB_M'
                             ] and site_name in allowed_sites:
                if tile_name not in o:
                    o[tile_name] = []

                o[tile_name].append(site_name)

    for tile_name in o:
        o[tile_name].sort(key=util.create_xy_fun('IOB_'))

    return o
예제 #3
0
파일: top.py 프로젝트: tmichalak/prjuray
def gen_sites():
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        tile_type = gridinfo.tile_type
        if tile_type in ['CLEL_L', 'CLEL_R']:
            # Don't fuzz the top and bottom of the grid, the interconnect
            # there behaves differently.
            _, _, y_min, y_max = grid.dims()
            if loc.grid_y <= y_min + 1 or loc.grid_y >= y_max - 1:
                continue

            site_name = sorted(gridinfo.sites.keys())[0]
            if gridinfo.tile_type[-1] == 'L':
                int_tile_loc = (loc.grid_x + 1, loc.grid_y)
            else:
                int_tile_loc = (loc.grid_x - 1, loc.grid_y)

            int_tile_name = grid.tilename_at_loc(int_tile_loc)

            if not int_tile_name.startswith('INT_'):
                continue

            yield int_tile_name, site_name
예제 #4
0
def gen_sites():
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)
        if gridinfo.tile_type in ['CLEM_R']:
            site_name = sorted(gridinfo.sites.keys())[0]
            yield tile_name, site_name
예제 #5
0
def gen_bufgs():
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site, site_type in gridinfo.sites.items():
            if "BUFGCE" in site and "HDIO" not in site and "DIV" not in site:
                yield site
예제 #6
0
파일: top.py 프로젝트: SymbiFlow/prjuray
def gen_sites():
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site_name, site_type in gridinfo.sites.items():
            if site_type in ['RAMBFIFO18']:
                yield tile_name, site_name
예제 #7
0
파일: top.py 프로젝트: mfkiwl/prjuray
def gen_sites():
    """
    Generates all possible SLICE sites
    """
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)
        if gridinfo.tile_type in ['CLEL_L', 'CLEL_R', 'CLEM', 'CLEM_R']:
            site_name = sorted(gridinfo.sites.keys())[0]
            yield site_name
예제 #8
0
def gen_sites():
    """
    Generates all possible SLICE sites
    """
    SLICE_RE = re.compile(r"SLICE_X([0-9]+)Y([0-9]+)")

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)
        if gridinfo.tile_type in ['CLEL_L', 'CLEL_R', 'CLEM', 'CLEM_R']:
            site_name = sorted(gridinfo.sites.keys())[0]
            match = SLICE_RE.match(site_name)
            if match is not None:
                site_loc = int(match.group(1)), int(match.group(2))
                yield Site(tile_name, site_name, site_loc)
예제 #9
0
파일: gclk_2.py 프로젝트: mfkiwl/prjuray
def gen_bufgs():

    bufgces_by_tile = {}
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()
    for tile in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site, site_type in gridinfo.sites.items():
            if ("BUFGCE" in site or "BUFGCTRL" in site) and "HDIO" not in site:
                if tile not in bufgces_by_tile:
                    bufgces_by_tile[tile] = []

                bufgces_by_tile[tile].append((site, site_type))

    return bufgces_by_tile
예제 #10
0
파일: top.py 프로젝트: tmichalak/prjuray
def gen_sites():
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    o = {}
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site_name, site_type in gridinfo.sites.items():
            if site_type == 'BUFCE_LEAF':
                if tile_name not in o:
                    o[tile_name] = []

                o[tile_name].append(site_name)

    return o
예제 #11
0
def gen_sites():
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    tiles = {}
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site, site_type in gridinfo.sites.items():
            if site_type in ['SLICEM', 'SLICEL']:
                if gridinfo.tile_type not in tiles:
                    tiles[gridinfo.tile_type] = set()

                tiles[gridinfo.tile_type].add(site)

    return tiles
예제 #12
0
def gen_sites():
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    bufgces = []
    slices = []

    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site, site_type in gridinfo.sites.items():
            if "BUFGCE" in site and "HDIO" not in site:
                bufgces.append(site)

            if "SLICEM" in site or "SLICEL" in site:
                slices.append(site)

    return bufgces, slices
예제 #13
0
def gen_sites():
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    xy_fun = util.create_xy_fun('BITSLICE_RX_TX_')

    o = {}
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site_name, site_type in gridinfo.sites.items():
            if site_type == 'BITSLICE_RX_TX':
                if tile_name not in o:
                    o[tile_name] = []

                o[tile_name].append(site_name)

        if tile_name in o:
            o[tile_name].sort(key=lambda site: xy_fun(site))

    return o
예제 #14
0
def print_top(seed):
    np.random.seed(seed)

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()
    slices = sorted(gen_sites(grid))
    np.random.shuffle(slices)

    print("""
module top();
        """)
    print("""
    (* BEL="A6LUT", LOC="{loc}", KEEP, DONT_TOUCH *) LUT5 lut ();
    """.format(loc=slices.pop()))
    print('endmodule')

    leafs = populate_leafs(grid)

    site_to_site_type = {}
    site_to_tile = {}
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site, site_type in gridinfo.sites.items():
            site_to_site_type[site] = site_type
            site_to_tile[site] = tile_name

    bufgs = GlobalClockBuffers('../bufg_outputs.csv')

    clock_column = sorted(leafs.keys())
    np.random.shuffle(clock_column)

    bufg_leaf = util.create_xy_fun(prefix='BUFCE_LEAF_')

    delays = [0, 1, 2, 4, 8]

    global_clocks = list(range(MAX_GLOBAL_CLOCKS))
    np.random.shuffle(global_clocks)

    with open('complete_top.tcl', 'w') as f:
        print('place_design -directive Quick', file=f)
        print('source $::env(URAY_UTILS_DIR)/utils.tcl', file=f)

        for idx, global_clock in enumerate(global_clocks):
            bufg_list = [
                bufg for bufg in bufgs.bufgs[global_clock]
                if bufg.startswith('BUFGCE_X')
            ]
            bufg_list.sort()
            np.random.shuffle(bufg_list)

            bufg = bufg_list.pop()

            loc, column_direction = clock_column.pop()
            print('# {} {}'.format(loc, column_direction), file=f)

            gridinfo = grid.gridinfo_at_loc(loc)

            coords = []

            for site in gridinfo.sites.keys():
                x, y = bufg_leaf(site)
                coords.append((x, y))

            coords.sort()
            y_min = coords[0][1]

            buf_leafs = []
            for site in gridinfo.sites.keys():
                _, y = bufg_leaf(site)

                if y - y_min < 2 and column_direction > 0:
                    buf_leafs.append(site)

                if y - y_min >= 2 and column_direction < 0:
                    buf_leafs.append(site)

            buf_leafs.sort()
            np.random.shuffle(buf_leafs)

            bufce_leaf = buf_leafs.pop()

            slices = list(leafs[loc, column_direction])
            slices.sort()
            np.random.shuffle(slices)

            slice_site = slices.pop()

            delay = np.random.choice(delays)

            print(
                "create_leaf_delay {idx} {delay} {bufgce_site} {bufce_leaf_site} {slice_site}"
                .format(
                    idx=idx,
                    delay=delay,
                    bufgce_site=bufg,
                    bufce_leaf_site=bufce_leaf,
                    slice_site=slice_site,
                ),
                file=f)

        print('route_design -directive Quick', file=f)

        print('set_property IS_ENABLED 0 [get_drc_checks {RTRES-2}]', file=f)
예제 #15
0
def print_top(seed):
    np.random.seed(seed)

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    clocks = ClockColumns(grid)

    disabled_columns = set()
    for key in clocks.columns():
        if np.random.choice([1, 0], p=[.25, .75]):
            disabled_columns.add(key)

    clocks.remove_column(disabled_columns)

    print("""
module top(input clk, stb, di, output do);
        """)

    bufg_by_tile = gen_bufgs(grid)
    tile = np.random.choice(sorted(bufg_by_tile.keys()))
    bufgs = bufg_by_tile[tile]
    assert len(bufgs) > 0
    bufgs.sort()
    np.random.shuffle(bufgs)

    slices = sorted(clocks.sites.keys())
    np.random.shuffle(slices)

    num_bufgs = np.random.randint(1, min(len(bufgs) + 1, 25))
    assert num_bufgs > 0
    print('    wire [{}:0] bufg_clk;'.format(num_bufgs))

    for idx, site in enumerate(bufgs):
        if idx >= num_bufgs:
            break

        print(
            '    (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFGCE bufg_{i} ( .CE(1\'b1), .O(bufg_clk[{i}]) );'
            .format(i=idx, loc=site))

    num_slices = np.random.randint(1, len(slices) + 1)

    for idx, slice_loc in enumerate(slices):
        if idx >= num_slices:
            break

        all_clocks = list(range(0, num_bufgs))
        np.random.shuffle(all_clocks)
        while True:
            clock_str = 'bufg_clk[{}]'.format(all_clocks.pop())

            if clocks.add_clock(slice_loc, clock_str):
                print(
                    '    (* LOC="{loc}", KEEP, DONT_TOUCH *) FDCE ff_{i}(.C({clock_str}));'
                    .format(loc=slice_loc, i=idx, clock_str=clock_str))
                break

    print('endmodule')

    with open('top.tcl', 'w') as f:
        print("set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]", file=f)
예제 #16
0
def print_top(seed):
    np.random.seed(seed)

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    site_to_site_type = {}
    site_to_tile = {}
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site, site_type in gridinfo.sites.items():
            site_to_site_type[site] = site_type
            site_to_tile[site] = tile_name

    slices = sorted(gen_sites(grid))
    np.random.shuffle(slices)

    with open('../active_bufce_row.csv') as f:
        bufce_rows = [row for row in DictReader(f)]

    np.random.shuffle(bufce_rows)

    with open('../bufce_leaf_clock_regions.csv') as f:
        bufce_leafs = [row for row in DictReader(f)]

    bufgs = GlobalClockBuffers('../bufg_outputs.csv')

    with open('complete_top.tcl', 'w') as f:
        #print('place_design -directive Quick', file=f)
        print("""
write_checkpoint -force design_reset.dcp
close_design
open_checkpoint design_reset.dcp
route_design

set route_status [struct::set union [get_property ROUTE_STATUS [get_nets -hierarchical ]] []]

if { [llength $route_status] > 1 } {
    set_property ROUTE "" [get_nets -hierarchical]
    route_design -nets [get_nets bufce_row_out_*]
    route_design -nets [concat [get_nets lut_*] [get_nets -filter "TYPE == POWER || TYPE == GROUND"]]
    route_design
}
""",
              file=f)

    print("""
module top();
        """)

    N_LUTS = 3

    ce_inputs = [0, 1]
    for idx in range(N_LUTS):

        print("""
        wire lut_o_{idx};
        (* BEL="A6LUT", LOC="{loc}", KEEP, DONT_TOUCH *) LUT5 lut{idx} (.O(lut_o_{idx}));
        """.format(idx=idx, loc=slices.pop()))

        ce_inputs.append('lut_o_{}'.format(idx))

    clock_resource_in_use = set()

    bufg_for_hroute = {}
    bufce_rows_by_cmt = {}
    for idx, bufce_row in enumerate(bufce_rows):
        if np.random.choice([0, 1], p=[.75, .25]):
            continue

        clock_region = bufce_row['site_clock_region']
        if clock_region not in bufce_rows_by_cmt:
            bufce_rows_by_cmt[clock_region] = []

        # Don't overuse HDISTR resources!
        key = (bufce_row['site_clock_region'], bufce_row['hdistr_number'])
        if key in clock_resource_in_use:
            continue

        hdistr_number = int(bufce_row['hdistr_number'])
        if hdistr_number not in bufg_for_hroute:
            while True:
                site = np.random.choice(bufgs.bufgs[hdistr_number])
                site_type = site_to_site_type[site]

                if site_type == 'BUFGCE':
                    break

            s, bufg_for_hroute[hdistr_number] = make_bufg(
                site=site,
                site_type=site_type,
                idx=len(bufg_for_hroute),
                ce_inputs=['1'],
                randlib=np.random)

            print(s)

        clock_resource_in_use.add(key)

        bufce_rows_by_cmt[clock_region].append(idx)

        if np.random.choice([0, 1], p=[.9, .1]):
            bufg_in = '1'
            ce_type = 'ASYNC'
        else:
            bufg_in = bufg_for_hroute[hdistr_number]
            ce_type = np.random.choice(["SYNC", "ASYNC"])

        print("""
        wire bufce_row_out_{idx};
        (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFCE_ROW #(
            .IS_I_INVERTED({invert_i}),
            .IS_CE_INVERTED({invert_ce}),
            .CE_TYPE("{ce_type}")
            )
        bufce_row_{idx} (
            .I({bufg_in}),
            .O(bufce_row_out_{idx}),
            .CE({ce})
        );""".format(loc=bufce_row['site'],
                     invert_i=np.random.randint(2),
                     invert_ce=np.random.randint(2),
                     ce_type=ce_type,
                     ce=np.random.choice(ce_inputs),
                     bufg_in=bufg_in,
                     idx=idx))

    for idx, bufce_leaf in enumerate(bufce_leafs):
        if np.random.choice([0, 1], p=[.75, .25]):
            continue

        clock_region = bufce_leaf['clock_region']
        if clock_region not in bufce_rows_by_cmt:
            continue

        clock_in_idx = np.random.choice(bufce_rows_by_cmt[clock_region])

        print("""
        (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFCE_LEAF #(
            .IS_I_INVERTED({invert_i}),
            .IS_CE_INVERTED({invert_ce}),
            .CE_TYPE("{ce_type}")
        )
        bufce_leaf_{idx} (
            .I({clock_in}),
            .CE({ce})
        );""".format(loc=bufce_leaf['site'],
                     invert_i=np.random.randint(2),
                     invert_ce=np.random.randint(2),
                     ce_type=np.random.choice(["SYNC", "ASYNC"]),
                     ce=np.random.choice(ce_inputs),
                     idx=idx,
                     clock_in='bufce_row_out_{}'.format(clock_in_idx)))

    print('endmodule')
예제 #17
0
def run():
    parser = argparse.ArgumentParser()
    parser.add_argument('--bits_file', default='design.bits')
    parser.add_argument('--features_file', default='design.features')
    parser.add_argument('--extent_features_file', default=None)
    parser.add_argument('--block_type', default='CLB_IO_CLK')
    parser.add_argument(
        '--zero_feature_enums',
        help=
        "File containing features that are zero enums, and which parameter is the zero."
    )

    args = parser.parse_args()

    zero_features = {}

    if args.zero_feature_enums:
        with open(args.zero_feature_enums) as f:
            for l in f:
                parts = l.strip().split('=')
                assert len(parts) == 2, "Expected line with ="
                zero_features[parts[0]] = parts[1]

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    feature_data = {}
    feature_trees = {}
    if args.extent_features_file:
        with open(args.extent_features_file) as f:
            tile_type = None
            for l in f:
                l = l.strip()

                if l.startswith('.tiletype'):
                    tile_type = l.split(' ')[1]
                    assert tile_type not in feature_data
                    feature_data[tile_type] = set()

                feature_data[tile_type].add(l.strip())

        for tile_type in feature_data:
            features = feature_data[tile_type]

            split_features = []

            for feature in features:
                split_features.append(feature.split('.'))

            split_features.sort(key=lambda x: -len(x))

            tree = FeatureTree(part=tile_type)
            for split_feature in split_features:
                child = tree
                for part in split_feature:
                    child = child[part]

            tree.coalesce()

            feature_trees[tile_type] = tree

    all_features = read_features(args.features_file)

    tile_types = set()
    for _, tile_type in all_features.keys():
        tile_types.add(tile_type)

    for tile_type in tile_types:
        segmk = Segmaker(args.bits_file, bits_per_word=16)
        segmk.set_def_bt(args.block_type)

        tree = feature_trees[tile_type]
        pip_active = {}
        pip_sources = {}
        pip_active_per_tile = {}
        for pip_feature in tree.pip_features():
            dest = pip_feature.part
            assert dest not in pip_active
            assert dest not in pip_sources

            pip_active[dest] = 0

            sources = []
            for child in pip_feature:
                child_feature = pip_feature[child]
                parts = child_feature.full_feature().split('.')
                assert parts[1] == 'PIP'

                if child_feature.is_leaf():
                    sources.append(parts[-1])
                else:
                    src = child_feature.part
                    children = set(child for child in child_feature)
                    assert len(set(('FWD', 'REV')) | children) == 2, children
                    sources.extend([
                        '{}.FWD'.format(src),
                        '{}.REV'.format(src),
                    ])

            pip_sources[dest] = sources

        proto_pip_active = pip_active

        for (tile, a_type), features in all_features.items():
            if tile_type != a_type:
                continue

            loc = grid.loc_of_tilename(tile)
            gridinfo = grid.gridinfo_at_loc(loc)

            if BlockType.CLB_IO_CLK not in gridinfo.bits:
                print('*** WARNING *** Tile {} is missing bits!'.format(tile))
                continue

            pip_active = dict(proto_pip_active)

            indicies = {}

            for l in features:
                parts = l.split('.')
                feature = tree.find_feature(l)

                # Mark active indices on vector features
                if feature.index is not None and len(feature.index) > 1:
                    current_index = int(parts[-1].split('[')[1][:-1])

                    if id(feature) not in indicies:
                        indicies[id(feature)] = (feature, set())
                    indicies[id(feature)][1].add(current_index)

                segmk.add_tile_tag(tile, l, 1)

                if parts[0] == "PIP":
                    assert feature.is_leaf()
                    assert parts[1] in pip_active
                    pip_active[parts[1]] = 1
                elif feature.is_leaf() and feature.index is None:
                    parent = feature.parent

                    should_emit_enum_zero = True

                    # Only emit 0 tags if this is not a zero feature, or if
                    # this is feature is the zero enum.
                    if parent.part in zero_features:
                        if zero_features[parent.part] != feature.part:
                            should_emit_enum_zero = False
                            parts = parent.full_feature().split('.')[1:]
                            parts.append(zero_features[parent.part])
                            s = '.'.join(parts)
                            segmk.add_tile_tag(tile, s, 0)

                    if should_emit_enum_zero:
                        for child in parent:
                            child_feature = parent[child]
                            if child_feature is not feature:
                                if not child_feature.is_leaf():
                                    continue

                                parts = child_feature.full_feature().split(
                                    '.')[1:]
                                s = '.'.join(parts)
                                segmk.add_tile_tag(tile, s, 0)

            for feature, active_indicies in indicies.values():
                min_index = min(active_indicies)
                if min(feature.index) + 1 == min_index:
                    min_index = min(feature.index)

                max_index = max(active_indicies)
                if max(feature.index) - 1 == max_index:
                    max_index = max(feature.index)

                s = '.'.join(feature.full_feature().split('.')[1:])
                s = '['.join(s.split('[')[:-1])

                for idx in range(min_index, max_index + 1):
                    if idx in active_indicies:
                        continue

                    segmk.add_tile_tag(tile, '{}[{}]'.format(s, idx), 0)

            # Output disable features for pips.
            pip_active_per_tile[tile] = pip_active

        segmk.compile()
        segmk.write(allow_empty=True,
                    extra_tags=output_empty_pips(tree, pip_sources,
                                                 pip_active_per_tile))
예제 #18
0
def print_top(seed, f=sys.stdout):
    np.random.seed(seed)

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    bufgces_by_tile = {}
    rclk_int_l = []
    slices_by_tile = {}

    for tile in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile)

        if tile.startswith("RCLK_INT_L"):
            rclk_int_l.append((loc.grid_x, loc.grid_y, tile))

        gridinfo = grid.gridinfo_at_loc(loc)
        for site, site_type in gridinfo.sites.items():
            if ("BUFGCE" in site or "BUFGCTRL" in site) and "HDIO" not in site:
                if tile not in bufgces_by_tile:
                    bufgces_by_tile[tile] = []
                bufgces_by_tile[tile].append((site, site_type))
            elif "SLICE_" in site:
                slices_by_tile[loc.grid_x, loc.grid_y] = site

    halfcolumn_slices_by_row = {}
    for x, y, rclk in rclk_int_l:
        hc_up = []
        hc_down = []
        if y not in halfcolumn_slices_by_row:
            halfcolumn_slices_by_row[y] = []

        for yplus in range(y + 1, y + 31):
            if (x, yplus) not in grid.loc:
                continue

            tile = grid.tilename_at_loc((x, yplus))
            if not tile.startswith("INT_"):
                break

            slice_x = x + np.random.choice([+1, -1])
            if (slice_x, yplus) not in slices_by_tile:
                continue
            hc_up.append(slices_by_tile[slice_x, yplus])

        for yminus in range(y - 1, y - 31, -1):
            if (x, yminus) not in grid.loc:
                continue

            tile = grid.tilename_at_loc((x, yminus))
            if not tile.startswith("INT_"):
                break
            slice_x = x + np.random.choice([+1, -1])
            if (slice_x, yminus) not in slices_by_tile:
                continue
            hc_down.append(slices_by_tile[slice_x, yminus])

        halfcolumn_slices_by_row[y].append(hc_up)
        halfcolumn_slices_by_row[y].append(hc_down)

    buffers = []

    tiles = list(sorted(bufgces_by_tile.keys()))
    np.random.shuffle(tiles)

    for tile in tiles:
        shuffled_bufs = list(bufgces_by_tile[tile])
        np.random.shuffle(shuffled_bufs)
        target_type = np.random.choice(
            ["BUFGCE", "BUFGCE_DIV", "BUFGCTRL"]
            if len(buffers) > 0 else ["BUFGCE", "BUFGCE_DIV"])
        tile_buffers = np.random.randint(6)
        found_buffers = 0
        for buf, buftype in shuffled_bufs:
            if found_buffers >= tile_buffers:
                break
            if buftype != target_type:
                continue
            buffers.append((buf, buftype))
            found_buffers += 1

    def random_inversion(pins):
        return ", ".join(
            [".IS_%s_INVERTED(%d)" % (p, np.random.randint(2)) for p in pins])

    def random_control(pins):
        return ", ".join(
            [".%s(aux[%d])" % (p, np.random.randint(10)) for p in pins])

    CCIO_CLKS = 24
    print(
        "module top(input [{CCIO_CLKS}-1:0] i, input [9:0] aux, input d, output o, q);"
        .format(CCIO_CLKS=CCIO_CLKS),
        file=f)
    print("    wire [71:0] r;", file=f)
    # print("    assign r[0] = i;", file=f)
    # print("    assign o = r[%d];" % N, file=f)
    # for i in range(N):
    # 	bg, buftype = buffers[i]
    # 	#print("(* LOC=\"%s\" *)" % bg, file=f)
    # 	if "BUFGCTRL" in buftype:
    # 		print("    BUFGCTRL #(", file=f)
    # 		print("        %s," % random_inversion(["I0", "I1", "S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f)
    # 		print("        .INIT_OUT(%d), .PRESELECT_I0(\"%s\"), .PRESELECT_I1(\"%s\")" %
    # 				(np.random.randint(2), np.random.choice(["TRUE", "FALSE"]), np.random.choice(["TRUE", "FALSE"])), file=f)
    # 		print("    ) bufgctrl_%d (" % i, file=f)
    # 		print("        .I0(r[%d]), .I1(r[%d]), " % (i, np.random.randint(i+1)), file=f)
    # 		print("        %s," % random_control(["S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f)
    # 		print("        .O(r[%d])" % (i+1), file=f)
    # 		print("    );", file=f)
    print(
        "    assign r[{CCIO_CLKS}-1:0] = i;".format(CCIO_CLKS=CCIO_CLKS),
        file=f)
    for i in range(12):
        print("    BUFGCE_DIV #(", file=f)
        print("        .BUFGCE_DIVIDE(%d)," % np.random.randint(1, 9), file=f)
        print("        %s" % random_inversion(["I", "CE", "CLR"]), file=f)
        print("    ) bufgce_div_%d (" % i, file=f)
        print("        .I(i[%d])," % i, file=f)
        print("        %s," % random_control(["CE", "CLR"]), file=f)
        print("        .O(r[%d])" % (CCIO_CLKS + i), file=f)
        print("    );", file=f)
    for i in range(12):
        print("    BUFGCE #(", file=f)
        print(
            "        .CE_TYPE(\"%s\")," % np.random.choice(["SYNC", "ASYNC"]),
            file=f)
        print("        %s" % random_inversion(["I", "CE"]), file=f)
        print("    ) bufgce_%d (" % i, file=f)
        print("        .I(i[%d])," % np.random.randint(CCIO_CLKS), file=f)
        print("        %s," % random_control(["CE"]), file=f)
        print("        .O(r[%d])" % (i + 36), file=f)
        print("    );", file=f)

    R2 = 0
    NS = 64
    ffs = ""
    for row, hcs in sorted(halfcolumn_slices_by_row.items()):
        row_clks = np.random.randint(20, 25)
        clks = [np.random.randint(48) for k in range(row_clks)]

        samples = min(len(hcs), NS)
        hi = np.random.choice(range(len(hcs)), size=samples, replace=False)

        halfs = [hcs[hi[k]] for k in range(samples)]
        for h in halfs:
            half_clks = np.random.randint(13, 17)
            rclks = [np.random.choice(clks) for k in range(half_clks)]
            for sl in h:
                ffs += "(* LOC=\"%s\" *) FDCE ff_%d (.C(r[%d]), .CE(aux[%d]), .CLR(~aux[%d]), .D(r2[%d]), .Q(r2[%d]));\n" % (
                    sl, R2, rclks[R2 % len(rclks)], np.random.randint(10),
                    np.random.randint(10), R2, R2 + 1)
                R2 += 1
    print("    wire [%d:0] r2;" % R2, file=f)
    print("    assign r2[0] = d;", file=f)
    print("    assign q = r2[%d];" % R2, file=f)
    print(ffs, file=f)
    print("endmodule", file=f)

    with open("top.tcl", "w") as f:
        print('opt_design', file=f)
예제 #19
0
def main():
    parser = argparse.ArgumentParser(
        description=
        "Reduces raw database dump into prototype tiles, grid, and connections."
    )
    parser.add_argument('--root_dir', required=True)
    parser.add_argument('--output_dir', required=True)
    parser.add_argument('--verify_only', action='store_true')
    parser.add_argument('--ignored_wires')
    parser.add_argument('--max_cpu', type=int, default=10)

    args = parser.parse_args()

    now = datetime.datetime.now
    tiles, nodes = lib.read_root_csv(args.root_dir)

    processes = min(multiprocessing.cpu_count(), args.max_cpu)
    print('{} Running {} processes'.format(now(), processes))
    pool = multiprocessing.Pool(processes=processes)

    tileconn_file = os.path.join(args.output_dir, 'tileconn.json')
    wire_map_file = os.path.join(args.output_dir, 'wiremap.pickle')

    print('{} Reading tilegrid'.format(now()))
    with open(
            os.path.join(util.get_db_root(), util.get_part(),
                         'tilegrid.json')) as f:
        grid = json.load(f)

    if not args.verify_only:
        print('{} Creating tile map'.format(now()))
        grid2, wire_map = generate_tilegrid(pool, tiles)

        # Make sure tilegrid from 005-tilegrid matches tilegrid from
        # generate_tilegrid.
        db_grid_keys = set(grid.keys())
        generated_grid_keys = set(grid2.keys())
        assert db_grid_keys == generated_grid_keys, (db_grid_keys
                                                     ^ generated_grid_keys)

        for tile in db_grid_keys:
            for k in grid2[tile]:
                assert k in grid[tile], k
                assert grid[tile][k] == grid2[tile][k], (tile, k,
                                                         grid[tile][k],
                                                         grid2[tile][k])

        print('{} Estimating tile sizes'.format(now()))
        tile_type_sizes = tile_sizes.guess_tile_type_sizes(grid)

        with open(wire_map_file, 'wb') as f:
            pickle.dump(wire_map, f)

        print('{} Creating tile connections'.format(now()))
        tileconn, raw_node_data = generate_tileconn(pool, nodes, wire_map,
                                                    grid, tile_type_sizes)

        for data in tileconn:
            data['wire_pairs'] = tuple(
                sorted(data['wire_pairs'],
                       key=lambda x: tuple(extract_numbers(s) for s in x)))

        tileconn = tuple(
            sorted(tileconn, key=lambda x:
                   (x['tile_types'], x['grid_deltas'])))

        print('{} Writing tileconn'.format(now()))
        with open(tileconn_file, 'w') as f:
            json.dump(tileconn, f, indent=2, sort_keys=True)
    else:
        with open(wire_map_file, 'rb') as f:
            wire_map = pickle.load(f)

        print('{} Reading raw_node_data'.format(now()))
        raw_node_data = []
        for node_file in progressbar.progressbar(nodes):
            with open(node_file) as f:
                raw_node_data.extend(json.load(f)[:-1])

        print('{} Reading tileconn'.format(now()))
        with open(tileconn_file) as f:
            tileconn = json.load(f)

    wire_nodes_file = os.path.join(args.output_dir, 'wire_nodes.pickle')
    if os.path.exists(wire_nodes_file) and args.verify_only:
        with open(wire_nodes_file, 'rb') as f:
            wire_nodes = pickle.load(f)
    else:
        print("{} Connecting wires to verify tileconn".format(now()))
        wire_nodes = connect_wires(grid, tileconn, wire_map)
        with open(wire_nodes_file, 'wb') as f:
            pickle.dump(wire_nodes, f)

    print('{} Verifing tileconn'.format(now()))
    error_nodes = []
    lib.verify_nodes(
        [(node['node'], tuple(wire['wire'] for wire in node['wires'][:-1]))
         for node in raw_node_data], wire_nodes, error_nodes)

    if len(error_nodes) > 0:
        error_nodes_file = os.path.join(args.output_dir, 'error_nodes.json')
        with open(error_nodes_file, 'w') as f:
            json.dump(error_nodes, f, indent=2, sort_keys=True)

        ignored_wires = []
        ignored_wires_file = args.ignored_wires
        if os.path.exists(ignored_wires_file):
            with open(ignored_wires_file) as f:
                ignored_wires = set(l.strip() for l in f)

        if not lib.check_errors(error_nodes, ignored_wires):
            print('{} errors detected, see {} for details.'.format(
                len(error_nodes), error_nodes_file))
            sys.exit(1)
        else:
            print(
                '{} errors ignored because of {}\nSee {} for details.'.format(
                    len(error_nodes), ignored_wires_file, error_nodes_file))
예제 #20
0
def print_top(seed):
    np.random.seed(seed)

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    clocks = ClockColumns(grid)

    disabled_columns = set()
    for key in clocks.columns():
        if np.random.choice([1, 0], p=[.25, .75]):
            disabled_columns.add(key)

    clocks.remove_column(disabled_columns)

    site_to_site_type = {}
    site_to_tile = {}
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site, site_type in gridinfo.sites.items():
            site_to_site_type[site] = site_type
            site_to_tile[site] = tile_name

    bufgs = GlobalClockBuffers('../bufg_outputs.csv')

    slices = sorted(gen_sites(grid))
    np.random.shuffle(slices)

    with open('complete_top.tcl', 'w') as f:
        #print('place_design -directive Quick', file=f)
        print("""
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]
place_design
route_design
""",
              file=f)

    print("""
module top();
        """)

    N_LUTS = 4

    ce_inputs = [0, 1]
    for idx in range(N_LUTS):

        print("""
        wire lut_o_{idx};
        (* BEL="A6LUT", LOC="{loc}", KEEP, DONT_TOUCH *) LUT5 lut{idx} (.O(lut_o_{idx}));
        """.format(idx=idx, loc=slices.pop()))

        ce_inputs.append('lut_o_{}'.format(idx))

    N_GCLK = 1
    bufg_wires = {}
    bufg_str = {}
    for idx in range(N_GCLK):
        bufg, hroute_number = bufgs.random_bufg(np.random.choice)
        site_type = site_to_site_type[bufg]

        if site_type in ['BUFGCE', 'BUFGCE_HDIO']:
            s = """
    wire bufg_o_{idx};
    (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFGCE #(
        .IS_CE_INVERTED({invert_ce}),
        .CE_TYPE("{ce_type}")
        ) bufg_{idx} (
            .CE({ce}),
            .O(bufg_o_{idx})
        );""".format(loc=bufg,
                     idx=idx,
                     invert_ce=np.random.randint(2),
                     ce_type=np.random.choice(["SYNC", "ASYNC"]),
                     ce=np.random.choice(ce_inputs))
        elif site_type == 'BUFGCE_DIV':
            s = """
    wire bufg_o_{idx};
    (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFGCE_DIV #(
        .IS_CE_INVERTED({invert_ce}),
        .CE_TYPE("{ce_type}"),
        .BUFGCE_DIVIDE({bufce_divide})
        ) bufg_{idx} (
            .CE({ce}),
            .CLR({clr}),
            .O(bufg_o_{idx})
        );""".format(loc=bufg,
                     idx=idx,
                     invert_ce=np.random.randint(2),
                     ce_type=np.random.choice(["SYNC", "ASYNC"]),
                     ce=np.random.choice(ce_inputs),
                     clr=np.random.choice(ce_inputs),
                     bufce_divide=np.random.choice(range(1, 9)))
        elif site_type == 'BUFG_PS':
            s = """
    wire bufg_o_{idx};
    (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFG_PS #(
        ) bufg_{idx} (
            .O(bufg_o_{idx})
        );""".format(loc=bufg, idx=idx)
        elif site_type == 'BUFGCTRL':
            preselect_i0 = np.random.randint(2)
            if not preselect_i0:
                preselect_i1 = np.random.randint(2)
            else:
                preselect_i1 = 0

            s0 = np.random.choice(ce_inputs)
            s1 = np.random.choice(ce_inputs)
            if s0 == '0':
                while s1 == '0':
                    s1 = np.random.choice(ce_inputs)

            if s0 == '0' and s1 == '1':
                invert_s0 = np.random.randint(2)
                invert_s1 = 0
            elif s0 == '1' and s1 == '0':
                invert_s1 = np.random.randint(2)
                invert_s0 = 0
            elif s0 == '1' and s1 == '1':
                invert_s0 = np.random.randint(2)
                if invert_s0:
                    invert_s1 = 0
            else:
                invert_s0 = np.random.randint(2)
                invert_s1 = np.random.randint(2)

            s = """
    wire bufg_o_{idx};
    (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFGCTRL #(
        .INIT_OUT({init_out}),
        .IS_CE0_INVERTED({invert_ce0}),
        .IS_CE1_INVERTED({invert_ce1}),
        .IS_S0_INVERTED({invert_s0}),
        .IS_S1_INVERTED({invert_s1}),
        .IS_IGNORE0_INVERTED({invert_ignore0}),
        .IS_IGNORE1_INVERTED({invert_ignore1}),
        .PRESELECT_I0({preselect_i0}),
        .PRESELECT_I1({preselect_i1})
        ) bufg_{idx} (
            .IGNORE0({ignore0}),
            .IGNORE1({ignore1}),
            .S0({s0}),
            .S1({s1}),
            .CE0({ce0}),
            .CE1({ce1}),
            .O(bufg_o_{idx})
        );""".format(
                loc=bufg,
                idx=idx,
                init_out=np.random.randint(2),
                s0=s0,
                s1=s1,
                ce0=np.random.choice(ce_inputs),
                ce1=np.random.choice(ce_inputs),
                ignore0=np.random.choice(ce_inputs),
                ignore1=np.random.choice(ce_inputs),
                invert_ce0=np.random.randint(2),
                invert_ce1=np.random.randint(2),
                invert_s0=invert_s0,
                invert_s1=invert_s1,
                invert_ignore0=np.random.randint(2),
                invert_ignore1=np.random.randint(2),
                preselect_i0=preselect_i0,
                preselect_i1=preselect_i1,
            )
        else:
            assert False, site_type

        bufg_wires[hroute_number] = 'bufg_o_{idx}'.format(idx=idx)
        bufg_str[hroute_number] = s

    bufg_used = set()
    slices = sorted(clocks.sites.keys())

    num_slices = np.random.randint(1, len(slices) + 1)

    for idx, slice_loc in enumerate(slices):
        if idx >= num_slices:
            break

        all_clocks = list(bufg_wires.keys())
        np.random.shuffle(all_clocks)
        while True:
            hroute_number = all_clocks.pop()
            clock_str = bufg_wires[hroute_number]
            if clocks.add_clock(slice_loc, clock_str):
                if hroute_number not in bufg_used:
                    print(bufg_str[hroute_number])
                    bufg_used.add(hroute_number)

                print(
                    '    (* LOC="{loc}", KEEP, DONT_TOUCH *) FDCE ff_{i}(.C({clock_str}));'
                    .format(loc=slice_loc, i=idx, clock_str=clock_str))
                break

    print('endmodule')
예제 #21
0
def print_top(seed):
    np.random.seed(seed)

    options_by_tile = {}

    with open('../permutations.csv') as f:
        for row in csv.DictReader(f):
            tile = row['tile']

            opt = {}

            for bufg_idx in range(MAX_GLOBAL_CLOCKS):
                input_idx = row['bufg{}_input'.format(bufg_idx)]

                if input_idx == "":
                    continue

                opt[bufg_idx] = int(input_idx)

            if tile not in options_by_tile:
                options_by_tile[tile] = []
            options_by_tile[tile].append(opt)

    ps8_pins = sorted(get_ps8_pin_map())
    bus_widths = {}
    for pin in ps8_pins:
        parts = pin.split('/')[-1].split('[')

        if len(parts) == 1:
            bus_widths[parts[0]] = 1
        elif len(parts) == 2:
            if parts[0] not in bus_widths:
                bus_widths[parts[0]] = 0

            width = int(parts[1][:-1]) + 1
            if width > bus_widths[parts[0]]:
                bus_widths[parts[0]] = width
        else:
            assert False, pin

    tiles = ps8_bufg_pin_map_by_tile()
    for tile in tiles:
        tiles[tile].sort()

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    bufgs_by_tile = {}

    for tile in tiles:
        bufgs_by_tile[tile] = []

        gridinfo = grid.gridinfo_at_tilename(tile)

        for site, site_type in gridinfo.sites.items():
            if site_type == 'BUFG_PS':
                bufgs_by_tile[tile].append(site)

    for tile in tiles:
        bufgs_by_tile[tile].sort()
        assert len(bufgs_by_tile[tile]) == MAX_GLOBAL_CLOCKS, tile

    opins = []
    sinks = []

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

    spec_num = util.specn() - 1

    for tile in tiles:
        opts = options_by_tile[tile]

        if spec_num < len(opts):
            # Use permutation from permutations.csv
            opt = opts[spec_num]
        else:
            # Use a random permutation.
            opt = {}
            bufgs = set(range(MAX_GLOBAL_CLOCKS))
            for input_idx in range(len(tiles[tile])):
                bufg_idx = np.random.choice(sorted(bufgs))
                bufgs.remove(bufg_idx)
                opt[bufg_idx] = input_idx

        for bufg_idx, input_idx in opt.items():
            bufg = bufgs_by_tile[tile][bufg_idx]
            input_pin = tiles[tile][input_idx]

            idx = len(opins)
            print("""
            wire bufg_{idx};

            (* LOC="{loc}", KEEP, DONT_TOUCH *)
            BUFG_PS bufg_{idx} (
                .I(bufg_{idx})
            );
            """.format(loc=bufg, idx=idx))

            sinks.append('bufg_{idx}'.format(idx=idx))
            opins.append(input_pin)

    busses = set()
    for pin in opins:
        busses.add(pin.split('[')[0])

    for bus in busses:
        print('wire [{width}-1:0] {bus};'.format(
            bus=bus, width=bus_widths[bus]))

    print('PS8 ps8 (')

    connections = []
    for bus in busses:
        connections.append('  .{bus}({bus})'.format(bus=bus))
    print(',\n'.join(connections))

    print('\n);')

    for pin, sink in zip(opins, sinks):
        print('assign {sink} = {pin};'.format(pin=pin, sink=sink))

    print('endmodule')
예제 #22
0
def gen_sites():
    """ RCLK_DSP_INTF_CLKBUF_L connects HDISTR and HROUTE clock resources from
    neighbooring left/right clock regions.

    gen_sites finds RCLK_DSP_INTF_CLKBUF_L tiles, and then locates a BUFCE_ROW
    driver from the left side, and then finds a BUFCE_ROW driver from the
    right side that drives the same HDISTR.  A BUFCE_ROW only drives a
    particular HDISTR node within the clock region (0-23).

    A random BUFCE_LEAF from both the left and the right of
    RCLK_DSP_INTF_CLKBUF_L are chosen.  This randomness decouples
    non-RCLK_DSP_INTF_CLKBUF_L bits from the solution.
    """
    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    # Create a mapping from site to tile
    site_to_tile = {}
    for tile_name in grid.tiles():
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)
        for site in gridinfo.sites:
            site_to_tile[site] = tile_name

    # Load BUFCE_ROW site data, which includes:
    # - The BUFCE_ROW site name
    # - The clock region the BUFCE_ROW participates in
    # - Which HDISTR wire is driven by the BUFCE_ROW.
    loc_to_bufce_row = {}
    with open('../active_bufce_row.csv') as f:
        for bufce_row in csv.DictReader(f):
            site = bufce_row['site']
            tile = site_to_tile[site]
            loc = grid.loc_of_tilename(tile)

            if loc not in loc_to_bufce_row:
                loc_to_bufce_row[loc] = []

            loc_to_bufce_row[loc].append(bufce_row)

    o = []
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        if gridinfo.tile_type != "RCLK_DSP_INTF_CLKBUF_L":
            continue

        # Find a BUFCE_ROW driver that is left of the current
        # RCLK_DSP_INTF_CLKBUF_L tile.
        x, y = loc
        left_bufce_out = None
        hdistr_number = None
        while left_bufce_out is None:
            x -= 1
            if (x, y) in loc_to_bufce_row:
                left_bufce_out = loc_to_bufce_row[(x, y)][0]['site']
                hdistr_number = loc_to_bufce_row[(x, y)][0]['hdistr_number']
                break

        # Find a BUFCE_ROW driver that is right of the current
        # RCLK_DSP_INTF_CLKBUF_L tile, and is on the same HDISTR wire.
        x, y = loc
        right_bufce_out = None
        while right_bufce_out is None:
            x += 1
            if (x, y) in loc_to_bufce_row:
                for bufce_row in loc_to_bufce_row[(x, y)]:
                    if hdistr_number == bufce_row['hdistr_number']:
                        right_bufce_out = bufce_row['site']
                        break

        # Find a random BUFCE_LEAF driver that is to the left of the current
        # RCLK_DSP_INTF_CLKBUF_L.
        x, y = loc
        left_site = None
        while left_site is None:
            x -= 1

            gridinfo = grid.gridinfo_at_loc((x, y))
            for site, site_type in gridinfo.sites.items():
                if site_type == 'BUFCE_LEAF':
                    left_site = get_random_leaf(gridinfo)
                    break

        # Find a random BUFCE_LEAF driver that is to the right of the current
        # RCLK_DSP_INTF_CLKBUF_L.
        x, y = loc
        right_site = None
        while right_site is None:
            x += 1

            gridinfo = grid.gridinfo_at_loc((x, y))
            for site, site_type in gridinfo.sites.items():
                if site_type == 'BUFCE_LEAF':
                    right_site = get_random_leaf(gridinfo)
                    break

        assert left_bufce_out is not None
        assert right_bufce_out is not None
        assert left_site is not None
        assert right_site is not None

        o.append((tile_name, left_bufce_out, right_bufce_out, left_site,
                  right_site))

    return o
예제 #23
0
def print_top(seed):
    np.random.seed(seed)

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    site_to_tile = {}
    site_to_site_type = {}
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site, site_type in gridinfo.sites.items():
            site_to_site_type[site] = site_type
            site_to_tile[site] = tile_name

    bufce_row_drivers = {}

    with open('../active_bufce_row.csv') as f:
        for row in csv.DictReader(f):
            tile = site_to_tile[row['site']]

            gridinfo = grid.gridinfo_at_tilename(tile)
            if gridinfo.tile_type == 'CMT_RIGHT':
                continue

            clock_region = CMT_XY_FUN(row['site_clock_region'])

            key = clock_region, int(row['hdistr_number'])
            assert key not in bufce_row_drivers
            bufce_row_drivers[key] = row['site']

    bufg_drivers = {}

    with open('../bufg_outputs.csv') as f:
        for row in csv.DictReader(f):
            if site_to_site_type[row['site']] != 'BUFGCE_HDIO':
                continue

            clock_region = CMT_XY_FUN(row['clock_region'])
            if clock_region not in bufg_drivers:
                bufg_drivers[clock_region] = []

            bufg_drivers[clock_region].append(row['site'])

    for clock_region in bufg_drivers:
        bufg_drivers[clock_region].sort()
        np.random.shuffle(bufg_drivers[clock_region])

    clock_regions = set()
    for clock_region, _ in bufce_row_drivers.keys():
        clock_regions.add(clock_region)

    for clock_region in bufg_drivers.keys():
        clock_regions.add(clock_region)

    print("""
module top();
        """)

    bufg_routes = []
    for hroute in range(MAX_GLOBAL_CLOCKS):
        if np.random.randint(2):
            continue

        select_clock_regions = sorted(clock_regions)
        np.random.shuffle(select_clock_regions)

        bufg = None
        while len(select_clock_regions) > 0:
            clock_region = select_clock_regions.pop()
            if clock_region not in bufg_drivers:
                continue

            if len(bufg_drivers[clock_region]) > 0:
                bufg = bufg_drivers[clock_region].pop()
                break

        if bufg is None:
            continue

        sel_x, sel_y = clock_region
        clock_regions_for_bufg = []
        for x, y in clock_regions:
            if y == sel_y:
                clock_regions_for_bufg.append((x, y))

        clock_regions_for_bufg.sort()
        np.random.shuffle(clock_regions_for_bufg)

        bufce_row = None
        while True:
            clock_region = clock_regions_for_bufg.pop()
            key = clock_region, hroute

            if key in bufce_row_drivers:
                bufce_row = bufce_row_drivers[key]
                break

        if bufce_row is None:
            continue

        bufg_s, bufg_o_wire = make_bufg(
            site=bufg,
            site_type=site_to_site_type[bufg],
            idx=hroute,
            ce_inputs=['1'],
            randlib=np.random)

        print(bufg_s)

        print("""
        (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFCE_ROW row{idx} (
            .I({bufg_o_wire})
        );""".format(
            loc=bufce_row,
            idx=hroute,
            bufg_o_wire=bufg_o_wire,
        ))

        bufg_routes.append((bufg, bufce_row, hroute))

    print('endmodule')

    with open('complete_top.tcl', 'w') as f:
        print(
            """
source $::env(URAY_UTILS_DIR)/utils.tcl
write_checkpoint -force design_reset.dcp
close_design
open_checkpoint design_reset.dcp
""",
            file=f)

        for bufg, bufce_row, hroute in bufg_routes:
            if np.random.randint(2):
                print(
                    "route_bufg_to_bufce_row_via_opposite_wire {bufg} {bufce_row} {hroute}"
                    .format(bufg=bufg, bufce_row=bufce_row, hroute=hroute),
                    file=f)

        print("""
route_design
""", file=f)
예제 #24
0
def print_top(seed):
    np.random.seed(seed)

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    clocks = ClockColumns(grid)

    disabled_columns = set()
    for key in clocks.columns():
        if np.random.choice([1, 0], p=[.25, .75]):
            disabled_columns.add(key)

    clocks.remove_column(disabled_columns)

    site_to_site_type = {}
    site_to_tile = {}
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site, site_type in gridinfo.sites.items():
            site_to_site_type[site] = site_type
            site_to_tile[site] = tile_name

    bufgs = GlobalClockBuffers('../bufg_outputs.csv')

    slices = sorted(gen_sites(grid))
    np.random.shuffle(slices)

    with open('complete_top.tcl', 'w') as f:
        print("""
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]
place_design
route_design
""",
              file=f)

    print("""
module top();
        """)

    N_LUTS = 4

    ce_inputs = [0, 1]
    for idx in range(N_LUTS):

        print("""
        wire lut_o_{idx};
        (* BEL="A6LUT", LOC="{loc}", KEEP, DONT_TOUCH *) LUT5 lut{idx} (.O(lut_o_{idx}));
        """.format(idx=idx, loc=slices.pop()))

        ce_inputs.append('lut_o_{}'.format(idx))

    N_GCLK = np.random.randint(1, MAX_GLOBAL_CLOCKS)
    assert N_GCLK <= MAX_GLOBAL_CLOCKS
    assert N_GCLK >= 1
    bufg_wires = {}
    bufg_str = {}
    for idx in range(N_GCLK):
        bufg, hroute_number = bufgs.random_bufg(np.random.choice)

        site_type = site_to_site_type[bufg]
        bufg_str[hroute_number], bufg_wires[hroute_number] = make_bufg(
            bufg, site_type, idx, ce_inputs, np.random)

    bufg_used = set()
    slices = sorted(clocks.sites.keys())

    num_slices = np.random.randint(1, len(slices) + 1)

    for idx, slice_loc in enumerate(slices):
        if idx >= num_slices:
            break

        all_clocks = list(bufg_wires.keys())
        np.random.shuffle(all_clocks)
        while True:
            hroute_number = all_clocks.pop()
            clock_str = bufg_wires[hroute_number]
            if clocks.add_clock(slice_loc, clock_str):
                if hroute_number not in bufg_used:
                    print(bufg_str[hroute_number])
                    bufg_used.add(hroute_number)

                print(
                    '    (* LOC="{loc}", KEEP, DONT_TOUCH *) FDCE ff_{i}(.C({clock_str}));'
                    .format(loc=slice_loc, i=idx, clock_str=clock_str))
                break

    print('endmodule')
예제 #25
0
def print_top(seed):
    np.random.seed(seed)

    db = Database(util.get_db_root(), util.get_part())
    grid = db.grid()

    site_to_tile = {}
    site_to_site_type = {}
    for tile_name in sorted(grid.tiles()):
        loc = grid.loc_of_tilename(tile_name)
        gridinfo = grid.gridinfo_at_loc(loc)

        for site, site_type in gridinfo.sites.items():
            site_to_site_type[site] = site_type
            site_to_tile[site] = tile_name

    bufce_leaf_drivers = {}
    with open('../bufce_leaf_clock_regions.csv') as f:
        for row in csv.DictReader(f):
            clock_region = CMT_XY_FUN(row['clock_region'])

            if clock_region not in bufce_leaf_drivers:
                bufce_leaf_drivers[clock_region] = []

            bufce_leaf_drivers[clock_region].append(row['site'])

    for clock_region in bufce_leaf_drivers:
        bufce_leaf_drivers[clock_region].sort()
        np.random.shuffle(bufce_leaf_drivers[clock_region])

    bufg_drivers = {}
    with open('../bufg_outputs.csv') as f:
        for row in csv.DictReader(f):
            if site_to_site_type[row['site']] != 'BUFGCE_HDIO':
                continue

            clock_region = CMT_XY_FUN(row['clock_region'])
            if clock_region not in bufg_drivers:
                bufg_drivers[clock_region] = []

            bufg_drivers[clock_region].append(row['site'])

    for clock_region in bufg_drivers:
        bufg_drivers[clock_region].sort()
        np.random.shuffle(bufg_drivers[clock_region])

    clock_regions = set()
    for clock_region in bufg_drivers.keys():
        clock_regions.add(clock_region)

    print("""
module top();
        """)

    pair_idx = 0

    bufg_hdistr_sets = []
    for clock_region in bufg_drivers.keys():
        hdistrs_avail = list(range(MAX_GLOBAL_CLOCKS))
        np.random.shuffle(hdistrs_avail)

        for bufg in bufg_drivers[clock_region]:
            hdistr = hdistrs_avail.pop()

            bufg_s, bufg_o_wire = make_bufg(site=bufg,
                                            site_type=site_to_site_type[bufg],
                                            idx=pair_idx,
                                            ce_inputs=['1'],
                                            randlib=np.random)

            print(bufg_s)

            bufce_leaf = bufce_leaf_drivers[clock_region].pop()
            print("""
            (* LOC="{loc}", KEEP, DONT_TOUCH *) BUFCE_LEAF bufce_leaf_{idx} (
                .I({clock_in})
            );""".format(loc=bufce_leaf, idx=pair_idx, clock_in=bufg_o_wire))

            bufg_hdistr_sets.append((bufg, bufce_leaf, hdistr))
            pair_idx += 1

    print('endmodule')

    with open('complete_top.tcl', 'w') as f:
        print("""
source $::env(URAY_UTILS_DIR)/utils.tcl
write_checkpoint -force design_reset.dcp
close_design
open_checkpoint design_reset.dcp
""",
              file=f)

        for (bufg, bufce_leaf, hdistr) in bufg_hdistr_sets:
            print(
                'route_bufg_to_bufce_leaf {bufg} {bufce_leaf} {hdistr}'.format(
                    bufg=bufg, bufce_leaf=bufce_leaf, hdistr=hdistr),
                file=f)

        print("""
route_design
""", file=f)