Esempio n. 1
0
def test_dump_pnr():
    num_tracks = 2
    addr_width = 8
    data_width = 32
    bit_widths = [1, 16]

    tile_id_width = 16

    chip_size = 2
    track_length = 1

    # creates all the cores here
    # we don't want duplicated cores when snapping into different interconnect
    # graphs
    cores = {}
    for x in range(chip_size):
        for y in range(chip_size):
            cores[(x, y)] = DummyCore()

    def create_core(xx: int, yy: int):
        return cores[(xx, yy)]

    in_conn = []
    out_conn = []
    for side in SwitchBoxSide:
        in_conn.append((side, SwitchBoxIO.SB_IN))
        out_conn.append((side, SwitchBoxIO.SB_OUT))

    pipeline_regs = []
    for track in range(num_tracks):
        for side in SwitchBoxSide:
            pipeline_regs.append((track, side))

    ics = {}
    for bit_width in bit_widths:
        ic = create_uniform_interconnect(chip_size,
                                         chip_size,
                                         bit_width,
                                         create_core, {
                                             f"data_in_{bit_width}b": in_conn,
                                             f"data_out_{bit_width}b": out_conn
                                         }, {track_length: num_tracks},
                                         SwitchBoxType.Disjoint,
                                         pipeline_reg=pipeline_regs)
        ics[bit_width] = ic

    interconnect = Interconnect(ics,
                                addr_width,
                                data_width,
                                tile_id_width,
                                lift_ports=True)

    design_name = "test"
    with tempfile.TemporaryDirectory() as tempdir:
        interconnect.dump_pnr(tempdir, design_name)

        assert os.path.isfile(os.path.join(tempdir, f"{design_name}.info"))
        assert os.path.isfile(os.path.join(tempdir, "1.graph"))
        assert os.path.isfile(os.path.join(tempdir, "16.graph"))
        assert os.path.isfile(os.path.join(tempdir, f"{design_name}.layout"))
Esempio n. 2
0
def create_dummy_cgra(chip_size, num_tracks, reg_mode, wiring, num_cfg=1):
    addr_width = 8
    data_width = 32
    bit_widths = [1, 16]
    tile_id_width = 16
    track_length = 1
    # creates all the cores here
    # we don't want duplicated cores when snapping into different interconnect
    # graphs
    cores = {}
    for x in range(chip_size):
        for y in range(chip_size):
            cores[(x, y)] = DummyCore()

    def create_core(xx: int, yy: int):
        return cores[(xx, yy)]

    in_conn = []
    out_conn = []
    for side in SwitchBoxSide:
        in_conn.append((side, SwitchBoxIO.SB_IN))
        out_conn.append((side, SwitchBoxIO.SB_OUT))
    pipeline_regs = []
    for track in range(num_tracks):
        for side in SwitchBoxSide:
            pipeline_regs.append((track, side))
    # if reg mode is off, reset to empty
    if not reg_mode:
        pipeline_regs = []
    ics = {}
    for bit_width in bit_widths:
        ic = create_uniform_interconnect(chip_size, chip_size, bit_width,
                                         create_core, {
                                             f"data_in_{bit_width}b": in_conn,
                                             f"data_out_{bit_width}b": out_conn
                                         }, {track_length: num_tracks},
                                         SwitchBoxType.Disjoint, pipeline_regs)
        ics[bit_width] = ic
    interconnect = Interconnect(ics,
                                addr_width,
                                data_width,
                                tile_id_width,
                                lift_ports=True)
    # finalize the design
    interconnect.finalize()
    # wiring
    if wiring == GlobalSignalWiring.Fanout:
        apply_global_fanout_wiring(interconnect, IOSide.None_)
    elif wiring == GlobalSignalWiring.Meso:
        apply_global_meso_wiring(interconnect, IOSide.None_)
    else:
        assert wiring == GlobalSignalWiring.ParallelMeso
        apply_global_parallel_meso_wiring(interconnect, IOSide.None_, num_cfg)

    return bit_widths, data_width, ics, interconnect
Esempio n. 3
0
def test_1x1(double_buffer):
    ics = {}
    in_conn = []
    out_conn = []
    addr_width = 8
    data_width = 32
    for side in SwitchBoxSide:
        in_conn.append((side, SwitchBoxIO.SB_IN))
        out_conn.append((side, SwitchBoxIO.SB_OUT))

    core = DummyCore()

    for bit_width in {1, 16}:
        ic = create_uniform_interconnect(1, 1, bit_width,
                                         lambda _, __: core,
                                         {f"data_in_{bit_width}b": in_conn,
                                          f"data_out_{bit_width}b": out_conn},
                                         {1: 2},
                                         SwitchBoxType.Disjoint)
        ics[bit_width] = ic
    interconnect = Interconnect(ics, addr_width, data_width, 16,
                                lift_ports=True, double_buffer=double_buffer)
    interconnect.finalize()
    apply_global_fanout_wiring(interconnect)
    circuit = interconnect.circuit()
    with tempfile.TemporaryDirectory() as tempdir:
        filename = os.path.join(tempdir, "test1x1")
        magma.compile(filename, circuit, output="coreir-verilog")
    # test routing for 1x1
    compares = {}
    for seed in {0, 1}:
        routing_result, _ = route_one_tile(interconnect, 0, 0,
                                           ports=["data_in_16b",
                                                  "data_out_16b"],
                                           seed=seed)
        # routing result ordering is the same as ports
        assert len(routing_result) == 2
        bs = interconnect.get_route_bitstream(routing_result)
        assert len(bs) > 0
        compares[seed] = bs
    for i in range(2):
        assert compares[0][i] != compares[1][i]
Esempio n. 4
0
def create_cgra(width: int, height: int, io_sides: IOSide,
                add_reg: bool = True,
                mem_ratio: Tuple[int, int] = (1, 4),
                reg_addr_width: int = 8,
                config_data_width: int = 32,
                tile_id_width: int = 16,
                num_tracks: int = 5,
                add_pd: bool = True,
                use_sram_stub: bool = True,
                hi_lo_tile_id: bool = True,
                pass_through_clk: bool = True,
                global_signal_wiring: GlobalSignalWiring =
                GlobalSignalWiring.Meso,
                standalone: bool = False,
                switchbox_type: SwitchBoxType = SwitchBoxType.Imran,
                port_conn_override: Dict[str,
                                         List[Tuple[SwitchBoxSide,
                                                    SwitchBoxIO]]] = None):
    # currently only add 16bit io cores
    bit_widths = [1, 16]
    track_length = 1

    # compute the actual size
    width, height = get_actual_size(width, height, io_sides)
    # these values are inclusive
    x_min, x_max, y_min, y_max = get_array_size(width, height, io_sides)
    # compute ratio
    tile_max = mem_ratio[-1]
    mem_tile_ratio = tile_max - mem_ratio[0]

    # creates all the cores here
    # we don't want duplicated cores when snapping into different interconnect
    # graphs
    cores = {}
    for x in range(width):
        for y in range(height):
            # empty corner
            if x in range(x_min) and y in range(y_min):
                core = None
            elif x in range(x_min) and y in range(y_max + 1, height):
                core = None
            elif x in range(x_max + 1, width) and y in range(y_min):
                core = None
            elif x in range(x_max + 1, width) and y in range(y_max + 1, height):
                core = None
            elif x in range(x_min) \
                    or x in range(x_max + 1, width) \
                    or y in range(y_min) \
                    or y in range(y_max + 1, height):
                core = IOCore()
            else:
                core = MemCore(use_sram_stub=use_sram_stub) if \
                    ((x - x_min) % tile_max >= mem_tile_ratio) else \
                    PeakCore(PE_fc)

            cores[(x, y)] = core

    def create_core(xx: int, yy: int):
        return cores[(xx, yy)]

    # Specify input and output port connections.
    inputs = set()
    outputs = set()
    for core in cores.values():
        # Skip IO cores.
        if core is None or isinstance(core, IOCore):
            continue
        inputs |= {i.qualified_name() for i in core.inputs()}
        outputs |= {o.qualified_name() for o in core.outputs()}

    # This is slightly different from the original CGRA. Here we connect
    # input to every SB_IN and output to every SB_OUT.
    port_conns = {}
    in_conn = [(side, SwitchBoxIO.SB_IN) for side in SwitchBoxSide]
    out_conn = [(side, SwitchBoxIO.SB_OUT) for side in SwitchBoxSide]
    port_conns.update({input_: in_conn for input_ in inputs})
    port_conns.update({output: out_conn for output in outputs})

    if port_conn_override is not None:
        port_conns.update(port_conn_override)

    pipeline_regs = []
    for track in range(num_tracks):
        for side in SwitchBoxSide:
            pipeline_regs.append((track, side))
    # if reg mode is off, reset to empty
    if not add_reg:
        pipeline_regs = []
    ics = {}

    track_list = list(range(num_tracks))
    io_in = {"f2io_1": [0], "f2io_16": [0]}
    io_out = {"io2f_1": track_list, "io2f_16": track_list}

    for bit_width in bit_widths:
        if io_sides & IOSide.None_:
            io_conn = None
        else:
            io_conn = {"in": io_in, "out": io_out}
        ic = create_uniform_interconnect(width, height, bit_width,
                                         create_core,
                                         port_conns,
                                         {track_length: num_tracks},
                                         switchbox_type,
                                         pipeline_regs,
                                         io_sides=io_sides,
                                         io_conn=io_conn)
        ics[bit_width] = ic

    interconnect = Interconnect(ics, reg_addr_width, config_data_width,
                                tile_id_width,
                                lift_ports=standalone,
                                stall_signal_width=1)
    if hi_lo_tile_id:
        tile_id_physical(interconnect)
    if add_pd:
        add_power_domain(interconnect)

    interconnect.finalize()
    if global_signal_wiring == GlobalSignalWiring.Meso:
        apply_global_meso_wiring(interconnect, io_sides=io_sides)
    elif global_signal_wiring == GlobalSignalWiring.Fanout:
        apply_global_fanout_wiring(interconnect, io_sides=io_sides)
    elif global_signal_wiring == GlobalSignalWiring.ParallelMeso:
        apply_global_meso_wiring(interconnect, io_sides=io_sides)
    if add_pd:
        add_aon_read_config_data(interconnect)

    if pass_through_clk:
        clk_physical(interconnect)

    return interconnect
Esempio n. 5
0
def test_uniform(chip_size: int, num_track: int, track_width):
    # USAGE
    track_length = 1

    def dummy_col(_: int, __: int):
        return DummyCore()

    in_conn = [(SwitchBoxSide.WEST, SwitchBoxIO.SB_IN),
               (SwitchBoxSide.WEST, SwitchBoxIO.SB_OUT)]
    out_conn = [(SwitchBoxSide.EAST, SwitchBoxIO.SB_OUT),
                (SwitchBoxSide.WEST, SwitchBoxIO.SB_OUT)]
    ic = create_uniform_interconnect(chip_size, chip_size, track_width,
                                     dummy_col, {
                                         "data_in": in_conn,
                                         "data_out": out_conn
                                     }, {track_length: num_track},
                                     SwitchBoxType.Disjoint)

    # TESTS
    for x in range(chip_size):
        for y in range(chip_size):
            assert_tile_coordinate(ic[x, y], x, y)
    # since we already covered the tests on individual tiles
    # we will focus on the interconnect between each tiles here
    # we first test horizontal connections
    for x in range(0, chip_size - 1):
        for y in range(chip_size):
            tile_from = ic[x, y]
            tile_to = ic[x + track_length, y]
            assert tile_from in ic
            assert tile_to in ic
            for track in range(num_track):
                # get individual sb mux
                tile_from_sb = tile_from.get_sb(SwitchBoxSide.EAST, track,
                                                SwitchBoxIO.SB_OUT)
                tile_to_sb = tile_to.get_sb(SwitchBoxSide.WEST, track,
                                            SwitchBoxIO.SB_IN)
                assert tile_from_sb in ic and tile_to_sb in ic
                assert tile_to_sb in tile_from_sb
                # reverse direction
                tile_from_sb = tile_to.get_sb(SwitchBoxSide.WEST, track,
                                              SwitchBoxIO.SB_OUT)
                tile_to_sb = tile_from.get_sb(SwitchBoxSide.EAST, track,
                                              SwitchBoxIO.SB_IN)
                assert tile_from_sb in ic and tile_to_sb in ic
                assert tile_to_sb in tile_from_sb

    # now for the vertical connections
    for x in range(chip_size):
        for y in range(0, chip_size - 1):
            tile_from = ic[x, y]
            tile_to = ic[x, y + track_length]
            assert tile_from in ic
            assert tile_to in ic
            for track in range(num_track):
                # get individual sb mux
                tile_from_sb = tile_from.get_sb(SwitchBoxSide.SOUTH, track,
                                                SwitchBoxIO.SB_OUT)
                tile_to_sb = tile_to.get_sb(SwitchBoxSide.NORTH, track,
                                            SwitchBoxIO.SB_IN)
                assert tile_from_sb in ic and tile_to_sb in ic
                assert tile_to_sb in tile_from_sb
                # reverse direction
                tile_from_sb = tile_to.get_sb(SwitchBoxSide.NORTH, track,
                                              SwitchBoxIO.SB_OUT)
                tile_to_sb = tile_from.get_sb(SwitchBoxSide.SOUTH, track,
                                              SwitchBoxIO.SB_IN)
                assert tile_from_sb in ic and tile_to_sb in ic
                assert tile_to_sb in tile_from_sb
Esempio n. 6
0
def create_cgra(chip_size: int, add_io: bool = False, cores_input=None):
    # currently only add 16bit io cores
    num_tracks = 2
    reg_mode = True
    addr_width = 8
    data_width = 32
    bit_widths = [1, 16]
    tile_id_width = 16
    track_length = 1
    margin = 0 if not add_io else 1
    chip_size += 2 * margin
    # recalculate the margin
    # creates all the cores here
    # we don't want duplicated cores when snapping into different interconnect
    # graphs
    if cores_input is None:
        cores_input = {}
    cores = {}
    for x in range(chip_size):
        for y in range(chip_size):
            if (x, y) in cores_input:
                # allow it to override
                cores[(x, y)] = cores_input[(x, y)]
                continue
            # empty corner
            if x in range(margin) and y in range(margin):
                core = None
            elif x in range(margin) and y in range(chip_size - margin,
                                                   chip_size):
                core = None
            elif x in range(chip_size - margin,
                            chip_size) and y in range(margin):
                core = None
            elif x in range(chip_size - margin,
                            chip_size) and y in range(chip_size - margin,
                                                      chip_size):
                core = None
            elif x in range(margin) \
                    or x in range(chip_size - margin, chip_size) \
                    or y in range(margin) \
                    or y in range(chip_size - margin, chip_size):
                if x == margin or y == margin:
                    core = IO16bit()
                else:
                    core = IO1bit()
            else:
                core = MemoryCore(1024) if ((x - margin) % 2 == 1) else \
                    PeCore()
            cores[(x, y)] = core

    def create_core(xx: int, yy: int):
        return cores[(xx, yy)]

    # specify input and output port connections
    inputs = ["data0", "data1", "bit0", "bit1", "bit2", "data_in",
              "addr_in", "flush", "ren_in", "wen_in", "data_in_16b", "wen",
              "ren", "addr"]
    outputs = ["out", "outb", "data_out", "data_out_16b"]
    # this is slightly different from the chip we tape out
    # here we connect input to every SB_IN and output to every SB_OUT
    port_conns = {}
    in_conn = []
    out_conn = []
    for side in SwitchBoxSide:
        in_conn.append((side, SwitchBoxIO.SB_IN))
        out_conn.append((side, SwitchBoxIO.SB_OUT))
    for input_port in inputs:
        port_conns[input_port] = in_conn
    for output_port in outputs:
        port_conns[output_port] = out_conn
    pipeline_regs = []
    for track in range(num_tracks):
        for side in SwitchBoxSide:
            pipeline_regs.append((track, side))
    # if reg mode is off, reset to empty
    if not reg_mode:
        pipeline_regs = []
    ics = {}

    sides = IOSide.North | IOSide.East | IOSide.South | IOSide.West

    io_in = {"f2io_1": [1], "f2io_16": [0]}
    io_out = {"io2f_1": [1], "io2f_16": [0]}
    for bit_width in bit_widths:
        if add_io:
            io_conn = {"in": io_in, "out": io_out}
        else:
            io_conn = None
        ic = create_uniform_interconnect(chip_size, chip_size, bit_width,
                                         create_core,
                                         port_conns,
                                         {track_length: num_tracks},
                                         SwitchBoxType.Disjoint,
                                         pipeline_regs,
                                         io_sides=sides,
                                         io_conn=io_conn)
        ics[bit_width] = ic

    interconnect = Interconnect(ics, addr_width, data_width, tile_id_width)

    return interconnect