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)
Пример #2
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)
Пример #3
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)