Exemple #1
0
class Arbiter(Module):
    def __init__(self, pe_id, config):
        self.network_interface_in = NetworkInterface(
            name="left_in", **config.addresslayout.get_params())
        self.network_interface_out = NetworkInterface(
            name="right_out", **config.addresslayout.get_params())
        self.local_interface_in = NetworkInterface(
            name="local_in", **config.addresslayout.get_params())
        local_interface_out = NetworkInterface(
            name="local_out", **config.addresslayout.get_params())

        self.apply_interface_out = ApplyInterface(
            **config.addresslayout.get_params())
        self.start_message = ApplyInterface(
            **config.addresslayout.get_params())
        self.start_message.select = Signal()

        self.network_round = Signal(config.addresslayout.channel_bits)
        self.round_accepting = Signal(config.addresslayout.channel_bits)

        mux_interface = NetworkInterface(**config.addresslayout.get_params())

        inject = Signal()
        self.comb += [
            inject.eq(
                self.local_interface_in.msg.roundpar == self.network_round),
            If(
                self.network_interface_in.valid &
                (self.network_interface_in.msg.roundpar == self.network_round),
                self.network_interface_in.connect(mux_interface)).Elif(
                    inject, self.local_interface_in.connect(mux_interface))
        ]

        self.comb += [
            If(mux_interface.dest_pe == pe_id,
               mux_interface.connect(local_interface_out)).Else(
                   mux_interface.connect(self.network_interface_out))
        ]

        self.submodules.barriercounter = Barriercounter(config)

        self.comb += [
            local_interface_out.msg.connect(
                self.barriercounter.apply_interface_in.msg),
            self.barriercounter.apply_interface_in.valid.eq(
                local_interface_out.valid),
            local_interface_out.ack.eq(
                self.barriercounter.apply_interface_in.ack),
            If(self.start_message.select,
               self.start_message.connect(self.apply_interface_out)).Else(
                   self.barriercounter.apply_interface_out.connect(
                       self.apply_interface_out)),
            self.round_accepting.eq(self.barriercounter.round_accepting)
        ]

    def gen_selfcheck(self, tb):
        yield
class Arbiter(Module):
    def __init__(self, pe_id, config):
        self.network_interface_in = NetworkInterface(name="left_in", **config.addresslayout.get_params())
        self.network_interface_out = NetworkInterface(name="right_out", **config.addresslayout.get_params())
        self.local_interface_in = NetworkInterface(name="local_in", **config.addresslayout.get_params())
        local_interface_out = NetworkInterface(name="local_out", **config.addresslayout.get_params())

        self.apply_interface_out = ApplyInterface(**config.addresslayout.get_params())
        self.start_message = ApplyInterface(**config.addresslayout.get_params())
        self.start_message.select = Signal()

        self.network_round = Signal(config.addresslayout.channel_bits)
        self.round_accepting = Signal(config.addresslayout.channel_bits)

        mux_interface = NetworkInterface(**config.addresslayout.get_params())


        inject = Signal()
        self.comb += [
            inject.eq(self.local_interface_in.msg.roundpar == self.network_round),
            If(self.network_interface_in.valid & (self.network_interface_in.msg.roundpar == self.network_round),
                self.network_interface_in.connect(mux_interface)
            ).Elif(inject,
                self.local_interface_in.connect(mux_interface)
            )
        ]



        self.comb += [
            If(mux_interface.dest_pe == pe_id,
                mux_interface.connect(local_interface_out)
            ).Else(
                mux_interface.connect(self.network_interface_out)
            )
        ]

        self.submodules.barriercounter = Barriercounter(config)

        self.comb += [
            local_interface_out.msg.connect(self.barriercounter.apply_interface_in.msg),
            self.barriercounter.apply_interface_in.valid.eq(local_interface_out.valid),
            local_interface_out.ack.eq(self.barriercounter.apply_interface_in.ack),
            If(self.start_message.select,
                self.start_message.connect(self.apply_interface_out)
            ).Else(
                self.barriercounter.apply_interface_out.connect(self.apply_interface_out)
            ),
            self.round_accepting.eq(self.barriercounter.round_accepting)
        ]

    def gen_selfcheck(self, tb):
        yield
Exemple #3
0
    def __init__(self, config):
        num_pe = config.addresslayout.num_pe
        num_nodes_per_pe = config.addresslayout.num_nodes_per_pe

        self.apply_interface = [
            ApplyInterface(name="network_out",
                           **config.addresslayout.get_params())
            for _ in range(num_pe)
        ]
        self.network_interface = [
            NetworkInterface(name="network_in",
                             **config.addresslayout.get_params())
            for _ in range(num_pe)
        ]

        fifos = [
            InterfaceFIFO(layout=set_layout_parameters(
                _network_layout, **config.addresslayout.get_params()),
                          depth=8) for i in range(num_pe)
        ]
        self.submodules.fifos = fifos
        self.submodules.arbiter = [
            Arbiter(sink, config) for sink in range(num_pe)
        ]

        for i in range(num_pe):
            j = (i + 1) % num_pe

            self.comb += [
                self.arbiter[i].network_interface_out.connect(fifos[i].din),
                fifos[i].dout.connect(self.arbiter[j].network_interface_in),
                self.network_interface[i].connect(
                    self.arbiter[i].local_interface_in),
                self.arbiter[i].apply_interface_out.connect(
                    self.apply_interface[i])
            ]

        network_round = Signal(config.addresslayout.channel_bits)
        next_round = Signal(config.addresslayout.channel_bits)
        proceed = Signal()

        self.comb += [
            proceed.eq(
                reduce(and_,
                       [a.round_accepting == next_round
                        for a in self.arbiter])),
            If(network_round < config.addresslayout.num_channels - 1,
               next_round.eq(network_round + 1)).Else(next_round.eq(0)),
            [
                self.arbiter[i].network_round.eq(network_round)
                for i in range(num_pe)
            ]
        ]

        self.sync += If(proceed, network_round.eq(next_round))
Exemple #4
0
    def __init__(self, config):
        num_pe = config.addresslayout.num_pe
        num_nodes_per_pe = config.addresslayout.num_nodes_per_pe

        self.apply_interface = [
            ApplyInterface(name="network_out",
                           **config.addresslayout.get_params())
            for _ in range(num_pe)
        ]
        self.network_interface = [
            NetworkInterface(name="network_in",
                             **config.addresslayout.get_params())
            for _ in range(num_pe)
        ]

        self.submodules.arbiter = [
            Arbiter(sink, config) for sink in range(num_pe)
        ]
        self.comb += [
            a.apply_interface_out.connect(self.apply_interface[i])
            for i, a in enumerate(self.arbiter)
        ]
    def __init__(self, config):
        self.network_interface_in = NetworkInterface(name="barrierdistributor_in", **config.addresslayout.get_params())
        self.network_interface_out = NetworkInterface(name="barrierdistributor_out", **config.addresslayout.get_params())

        self.submodules.fifo = InterfaceFIFO(layout=self.network_interface_in.layout, depth=8)

        self.comb += [
            self.network_interface_in.connect(self.fifo.din)
        ]

        self.total_num_messages = Signal(32)
        self.sync += [
            If(self.network_interface_out.valid & self.network_interface_out.ack & ~self.network_interface_out.msg.barrier,
                self.total_num_messages.eq(self.total_num_messages + 1)
            )
        ]

        num_pe = config.addresslayout.num_pe

        have_barrier = Signal()
        curr_barrier = Signal(config.addresslayout.peidsize)
        barrier_done = Signal()
        sink = Signal(config.addresslayout.peidsize)
        num_msgs_since_last_barrier = Array(Signal(config.addresslayout.nodeidsize) for _ in range(num_pe))
        halt = Signal()

        self.comb += [
            have_barrier.eq(self.fifo.dout.msg.barrier & self.fifo.dout.valid),
            barrier_done.eq(curr_barrier == (num_pe - 1))
        ]

        self.sync += [
            If(have_barrier & self.network_interface_out.ack,
                num_msgs_since_last_barrier[curr_barrier].eq(0),
                If(~barrier_done,
                    curr_barrier.eq(curr_barrier + 1)
                ).Else(
                    curr_barrier.eq(0),
                    halt.eq(1)
                )
            )
        ]

        self.sync += [
            If(~have_barrier & self.fifo.dout.valid & self.fifo.dout.ack,
                num_msgs_since_last_barrier[sink].eq(num_msgs_since_last_barrier[sink] + 1),
                halt.eq(0)
            )
        ]

        self.comb += [
            If(have_barrier,
                sink.eq(curr_barrier),
                self.network_interface_out.dest_pe.eq(curr_barrier),
                self.network_interface_out.msg.dest_id.eq(num_msgs_since_last_barrier[sink]),
                self.network_interface_out.msg.halt.eq(halt),
                self.fifo.dout.ack.eq(barrier_done & self.network_interface_out.ack)
            ).Else(
                sink.eq(self.fifo.dout.dest_pe),
                self.network_interface_out.dest_pe.eq(self.fifo.dout.dest_pe),
                self.network_interface_out.msg.dest_id.eq(self.fifo.dout.msg.dest_id),
                self.network_interface_out.msg.halt.eq(0),
                self.fifo.dout.ack.eq(self.network_interface_out.ack)
            ),
            self.fifo.dout.connect(self.network_interface_out, omit=["ack", "dest_id", "dest_pe", "halt"])
        ]
Exemple #6
0
    def __init__(self, config):
        self.network_interface_in = NetworkInterface(
            name="barrierdistributor_in", **config.addresslayout.get_params())
        self.network_interface_out = NetworkInterface(
            name="barrierdistributor_out", **config.addresslayout.get_params())

        self.submodules.fifo = InterfaceFIFO(
            layout=self.network_interface_in.layout, depth=8)

        self.comb += [self.network_interface_in.connect(self.fifo.din)]

        self.total_num_messages = Signal(32)
        self.sync += [
            If(
                self.network_interface_out.valid
                & self.network_interface_out.ack
                & ~self.network_interface_out.msg.barrier,
                self.total_num_messages.eq(self.total_num_messages + 1))
        ]

        num_pe = config.addresslayout.num_pe

        have_barrier = Signal()
        curr_barrier = Signal(config.addresslayout.peidsize)
        barrier_done = Signal()
        sink = Signal(config.addresslayout.peidsize)
        num_msgs_since_last_barrier = Array(
            Signal(config.addresslayout.nodeidsize) for _ in range(num_pe))
        halt = Signal()

        self.comb += [
            have_barrier.eq(self.fifo.dout.msg.barrier & self.fifo.dout.valid),
            barrier_done.eq(curr_barrier == (num_pe - 1))
        ]

        self.sync += [
            If(
                have_barrier & self.network_interface_out.ack,
                num_msgs_since_last_barrier[curr_barrier].eq(0),
                If(~barrier_done, curr_barrier.eq(curr_barrier + 1)).Else(
                    curr_barrier.eq(0), halt.eq(1)))
        ]

        self.sync += [
            If(
                ~have_barrier & self.fifo.dout.valid & self.fifo.dout.ack,
                num_msgs_since_last_barrier[sink].eq(
                    num_msgs_since_last_barrier[sink] + 1), halt.eq(0))
        ]

        self.comb += [
            If(
                have_barrier, sink.eq(curr_barrier),
                self.network_interface_out.dest_pe.eq(curr_barrier),
                self.network_interface_out.msg.dest_id.eq(
                    num_msgs_since_last_barrier[sink]),
                self.network_interface_out.msg.halt.eq(halt),
                self.fifo.dout.ack.eq(
                    barrier_done & self.network_interface_out.ack)).Else(
                        sink.eq(self.fifo.dout.dest_pe),
                        self.network_interface_out.dest_pe.eq(
                            self.fifo.dout.dest_pe),
                        self.network_interface_out.msg.dest_id.eq(
                            self.fifo.dout.msg.dest_id),
                        self.network_interface_out.msg.halt.eq(0),
                        self.fifo.dout.ack.eq(self.network_interface_out.ack)),
            self.fifo.dout.connect(self.network_interface_out,
                                   omit=["ack", "dest_id", "dest_pe", "halt"])
        ]
    def __init__(self, config):
        num_pe = config.addresslayout.num_pe
        num_nodes_per_pe = config.addresslayout.num_nodes_per_pe

        self.apply_interface = [
            ApplyInterface(**config.addresslayout.get_params())
            for _ in range(num_pe)
        ]
        self.network_interface = [
            NetworkInterface(**config.addresslayout.get_params())
            for _ in range(num_pe)
        ]

        fifos = [[
            RecordFIFO(
                layout=Message(**config.addresslayout.get_params()).layout,
                depth=8) for i in range(num_pe)
        ] for j in range(num_pe)]
        self.submodules.fifos = fifos
        self.submodules.arbiter = [
            Arbiter(config, fifos[sink]) for sink in range(num_pe)
        ]

        self.comb += [
            self.arbiter[i].apply_interface.connect(self.apply_interface[i])
            for i in range(num_pe)
        ]

        # connect fifos across PEs
        for source in range(num_pe):
            array_dest_id = Array(
                fifo.din.dest_id
                for fifo in [fifos[sink][source] for sink in range(num_pe)])
            array_sender = Array(
                fifo.din.sender
                for fifo in [fifos[sink][source] for sink in range(num_pe)])
            array_payload = Array(
                fifo.din.payload
                for fifo in [fifos[sink][source] for sink in range(num_pe)])
            array_roundpar = Array(
                fifo.din.roundpar
                for fifo in [fifos[sink][source] for sink in range(num_pe)])
            array_barrier = Array(
                fifo.din.barrier
                for fifo in [fifos[sink][source] for sink in range(num_pe)])
            array_we = Array(
                fifo.we
                for fifo in [fifos[sink][source] for sink in range(num_pe)])
            array_writable = Array(
                fifo.writable
                for fifo in [fifos[sink][source] for sink in range(num_pe)])

            have_barrier = Signal()
            barrier_ack = Array(Signal() for _ in range(num_pe))
            barrier_done = Signal()

            self.comb += barrier_done.eq(reduce(
                and_, barrier_ack)), have_barrier.eq(
                    self.network_interface[source].msg.barrier
                    & self.network_interface[source].valid)

            self.sync += If(have_barrier & ~barrier_done, [
                barrier_ack[i].eq(barrier_ack[i] | array_writable[i])
                for i in range(num_pe)
            ]).Else([barrier_ack[i].eq(0) for i in range(num_pe)])

            sink = Signal(config.addresslayout.peidsize)

            self.comb += If(
                have_barrier, [array_barrier[i].eq(1) for i in range(num_pe)],
                [
                    array_roundpar[i].eq(
                        self.network_interface[source].msg.roundpar)
                    for i in range(num_pe)
                ], [array_we[i].eq(~barrier_ack[i]) for i in range(num_pe)],
                self.network_interface[source].ack.eq(barrier_done)).Else(
                    sink.eq(self.network_interface[source].dest_pe),
                    array_dest_id[sink].eq(
                        self.network_interface[source].msg.dest_id),
                    array_sender[sink].eq(
                        self.network_interface[source].msg.sender),
                    array_payload[sink].eq(
                        self.network_interface[source].msg.payload),
                    array_roundpar[sink].eq(
                        self.network_interface[source].msg.roundpar),
                    array_we[sink].eq(self.network_interface[source].valid),
                    self.network_interface[source].ack.eq(
                        array_writable[sink]))
    def __init__(self, pe_id, config, port=None):
        self.pe_id = pe_id
        addresslayout = config.addresslayout
        nodeidsize = addresslayout.nodeidsize
        num_nodes_per_pe = addresslayout.num_nodes_per_pe
        num_pe = addresslayout.num_pe
        edgeidsize = addresslayout.edgeidsize
        max_edges_per_pe = addresslayout.max_edges_per_pe
        peidsize = addresslayout.peidsize

        # input
        self.scatter_interface = ScatterInterface(**addresslayout.get_params())

        #output
        self.network_interface = NetworkInterface(**addresslayout.get_params())

        ###

        # # memory layout (TODO: replace with an actual record)
        def _pack_adj_idx(adj_idx):
            return [b<<edgeidsize | a for a,b in adj_idx]
        #
        # adj_idx, adj_val = adj_mat

        # CSR edge storage: (idx, val) tuple of arrays
        # idx: array of (start_adr, num_neighbors)
        self.specials.mem_idx = Memory(edgeidsize*2, max(2, len(config.adj_idx[pe_id])), name="edge_csr_idx", init=_pack_adj_idx(config.adj_idx[pe_id]))
        self.specials.rd_port_idx = rd_port_idx = self.mem_idx.get_port(has_re=True)
        self.specials.wr_port_idx = wr_port_idx = self.mem_idx.get_port(write_capable=True)

        # val: array of nodeids
        # resides in submodule

        if config.memtype == "HMC":
            from core_neighbors_hmc import Neighbors
        elif config.memtype == "HMCO":
            from core_neighbors_hmc_ordered import Neighbors
        elif config.memtype == "AXI":
            from core_neighbors_ddr import Neighbors
        else:
            from core_neighbors import Neighbors

        self.submodules.get_neighbors = Neighbors(pe_id=pe_id, config=config, port=port)


        # flow control variables
        upstream_ack = Signal()


        ## stage 1

        # address idx with incoming message
        self.comb += [
            rd_port_idx.adr.eq(addresslayout.local_adr(self.scatter_interface.sender)),
            rd_port_idx.re.eq(upstream_ack),
            self.scatter_interface.ack.eq(upstream_ack)
        ]

        # keep input for next stage
        scatter_msg1 = Signal(addresslayout.updatepayloadsize)
        scatter_sender1 = Signal(addresslayout.nodeidsize)
        scatter_round1 = Signal(config.addresslayout.channel_bits)
        scatter_msg_valid1 = Signal()
        scatter_barrier1 = Signal()
        # valid1 requests get_neighbors, so don't set for barrier
        self.sync += [
            If( upstream_ack,
                scatter_msg1.eq(self.scatter_interface.payload),
                scatter_sender1.eq(self.scatter_interface.sender),
                scatter_round1.eq(self.scatter_interface.roundpar),
                scatter_msg_valid1.eq(self.scatter_interface.valid & ~self.scatter_interface.barrier),
                scatter_barrier1.eq(self.scatter_interface.valid & self.scatter_interface.barrier)
            )
        ]

        ## stage 2

        # ask get_neighbors submodule for all neighbors of input node
        # upstream_ack will only go up again when all neighbors done
        self.comb +=[
            self.get_neighbors.neighbor_in.start_idx.eq(rd_port_idx.dat_r[:edgeidsize]),
            self.get_neighbors.neighbor_in.num_neighbors.eq(rd_port_idx.dat_r[edgeidsize:]),
            self.get_neighbors.neighbor_in.valid.eq(scatter_msg_valid1),
            self.get_neighbors.neighbor_in.barrier.eq(scatter_barrier1),
            self.get_neighbors.neighbor_in.message.eq(scatter_msg1),
            self.get_neighbors.neighbor_in.sender.eq(scatter_sender1),
            self.get_neighbors.neighbor_in.round.eq(scatter_round1),
            upstream_ack.eq(self.get_neighbors.neighbor_in.ack)
        ]


        ## stage 3

        # user modification based on edge data

        self.submodules.scatterkernel = config.scatterkernel(config)

        self.submodules.neighbor_out_fifo = InterfaceFIFO(layout=self.get_neighbors.neighbor_out.layout+([("edgedata", len(self.get_neighbors.edgedata_out), DIR_M_TO_S)] if config.has_edgedata else []), depth=8)


        self.comb += [
            self.get_neighbors.neighbor_out.connect(self.neighbor_out_fifo.din, omit={"valid", "edgedata"}),
            self.neighbor_out_fifo.din.valid.eq(self.get_neighbors.neighbor_out.valid | self.get_neighbors.neighbor_out.barrier),
            self.scatterkernel.update_in.raw_bits().eq(self.neighbor_out_fifo.dout.message),
            self.scatterkernel.num_neighbors_in.eq(self.neighbor_out_fifo.dout.num_neighbors),
            self.scatterkernel.neighbor_in.eq(self.neighbor_out_fifo.dout.neighbor),
            self.scatterkernel.sender_in.eq(self.neighbor_out_fifo.dout.sender),
            self.scatterkernel.round_in.eq(self.neighbor_out_fifo.dout.round),
            self.scatterkernel.barrier_in.eq(self.neighbor_out_fifo.dout.valid & self.neighbor_out_fifo.dout.barrier),
            self.scatterkernel.valid_in.eq(self.neighbor_out_fifo.dout.valid & ~self.neighbor_out_fifo.dout.barrier),
            self.neighbor_out_fifo.dout.ack.eq(self.scatterkernel.ready)
        ]
        if config.has_edgedata:
            self.comb += [
                self.neighbor_out_fifo.din.edgedata.eq(self.get_neighbors.edgedata_out),
                self.scatterkernel.edgedata_in.raw_bits().eq(self.neighbor_out_fifo.dout.edgedata)
            ]

        # scatterkernel output



        self.submodules.barrierdistributor = BarrierDistributor(config)

        self.submodules.scatterkerneloutfifo = InterfaceFIFO(layout=self.barrierdistributor.network_interface_in.layout, depth=8)

        self.comb += [
            self.scatterkerneloutfifo.din.msg.dest_id.eq(self.scatterkernel.neighbor_out),
            self.scatterkerneloutfifo.din.msg.payload.eq(self.scatterkernel.message_out.raw_bits()),
            self.scatterkerneloutfifo.din.msg.sender.eq(self.scatterkernel.sender_out),
            self.scatterkerneloutfifo.din.msg.roundpar.eq(self.scatterkernel.round_out),
            self.scatterkerneloutfifo.din.msg.barrier.eq(self.scatterkernel.barrier_out),
            self.scatterkerneloutfifo.din.dest_pe.eq(addresslayout.pe_adr(self.scatterkernel.neighbor_out)),
            self.scatterkerneloutfifo.din.valid.eq(self.scatterkernel.valid_out | self.scatterkernel.barrier_out),
            self.scatterkernel.message_ack.eq(self.scatterkerneloutfifo.din.ack),
            self.scatterkerneloutfifo.dout.connect(self.barrierdistributor.network_interface_in)
        ]

        # buffer output
        self.submodules.outfifo = InterfaceFIFO(layout=self.network_interface.layout, depth=8)

        self.comb += [
            self.barrierdistributor.network_interface_out.connect(self.outfifo.din),
            self.outfifo.dout.connect(self.network_interface)
        ]

        self.total_num_messages = self.barrierdistributor.total_num_messages