Ejemplo n.º 1
0
def clk_physical(interconnect: Interconnect):
    for (x, y) in interconnect.tile_circuits:
        tile = interconnect.tile_circuits[(x, y)]
        tile_core = tile.core
        # We only want to do this on PE and memory tiles
        if isinstance(tile_core, IOCore) or tile_core is None:
            continue
        orig_in_port = tile.ports.clk
        orig_out_port = tile.ports.clk_out
        # Remove the pass through connection that already exists
        tile.remove_wire(orig_in_port, orig_out_port)
        # Create a new pass through clock input
        tile.add_port("clk_pass_through", magma.In(magma.Clock))
        pass_through_input = tile.ports.clk_pass_through
        # Create new pass through output
        pass_through_output = pass_signal_through(tile, pass_through_input)
        # Connect new clk pass through input to old pass through output
        tile.wire(pass_through_input, orig_out_port)
        # For top row tiles, connect new clk input to global clock
        if y < 2:
            interconnect.wire(interconnect.ports.clk,
                              pass_through_input)
        # For other tiles, connect new clk input to 
        # pass through output of tile above.
        else:
            tile_above = interconnect.tile_circuits[(x, y-1)]
            interconnect.wire(tile_above.ports.clk_pass_through_out,
                              pass_through_input)
def config_port_pass(interconnect: Interconnect):
    # x coordinate of garnet
    x_min = interconnect.x_min
    x_max = interconnect.x_max
    width = x_max - x_min + 1

    # Add parallel configuration ports to interconnect
    # interconnect must have config port
    assert "config" in interconnect.ports

    interconnect.remove_port("config")
    config_data_width = interconnect.config_data_width
    # config_addr_width is same as config_data_width
    interconnect.add_port(
        "config",
        magma.In(magma.Array[
            width,
            ConfigurationType(config_data_width, config_data_width)]))

    # looping through on a per-column bases
    for x_coor in range(x_min, x_min + width):
        column = interconnect.get_column(x_coor)
        # skip tiles with no config
        column = [entry for entry in column if "config" in entry.ports]
        # wire configuration ports to first tile in column
        interconnect.wire(interconnect.ports.config[x_coor],
                          column[0].ports.config)
def stall_port_pass(interconnect: Interconnect):
    # x coordinate of garnet
    x_min = interconnect.x_min
    x_max = interconnect.x_max
    width = x_max - x_min + 1

    # Add cgra stall
    assert "stall" in interconnect.ports
    stall_signal_width = interconnect.stall_signal_width

    # Currently stall signal is 1 bit
    assert stall_signal_width == 1

    interconnect.remove_port("stall")
    interconnect.add_port(
        "stall", magma.In(magma.Bits[width * interconnect.stall_signal_width]))

    # looping through on a per-column bases
    for x_coor in range(x_min, x_min + width):
        column = interconnect.get_column(x_coor)
        # skip tiles with no stall
        column = [entry for entry in column if "stall" in entry.ports]
        # wire configuration ports to first tile in column
        interconnect.wire(interconnect.ports.stall[x_coor],
                          column[0].ports.stall[0])
Ejemplo n.º 4
0
def tile_id_physical(interconnect: Interconnect):
    tile_id_width = interconnect.tile_id_width
    tie_hi_width = (tile_id_width // 2) + 1
    if (tile_id_width % 2) == 0:
        tie_lo_width = tile_id_width // 2
    else:
        tie_lo_width = (tile_id_width // 2) + 1
    for (x, y) in interconnect.tile_circuits:
        tile = interconnect.tile_circuits[(x, y)]
        tile_core = tile.core
        if isinstance(tile_core, IOCoreValid) or tile_core is None:
            continue
        tile.add_ports(hi=magma.Out(magma.Bits[tie_hi_width]),
                       lo=magma.Out(magma.Bits[tie_lo_width]))
        # wire all hi bits high
        tile.wire(tile.ports.hi, Const((2**tie_hi_width) - 1))
        # wire all lo bits low
        tile.wire(tile.ports.lo, Const(0))
        # Get the correct tile_id value
        x_bv = BitVector[tile_id_width / 2](x)
        y_bv = BitVector[tile_id_width / 2](y)
        tile_id_bv = BitVector.concat(y_bv, x_bv)
        # Disconnect existing constant from tile_id port
        tile_id_port = tile.ports.tile_id
        for wire in interconnect.wires:
            if tile_id_port in wire:
                interconnect.remove_wire(wire[0], wire[1])
                break

        # Actually connect hi/lo outputs to tile_id at top level
        for i in range(tile_id_width):
            lo_index = i // 2
            if (i % 2) == 0:
                hi_index = i // 2
            else:
                hi_index = (i // 2) + 1
            hi_port = tile.ports.hi[hi_index]
            lo_port = tile.ports.lo[lo_index]
            tie_port = hi_port if (tile_id_bv[i] == 1) else lo_port
            # Connect tile_id ports to hi/lo outputs instead of constant
            interconnect.wire(tile.ports.tile_id[i], tie_port)
def pipeline_config_signals(interconnect: Interconnect, interval):
    # Right now in canal, the width of config_addr and config_data
    # are hard-coded to be the same. This should be changed.
    config_data_width = interconnect.config_data_width
    config_addr_width = config_data_width
    for (x, y) in interconnect.tile_circuits:
        tile = interconnect.tile_circuits[(x, y)]
        tile_core = tile.core
        # We only want to do this on PE and memory tiles
        if tile_core is None or "config" not in tile_core.ports or y == 0:
            continue
        else:
            if interval != 0 and y % interval == 0 and (
                (x, y + 1) in interconnect.tile_circuits):
                tile_below = interconnect.tile_circuits[(x, y + 1)]
                pipe_stage = PipelineStage(config_addr_width,
                                           config_data_width)
                # remove existing config wire
                interconnect.remove_wire(tile.ports.config_out,
                                         tile_below.ports.config)
                # Now, wire config through the pipe stage
                interconnect.wire(tile.ports.config_out,
                                  pipe_stage.ports.config)
                interconnect.wire(pipe_stage.ports.config_out,
                                  tile_below.ports.config)
                # Wire up pipe stage clock input to output clock
                interconnect.wire(tile.ports.clk_out, pipe_stage.ports.clk)
Ejemplo n.º 6
0
def chain_pass(interconnect: Interconnect):  # pragma: nocover
    for (x, y) in interconnect.tile_circuits:
        tile = interconnect.tile_circuits[(x, y)]
        tile_core = tile.core
        if isinstance(tile_core, MemCore):
            # lift ports up
            lift_mem_ports(tile, tile_core)

            previous_tile = interconnect.tile_circuits[(x, y - 1)]
            if not isinstance(previous_tile.core, MemCore):
                interconnect.wire(Const(0), tile.ports.chain_valid_in)
                interconnect.wire(Const(0), tile.ports.chain_data_in)
            else:
                interconnect.wire(previous_tile.ports.chain_valid_out,
                                  tile.ports.chain_valid_in)
                interconnect.wire(previous_tile.ports.chain_data_out,
                                  tile.ports.chain_data_in)
Ejemplo n.º 7
0
def clk_physical(interconnect: Interconnect):
    for (x, y) in interconnect.tile_circuits:
        tile = interconnect.tile_circuits[(x, y)]
        tile_core = tile.core
        # We only want to do this on PE and memory tiles
        if tile_core is None or isinstance(tile_core, IOCoreBase):
            continue
        elif isinstance(tile_core, MemCore):
            if (x, y + 1) in interconnect.tile_circuits:
                tile_below = interconnect.tile_circuits[(x, y + 1)]
                if isinstance(tile_below.core, MemCore):
                    interconnect.remove_wire(tile.ports.clk_out,
                                             tile_below.ports.clk)
            # Get the PE tile to the left of this mem tile
            tile_left = interconnect.tile_circuits[(x - 1, y)]
            # Connect the clk input of this mem tile to the right clk
            # output of the neighboring PE tile
            interconnect.wire(tile_left.ports.clk_pass_through_out_right,
                              tile.ports.clk)
        else:
            orig_in_port = tile.ports.clk
            orig_out_port = tile.ports.clk_out
            # Remove the pass through connection that already exists
            tile.remove_wire(orig_in_port, orig_out_port)
            # Create a new pass through clock input
            tile.add_port("clk_pass_through", magma.In(magma.Bit))
            pass_through_input = tile.ports.clk_pass_through
            pass_through_input_as_clk = tile.convert(pass_through_input,
                                                     magma.clock)
            # Create 2 new clk pass through outputs (bottom and right)
            tile.add_port("clk_pass_through_out_bot", magma.Out(magma.Bit))
            tile.add_port("clk_pass_through_out_right", magma.Out(magma.Clock))
            tile.wire(tile.ports.clk_pass_through,
                      tile.ports.clk_pass_through_out_bot)
            tile.wire(pass_through_input_as_clk,
                      tile.ports.clk_pass_through_out_right)

            # Connect new clk pass through input to old pass through output
            tile.wire(pass_through_input_as_clk, orig_out_port)
            # For top row tiles, connect new clk input to global clock
            if y < 2:
                interconnect_clk_as_bit = interconnect.convert(
                    interconnect.ports.clk, magma.bit)
                interconnect.wire(interconnect_clk_as_bit, pass_through_input)
            # For other tiles, connect new clk input to
            # pass through output of tile above.
            else:
                tile_above = interconnect.tile_circuits[(x, y - 1)]
                interconnect.wire(tile_above.ports.clk_pass_through_out_bot,
                                  pass_through_input)