Esempio n. 1
0
    def generate_circuit(self):
        int_priority_encoder = PriorityEncoder(len(self.intrs) + 1)
        self.submodules += int_priority_encoder

        for i in range(len(self.intrs)):
            self.comb += int_priority_encoder.i[i + 1].eq(self.intrs[i])

        self.comb += self.intr_number.eq(int_priority_encoder.o)
        self.comb += self.intr.eq(reduce(or_, [0] + self.intrs))
Esempio n. 2
0
    def __init__(self, config, ext_message_width, num_local_pe):
        self.send_barrier = Signal()
        self.send_barrier_ack = Signal()

        self.receive_barrier = Signal()
        self.receive_barrier_ack = Signal()

        self.message_in_data_inside = [Signal(ext_message_width) for _ in range(config.addresslayout.num_ext_ports)]
        self.message_in_valid_inside = [Signal() for _ in range(config.addresslayout.num_ext_ports)]
        self.message_in_ack_inside = [Signal() for _ in range(config.addresslayout.num_ext_ports)]

        self.message_in_data = [Signal(ext_message_width) for _ in range(config.addresslayout.num_ext_ports)]
        self.message_in_valid = [Signal() for _ in range(config.addresslayout.num_ext_ports)]
        self.message_in_ack = [Signal() for _ in range(config.addresslayout.num_ext_ports)]

        self.message_out_data_inside = Signal(ext_message_width * num_local_pe)
        self.message_out_valid_inside = Signal(num_local_pe)
        self.message_out_ack_inside = Signal(num_local_pe)

        self.message_out_data = Signal(ext_message_width * num_local_pe)
        self.message_out_valid = Signal(num_local_pe)
        self.message_out_ack = Signal(num_local_pe)

        barrier_message = NetworkInterface(**config.addresslayout.get_params())
        self.comb += [
            barrier_message.broadcast.eq(1),
            barrier_message.valid.eq(1),
            barrier_message.ack.eq(1)
        ]

        self.comb += [
            If(self.send_barrier,
                self.message_out_data.eq(barrier_message.raw_bits()),
                self.message_out_valid.eq(1),
                self.send_barrier_ack.eq(self.message_out_ack[0])
            ).Else(
                self.message_out_data.eq(self.message_out_data_inside),
                self.message_out_valid.eq(self.message_out_valid_inside),
                self.message_out_ack_inside.eq(self.message_out_ack)
            )
        ]

        self.submodules.pe = PriorityEncoder(config.addresslayout.num_ext_ports)

        for port in range(config.addresslayout.num_ext_ports):
            self.comb += [
                self.pe.i[port].eq((self.message_in_data[port] == barrier_message.raw_bits()) & self.message_in_valid[port]),
                If(self.pe.i[port],
                    self.receive_barrier.eq((self.pe.o == port)),
                    self.message_in_ack[port].eq(self.receive_barrier_ack & (self.pe.o == port))
                ).Else(
                    self.message_in_data_inside[port].eq(self.message_in_data[port]),
                    self.message_in_valid_inside[port].eq(self.message_in_valid[port]),
                    self.message_in_ack[port].eq(self.message_in_ack_inside[port])
                )
            ]
Esempio n. 3
0
    def __init__(self, serdes):
        serdes_width = len(serdes.o)
        assert len(serdes.i) == serdes_width
        self.rtlink = rtlink.Interface(
            rtlink.OInterface(2, 2, fine_ts_width=log2_int(serdes_width)),
            rtlink.IInterface(1, fine_ts_width=log2_int(serdes_width)))
        self.probes = [serdes.i[-1], serdes.oe]
        override_en = Signal()
        override_o = Signal()
        override_oe = Signal()
        self.overrides = [override_en, override_o, override_oe]

        # # #

        # Output
        self.submodules += _SerdesDriver(serdes_o=serdes.o,
                                         stb=self.rtlink.o.stb &
                                         (self.rtlink.o.address == 0),
                                         data=self.rtlink.o.data[0],
                                         fine_ts=self.rtlink.o.fine_ts,
                                         override_en=override_en,
                                         override_o=override_o)

        oe_k = Signal()
        self.sync.rio_phy += [
            If(self.rtlink.o.stb & (self.rtlink.o.address == 1),
               oe_k.eq(self.rtlink.o.data[0])),
            If(override_en, serdes.oe.eq(override_oe)).Else(serdes.oe.eq(oe_k))
        ]

        # Input
        sensitivity = Signal(2)
        sample = Signal()
        self.sync.rio += [
            sample.eq(0),
            If(self.rtlink.o.stb & self.rtlink.o.address[1],
               sensitivity.eq(self.rtlink.o.data),
               If(self.rtlink.o.address[0], sample.eq(1)))
        ]

        i = serdes.i[-1]
        i_d = Signal()
        self.sync.rio_phy += [
            i_d.eq(i),
            self.rtlink.i.stb.eq(sample | (sensitivity[0] & (i & ~i_d))
                                 | (sensitivity[1] & (~i & i_d))),
            self.rtlink.i.data.eq(i),
        ]

        pe = PriorityEncoder(serdes_width)
        self.submodules += pe
        self.comb += pe.i.eq(serdes.i ^ Replicate(i_d, serdes_width))
        self.sync.rio_phy += self.rtlink.i.fine_ts.eq(pe.o)
Esempio n. 4
0
    def __init__(self):
        self.latency = 50
        self.dividend_i = Signal(32)
        self.divisor_i = Signal(32)
        self.valid_i = Signal()
        self.quotient_o = Signal(32)
        self.valid_o = Signal()

        ###

        dividend_sign = Signal()
        dividend_expn = Signal(8)
        dividend_mant = Signal(24)

        self.comb += [
            dividend_sign.eq(self.dividend_i[31]),
            dividend_expn.eq(self.dividend_i[23:31]),
            dividend_mant.eq(Cat(self.dividend_i[0:23], 1))
        ]

        # divide mantissa, add 24 bits of precision to be sure we have at least 24 left over

        w = 48

        self.submodules.div = Divider(w)

        self.comb += [
            self.div.dividend_i[:-24].eq(0),
            self.div.dividend_i[-24:].eq(dividend_mant),
            self.div.divisor_i.eq(self.divisor_i),
            self.div.valid_i.eq(self.valid_i)
        ]

        # keep exponent and sign for the duration of division (49 cycles...)

        expn = [Signal(8) for _ in range(w + 1)]
        sign = [Signal() for _ in range(w + 1)]

        self.sync += [expn[0].eq(dividend_expn), sign[0].eq(dividend_sign)]

        self.sync += [expn[i + 1].eq(expn[i]) for i in range(w)]

        self.sync += [sign[i + 1].eq(sign[i]) for i in range(w)]

        # shift mantissa and subtract shift from exponent

        pe = PriorityEncoder(w)
        self.submodules += pe

        self.comb += [pe.i.eq(self.div.quotient_o[::-1])]

        quotient_o_sign = Signal()
        quotient_o_expn = Signal(8)
        quotient_o_mant = Signal(48)

        self.sync += [
            quotient_o_sign.eq(sign[-1]),
            If(expn[-1] != 0, quotient_o_expn.eq(expn[-1] - pe.o),
               quotient_o_mant.eq(self.div.quotient_o << pe.o)).Else(
                   quotient_o_expn.eq(0),
                   quotient_o_mant.eq(self.div.quotient_o)),
            self.valid_o.eq(self.div.valid_o)
        ]

        self.comb += [
            self.quotient_o[31].eq(quotient_o_sign),
            self.quotient_o[23:31].eq(quotient_o_expn),
            self.quotient_o[0:23].eq(quotient_o_mant[-24:-1])
        ]
Esempio n. 5
0
    def __init__(self, pads, pads_n=None, cdmap=None):
        super(HiresGpio, self).__init__()
        self.sys8_stb = Signal(4)

        ###

        n = flen(pads)

        i0 = Signal(n)
        i = Signal(n)
        o = Signal(n)
        b = Signal(n)
        o0 = Signal(n)
        oe = Signal(n)
        r = Signal(n)
        f = Signal(n)
        ti = Signal(3)
        to = Signal(3)

        j = Signal()
        k = Signal()
        sys2_stb = Signal()
        self.sync += j.eq(~j)
        self.sync.sys2 += k.eq(j), sys2_stb.eq(k == j)

        # dout
        edges = Array([0xff ^ ((1 << i) - 1) for i in range(8)])
        edge_out = Signal(8)
        edge_out_n = Signal(8)
        rise_out = Signal(n)
        fall_out = Signal(n)
        self.comb += [
            edge_out.eq(edges[to]),
            edge_out_n.eq(~edge_out),
            rise_out.eq(~o0 & o),
            fall_out.eq(o0 & ~o),
        ]

        ios = []
        for j in range(n):
            io = IOSerdes(pads[j], pads_n[j] if pads_n else None)
            cdj = cdmap[j] if cdmap else 0
            io = RenameClockDomains(io, {"sys8": "sys8%i" % cdj})
            self.submodules += io
            ios.append(io)
            self.comb += io.sys8_stb.eq(self.sys8_stb[cdj])
            self.comb += io.sys2_stb.eq(sys2_stb)
            self.comb += [  # 0 cycle
                io.oe.eq(Replicate(oe[j], 8)),
                If(
                    rise_out[j],
                    io.o.eq(edge_out),
                ).Elif(
                    fall_out[j],
                    io.o.eq(edge_out_n),
                ).Else(io.o.eq(Replicate(o[j], 8)), )
            ]

        # din
        self.submodules.pe_ti = pe_ti = PriorityEncoder(8)
        self.submodules.pe_sel = pe_sel = PriorityEncoder(n)
        rise_in = Signal(n)
        fall_in = Signal(n)
        edge_in = Signal(8)
        bi = Signal()
        i0i = Signal()
        self.comb += [
            i.eq(Cat(io.i[-1] for io in ios) ^ b),
            rise_in.eq((~i0 & r) & i),
            fall_in.eq((i0 & f) & ~i),
            pe_sel.i.eq(rise_in | fall_in),
            i0i.eq(Array(fiter(i0))[pe_sel.o]),
            bi.eq(Array(fiter(b))[pe_sel.o]),
            edge_in.eq(Array([io.i for io in ios])[pe_sel.o]),
            pe_ti.i.eq(edge_in ^ Replicate(i0i ^ bi, 8)),
            ti.eq(pe_ti.o),
        ]

        # ventilator bus
        self.comb += [
            self.dout.ack.eq(1),
            self.busy.eq(self.din.stb & ~self.din.ack),
        ]

        self.sync += [  # 1 cycle each
            If(
                self.din.stb & self.din.ack,
                self.din.stb.eq(0),
            ),
            If(
                self.dout.stb,
                to.eq(self.dout.payload.addr[4:]),
                self.din.payload.addr.eq(0),
                Case(
                    self.dout.payload.addr[:4], {
                        0x0: [self.din.stb.eq(1),
                              self.din.payload.data.eq(i)],
                        0x1: [o.eq(self.dout.payload.data ^ b),
                              o0.eq(o)],
                        0x2: oe.eq(self.dout.payload.data),
                        0x3: r.eq(self.dout.payload.data),
                        0x4: f.eq(self.dout.payload.data),
                        0x5: b.eq(self.dout.payload.data),
                    }),
            ),
            If(
                ~(self.dout.stb & (self.dout.payload.addr[:4] == 0))
                & ~(self.din.stb & ~self.din.ack),
                i0.eq(i),
                If(
                    ~pe_sel.n,
                    self.din.stb.eq(1),
                    self.din.payload.addr[4:].eq(ti),
                    self.din.payload.addr[:4].eq(Mux(~i0i, 0x6, 0x7)),
                    self.din.payload.data.eq(Mux(~i0i, rise_in, fall_in)),
                ),
            )
        ]
Esempio n. 6
0
    def do_finalize(self):
        assert len(self.event_sources) < 2**6
        assert max(s.width for s in self.event_sources) <= 32

        # Fill the event, event data, and delay FIFOs.
        throttle_on = Signal()
        throttle_off = Signal()
        throttle_edge = Signal()
        throttle_fifos = []
        self.sync += [
            If(~self.throttle & throttle_on, self.throttle.eq(1),
               throttle_edge.eq(1)).Elif(self.throttle & throttle_off,
                                         self.throttle.eq(0),
                                         throttle_edge.eq(1)).Else(
                                             throttle_edge.eq(0))
        ]

        event_width = 1 + len(self.event_sources)
        if self.event_depth is None:
            event_depth = min(self._depth_for_width(event_width),
                              self._depth_for_width(self.delay_width))
        else:
            event_depth = self.event_depth

        self.submodules.event_fifo = event_fifo = \
            SyncFIFOBuffered(width=event_width, depth=event_depth)
        throttle_fifos.append(self.event_fifo)
        self.comb += [
            event_fifo.din.eq(
                Cat(self.throttle, [s.trigger for s in self.event_sources])),
            event_fifo.we.eq(
                reduce(lambda a, b: a | b, (s.trigger
                                            for s in self.event_sources))
                | throttle_edge)
        ]

        self.submodules.delay_fifo = delay_fifo = \
            SyncFIFOBuffered(width=self.delay_width, depth=event_depth)
        delay_timer = self._delay_timer = Signal(self.delay_width)
        self.sync += [
            If(delay_fifo.we,
               delay_timer.eq(0)).Else(delay_timer.eq(delay_timer + 1))
        ]
        self.comb += [
            delay_fifo.din.eq(delay_timer),
            delay_fifo.we.eq(event_fifo.we
                             | (delay_timer == ((1 << self.delay_width) - 1))
                             | self.done),
        ]

        for event_source in self.event_sources:
            if event_source.width > 0:
                event_source.submodules.data_fifo = event_data_fifo = \
                    SyncFIFOBuffered(event_source.width, event_source.depth)
                self.submodules += event_source
                throttle_fifos.append(event_data_fifo)
                self.comb += [
                    event_data_fifo.din.eq(event_source.data),
                    event_data_fifo.we.eq(event_source.trigger),
                ]
            else:
                event_source.submodules.data_fifo = _FIFOInterface(1, 0)

        # Throttle applets based on FIFO levels with hysteresis.
        self.comb += [
            throttle_on.eq(
                reduce(lambda a, b: a | b,
                       (f.fifo.level >= f.depth - f.depth //
                        (4 if f.depth > 4 else 2) for f in throttle_fifos))),
            throttle_off.eq(
                reduce(lambda a, b: a & b,
                       (f.fifo.level < f.depth // (4 if f.depth > 4 else 2)
                        for f in throttle_fifos))),
        ]

        # Dequeue events, and serialize events and event data.
        self.submodules.event_encoder = event_encoder = \
            PriorityEncoder(width=len(self.event_sources))
        self.submodules.event_decoder = event_decoder = \
            PriorityDecoder(width=len(self.event_sources))
        self.comb += event_decoder.i.eq(event_encoder.o)

        self.submodules.serializer = serializer = FSM(reset_state="WAIT-EVENT")
        rep_throttle_new = Signal()
        rep_throttle_cur = Signal()
        delay_septets = 5
        delay_counter = Signal(7 * delay_septets)
        serializer.act(
            "WAIT-EVENT",
            If(
                delay_fifo.readable,
                delay_fifo.re.eq(1),
                NextValue(delay_counter, delay_counter + delay_fifo.dout + 1),
            ),
            If(
                event_fifo.readable, event_fifo.re.eq(1),
                NextValue(event_encoder.i, event_fifo.dout[1:]),
                NextValue(rep_throttle_new, event_fifo.dout[0]),
                If((event_fifo.dout != 0) |
                   (rep_throttle_cur != event_fifo.dout[0]),
                   NextState("REPORT-DELAY"))).Elif(self.done,
                                                    NextState("REPORT-DELAY")))
        serializer.act(
            "REPORT-DELAY",
            If(delay_counter >= 128**4, NextState("REPORT-DELAY-5")).Elif(
                delay_counter >= 128**3, NextState("REPORT-DELAY-4")).Elif(
                    delay_counter >= 128**2, NextState("REPORT-DELAY-3")).Elif(
                        delay_counter >= 128**1,
                        NextState("REPORT-DELAY-2")).Else(
                            NextState("REPORT-DELAY-1")))
        for septet_no in range(delay_septets, 0, -1):
            if septet_no == 1:
                next_state = [
                    NextValue(delay_counter, 0),
                    If(rep_throttle_cur != rep_throttle_new,
                       NextState("REPORT-THROTTLE")).Elif(
                           event_encoder.i, NextState("REPORT-EVENT")).Elif(
                               self.done, NextState("REPORT-DONE")).Else(
                                   NextState("WAIT-EVENT"))
                ]
            else:
                next_state = [NextState("REPORT-DELAY-%d" % (septet_no - 1))]
            serializer.act(
                "REPORT-DELAY-%d" % septet_no,
                If(
                    self.output_fifo.writable,
                    self.output_fifo.din.eq(REPORT_DELAY | delay_counter.part(
                        (septet_no - 1) * 7, 7)), self.output_fifo.we.eq(1),
                    *next_state))
        serializer.act(
            "REPORT-THROTTLE",
            If(
                self.output_fifo.writable,
                NextValue(rep_throttle_cur, rep_throttle_new),
                If(
                    rep_throttle_new,
                    self.output_fifo.din.eq(REPORT_SPECIAL | SPECIAL_THROTTLE),
                ).Else(
                    self.output_fifo.din.eq(REPORT_SPECIAL
                                            | SPECIAL_DETHROTTLE), ),
                self.output_fifo.we.eq(1),
                If(event_encoder.n,
                   NextState("WAIT-EVENT")).Else(NextState("REPORT-EVENT"))))
        event_source = self.event_sources[event_encoder.o]
        event_data = Signal(32)
        serializer.act(
            "REPORT-EVENT",
            If(
                self.output_fifo.writable,
                NextValue(event_encoder.i, event_encoder.i & ~event_decoder.o),
                self.output_fifo.din.eq(REPORT_EVENT | event_encoder.o),
                self.output_fifo.we.eq(1),
                NextValue(event_data, event_source.data_fifo.dout),
                event_source.data_fifo.re.eq(1),
                If(event_source.width > 24,
                   NextState("REPORT-EVENT-DATA-4")).Elif(
                       event_source.width > 16,
                       NextState("REPORT-EVENT-DATA-3")).Elif(
                           event_source.width > 8,
                           NextState("REPORT-EVENT-DATA-2")).Elif(
                               event_source.width > 0,
                               NextState("REPORT-EVENT-DATA-1")).Else(
                                   If(event_encoder.i & ~event_decoder.o,
                                      NextState("REPORT-EVENT")).Else(
                                          NextState("WAIT-EVENT")))))
        for octet_no in range(4, 0, -1):
            if octet_no == 1:
                next_state = [
                    If(event_encoder.n,
                       NextState("WAIT-EVENT")).Else(NextState("REPORT-EVENT"))
                ]
            else:
                next_state = [
                    NextState("REPORT-EVENT-DATA-%d" % (octet_no - 1))
                ]
            serializer.act(
                "REPORT-EVENT-DATA-%d" % octet_no,
                If(
                    self.output_fifo.writable,
                    self.output_fifo.din.eq(
                        event_data.part((octet_no - 1) * 8, 8)),
                    self.output_fifo.we.eq(1), *next_state))
            serializer.act(
                "REPORT-DONE",
                If(self.output_fifo.writable,
                   self.output_fifo.din.eq(REPORT_SPECIAL | SPECIAL_DONE),
                   self.output_fifo.we.eq(1), NextState("DONE")))
            serializer.act("DONE", If(~self.done, NextState("WAIT-EVENT")))
Esempio n. 7
0
    def __init__(self, config):
        self.config = config
        self.submodules.cores = [
            Core(
                config, i * config.addresslayout.num_pe_per_fpga,
                min((i + 1) * config.addresslayout.num_pe_per_fpga,
                    config.addresslayout.num_pe))
            for i in range(config.addresslayout.num_fpga)
        ]

        self.global_inactive = Signal()
        self.comb += self.global_inactive.eq(
            reduce(and_, [core.global_inactive for core in self.cores]))

        self.submodules.adrlook_sender = AddressLookup(config)
        broadcast = Signal()
        broadcast_port = Signal(max=max(2, config.addresslayout.num_ext_ports))
        got_ack = Signal(config.addresslayout.num_ext_ports *
                         config.addresslayout.num_fpga)
        all_ack = Signal()

        self.submodules.fifo = [
            InterfaceFIFO(layout=self.cores[0].network.
                          external_network_interface_out[port].layout,
                          depth=8)
            for port in range(config.addresslayout.num_ext_ports)
        ]

        for port in range(config.addresslayout.num_ext_ports):
            ext_msg_channel_out = Array(
                core.network.external_network_interface_out[port].msg.raw_bits(
                ) for core in self.cores)
            ext_dest_pe_channel_out = Array(
                core.network.external_network_interface_out[port].dest_pe
                for core in self.cores)
            ext_valid_channel_out = Array(
                core.network.external_network_interface_out[port].valid
                for core in self.cores)
            ext_ack_channel_out = Array(
                core.network.external_network_interface_out[port].ack
                for core in self.cores)
            ext_broadcast_channel_out = Array(
                core.network.external_network_interface_out[port].broadcast
                for core in self.cores)

            ext_ack_channel_in = Array(
                core.network.external_network_interface_in[port].ack
                for core in self.cores)

            roundrobin = RoundRobin(config.addresslayout.num_fpga,
                                    switch_policy=SP_CE)
            self.submodules += roundrobin

            adrlook = AddressLookup(config)
            self.submodules += adrlook

            self.comb += [
                [
                    roundrobin.request[i].eq(ext_valid_channel_out[i])
                    for i in range(config.addresslayout.num_fpga)
                ],
                roundrobin.ce.eq(1),
                self.fifo[port].din.msg.raw_bits().eq(
                    ext_msg_channel_out[roundrobin.grant]),
                self.fifo[port].din.dest_pe.eq(
                    ext_dest_pe_channel_out[roundrobin.grant]),
                self.fifo[port].din.broadcast.eq(
                    ext_broadcast_channel_out[roundrobin.grant]),
                self.fifo[port].din.valid.eq(
                    ext_valid_channel_out[roundrobin.grant]),
                ext_ack_channel_out[roundrobin.grant].eq(
                    self.fifo[port].din.ack),
            ]

            self.comb += [
                adrlook.pe_adr_in.eq(self.fifo[port].dout.dest_pe),
                [
                    core.network.external_network_interface_in[port].msg.
                    raw_bits().eq(self.fifo[port].dout.msg.raw_bits())
                    for core in self.cores
                ],
                [
                    core.network.external_network_interface_in[port].dest_pe.
                    eq(self.fifo[port].dout.dest_pe) for core in self.cores
                ],
                [
                    core.network.external_network_interface_in[port].broadcast.
                    eq(broadcast) for core in self.cores
                ],
                [
                    self.cores[i].network.external_network_interface_in[port].
                    valid.eq(
                        (~broadcast & self.fifo[port].dout.valid
                         & (adrlook.fpga_out == i))
                        | (broadcast & ~((self.adrlook_sender.fpga_out == i) &
                                         (broadcast_port == port))
                           & ~got_ack[i * config.addresslayout.num_ext_ports +
                                      port]))
                    for i in range(config.addresslayout.num_fpga)
                ], self.fifo[port].dout.ack.eq(
                    (~broadcast & ext_ack_channel_in[adrlook.fpga_out])
                    | (broadcast & (port == broadcast_port) & all_ack))
            ]

        self.submodules.priorityencoder = PriorityEncoder(
            config.addresslayout.num_ext_ports)
        array_sender = Array(
            self.fifo[port].dout.msg.sender
            for port in range(config.addresslayout.num_ext_ports))

        self.comb += [
            self.priorityencoder.i[port].eq(self.fifo[port].dout.broadcast
                                            & self.fifo[port].dout.valid)
            for port in range(config.addresslayout.num_ext_ports)
        ]

        self.comb += [
            self.adrlook_sender.pe_adr_in.eq(array_sender[broadcast_port]),
            broadcast.eq(~self.priorityencoder.n),
            broadcast_port.eq(self.priorityencoder.o)
        ]

        self.sync += [
            If(
                broadcast,
                If(all_ack, got_ack.eq(0)).Else([
                    got_ack[i * config.addresslayout.num_ext_ports + port].eq(
                        got_ack[i * config.addresslayout.num_ext_ports + port]
                        | self.cores[i].network.
                        external_network_interface_in[port].ack)
                    for i in range(config.addresslayout.num_fpga)
                    for port in range(config.addresslayout.num_ext_ports)
                ]))
        ]

        self.comb += [
            all_ack.eq(
                reduce(and_, [
                    got_ack[i * config.addresslayout.num_ext_ports + port] |
                    ((self.adrlook_sender.fpga_out == i) &
                     (port == broadcast_port))
                    for i in range(config.addresslayout.num_fpga)
                    for port in range(config.addresslayout.num_ext_ports)
                ])),
        ]

        self.start = Signal()
        self.done = Signal()
        self.cycle_count = Signal(64)

        self.comb += [[core.start.eq(self.start) for core in self.cores],
                      self.done.eq(
                          reduce(and_, [core.done for core in self.cores])),
                      self.cycle_count.eq(self.cores[0].cycle_count)]
    def __init__(self, serdes):
        serdes_width = len(serdes.o)
        assert len(serdes.i) == serdes_width
        self.rtlink = rtlink.Interface(
            rtlink.OInterface(2, 2, fine_ts_width=log2_int(serdes_width)),
            rtlink.IInterface(1, fine_ts_width=log2_int(serdes_width)))
        self.probes = [serdes.i[-1], serdes.oe]
        override_en = Signal()
        override_o = Signal()
        override_oe = Signal()
        self.overrides = [override_en, override_o, override_oe]

        # Output enable, for interfacing to external buffers.
        self.oe = Signal()
        # input state exposed for edge_counter: latest serdes sample
        # support for short pulses will need a more involved solution
        self.input_state = Signal()

        # # #

        # Output
        self.submodules += _SerdesDriver(serdes_o=serdes.o,
                                         stb=self.rtlink.o.stb &
                                         (self.rtlink.o.address == 0),
                                         data=self.rtlink.o.data[0],
                                         fine_ts=self.rtlink.o.fine_ts,
                                         override_en=override_en,
                                         override_o=override_o)

        oe_k = Signal()
        self.oe.attr.add("no_retiming")
        self.sync.rio_phy += [
            If(self.rtlink.o.stb & (self.rtlink.o.address == 1),
               oe_k.eq(self.rtlink.o.data[0])),
            If(override_en, self.oe.eq(override_oe)).Else(self.oe.eq(oe_k))
        ]
        self.comb += serdes.oe.eq(self.oe)

        # Input
        sensitivity = Signal(2)
        sample = Signal()
        self.sync.rio += [
            sample.eq(0),
            If(self.rtlink.o.stb & self.rtlink.o.address[1],
               sensitivity.eq(self.rtlink.o.data),
               If(self.rtlink.o.address[0], sample.eq(1)))
        ]

        i = serdes.i[-1]
        self.comb += self.input_state.eq(i)
        i_d = Signal()
        self.sync.rio_phy += [
            i_d.eq(i),
            self.rtlink.i.data.eq(i),
        ]

        pe = PriorityEncoder(serdes_width)
        self.submodules += pe
        self.comb += pe.i.eq((serdes.i ^ Cat(i_d, serdes.i)) & (
            (serdes.i & Replicate(sensitivity[0], serdes_width))
            | (~serdes.i & Replicate(sensitivity[1], serdes_width))))
        self.sync.rio_phy += [
            self.rtlink.i.fine_ts.eq(pe.o),
            self.rtlink.i.stb.eq(sample | ~pe.n),
        ]
Esempio n. 9
0
    def __init__(self, slaves, depth=256, bus=None, with_wishbone=True):
        time_width, addr_width, data_width = [_[1] for _ in ventilator_layout]

        self.submodules.ctrl = CycleControl()

        self.submodules.ev = ev = EventManager()
        ev.in_readable = EventSourceLevel()
        ev.out_overflow = EventSourceProcess()
        ev.in_overflow = EventSourceLevel()
        ev.out_readable = EventSourceProcess()
        ev.stopped = EventSourceProcess()
        ev.started = EventSourceProcess()
        ev.finalize()

        self._in_time = CSRStatus(time_width)
        self._in_addr = CSRStatus(addr_width)
        self._in_data = CSRStatus(data_width)
        self._in_next = CSR()
        self._in_flush = CSR()

        self._out_time = CSRStorage(time_width, write_from_dev=with_wishbone)
        self._out_addr = CSRStorage(addr_width, write_from_dev=with_wishbone)
        self._out_data = CSRStorage(data_width, write_from_dev=with_wishbone)
        self._out_next = CSR()
        self._out_flush = CSR()

        self.busy = Signal()

        ###

        if with_wishbone:
            if bus is None:
                bus = wishbone.Interface()
            self.bus = bus

        slaves = [(self.ctrl, 0x00000000, 0xffffff00)] + slaves

        self.submodules.in_fifo = in_fifo = SyncFIFOBuffered(
            ventilator_layout, depth)
        self.submodules.out_fifo = out_fifo = SyncFIFOBuffered(
            ventilator_layout, depth)
        self.submodules.enc = PriorityEncoder(len(slaves))

        wb_in_next = Signal()
        wb_out_next = Signal()
        out_request = Signal()
        in_request = Signal()

        # CSRs and Events
        self.comb += [
            ev.in_readable.trigger.eq(in_fifo.readable),
            ev.out_overflow.trigger.eq(~out_fifo.writable),
            ev.in_overflow.trigger.eq(~in_fifo.writable),
            ev.out_readable.trigger.eq(out_fifo.readable),
            ev.started.trigger.eq(~self.ctrl.run),
            ev.stopped.trigger.eq(self.ctrl.run),
            self.ctrl.have_in.eq(~self.enc.n),
            self.ctrl.have_out.eq(out_fifo.readable),
            self._in_time.status.eq(in_fifo.dout.time),
            self._in_addr.status.eq(in_fifo.dout.addr),
            self._in_data.status.eq(in_fifo.dout.data),
            in_fifo.re.eq(self._in_next.re | wb_in_next),
            in_fifo.flush.eq(self._in_flush.re),
            out_fifo.din.time.eq(self._out_time.storage),
            out_fifo.din.addr.eq(self._out_addr.storage),
            out_fifo.din.data.eq(self._out_data.storage),
            out_fifo.we.eq(self._out_next.re | wb_out_next),
            out_fifo.flush.eq(self._out_flush.re),
        ]

        # din dout strobing
        self.comb += [
            # TODO: 0 <= diff <= plausibility range
            out_request.eq(out_fifo.readable & self.ctrl.run
                           & (self.ctrl.cycle == out_fifo.dout.time)),
            # ignore in_fifo.writable
            in_request.eq(~self.enc.n & self.ctrl.run),
            self.busy.eq(out_request | in_request),
        ]

        # to slaves
        addrs = []
        datas = []
        stbs = []
        acks = []
        for i, (slave, prefix, mask) in enumerate(slaves):
            prefix &= mask
            source = Source(slave_layout)
            sink = Sink(slave_layout)
            self.comb += [
                source.connect(slave.dout),
                sink.connect(slave.din),
            ]
            sel = Signal()
            acks.append(sel & source.ack)
            addrs.append(prefix | (sink.payload.addr & (~mask & 0xffffffff)))
            datas.append(sink.payload.data)
            stbs.append(sink.stb)
            self.comb += [
                sel.eq(out_fifo.dout.addr & mask == prefix),
                source.payload.addr.eq(out_fifo.dout.addr),
                source.payload.data.eq(out_fifo.dout.data),
                source.stb.eq(sel & out_request),
                sink.ack.eq((self.enc.o == i) & in_request),
            ]
        self.comb += out_fifo.re.eq(out_request & optree("|", acks))

        # from slaves
        self.comb += [
            self.enc.i.eq(Cat(stbs)),
            in_fifo.din.time.eq(self.ctrl.cycle),
            in_fifo.din.addr.eq(Array(addrs)[self.enc.o]),
            in_fifo.din.data.eq(Array(datas)[self.enc.o]),
            in_fifo.we.eq(in_request),
        ]

        # optional high throughput wishbone access
        if with_wishbone:
            self.comb += [
                self._out_time.dat_w.eq(bus.dat_w),
                self._out_addr.dat_w.eq(bus.dat_w),
                self._out_data.dat_w.eq(bus.dat_w),
                If(
                    bus.cyc & bus.stb,
                    If(
                        bus.we,
                        Case(
                            bus.adr[:4], {
                                0x5: wb_in_next.eq(1),
                                0x6: self._out_time.we.eq(1),
                                0x7: self._out_addr.we.eq(1),
                                0x8: self._out_data.we.eq(1),
                                0x9: wb_out_next.eq(1),
                            }),
                    ),
                    Case(
                        bus.adr[:4], {
                            0x0: bus.dat_r.eq(self.ctrl.cycle),
                            0x1: bus.dat_r.eq(self.ev.status.w),
                            0x2: bus.dat_r.eq(in_fifo.dout.time),
                            0x3: bus.dat_r.eq(in_fifo.dout.addr),
                            0x4: bus.dat_r.eq(in_fifo.dout.data),
                        }),
                )
            ]
            self.sync += bus.ack.eq(bus.cyc & bus.stb & ~bus.ack)
    def __init__(self, l0_trigger_generators,  outputs, l0_num=16, l1_num=16, 
            l1_extra=[], trigger_counter_len=4, 
            module_identifier="trigger_controller", with_ila=False):
        self.module_identifier = module_identifier
        self.trigger_counter_len = trigger_counter_len
        self.trigger_id_len = len(Signal(max=max(l1_num, 2)))

        assert self.trigger_id_len + trigger_counter_len <= 8

        # Trigger counter reset 
        self.trigger_controller_reset = Signal()
        phy = Output(self.trigger_controller_reset)
        self.submodules.reset_phy = phy
        self.add_rtio_channels(
                channel=Channel.from_phy(phy),
                device_id=f"{module_identifier}_trigger_controller_reset",
                module="artiq.coredevice.ttl",
                class_name="TTLOut")

        # Output config CSR
        l1_extra_triggers_num = sum([len(m.triggers) for m in l1_extra])
        l1_total_num = l1_num+l1_extra_triggers_num
        # FIXME: Add support for long RTIO output
        assert l1_total_num <= 32
        regs = [
            ("{}_l1_mask".format(output['label']), l1_total_num)
            for output in outputs
        ]
        output_config_phy = RtLinkCSR(regs, "output_config", 
            f"{module_identifier}_output_config")
        self.submodules.output_config = output_config_phy

        # Layer 0
        self.l0_coincidence_modules = l0_coincidence_modules = []
        for idx in range(l0_num):
            l0_module = RtioCoincidenceTriggerGenerator(
                    name=f"l0_{idx}",
                    generators=l0_trigger_generators,
                    reset_pulse_length=50,
                    pulse_max_length=255)
            l0_coincidence_modules.append(l0_module)
            setattr(self.submodules, f"module_l0_{idx}", l0_module)
            self.add_rtio_channels(
                channel=Channel.from_phy(l0_module),
                device_id=f"{module_identifier}_l0_{idx}",
                module="mcord_daq.coredevice.wrappers",
                class_name="RtioCoincidenceTriggerGeneratorWrapper",
                arguments={
                    "mask_mapping": l0_module.get_mask_mapping(),
                    "identifier": f"{module_identifier}_l0_{idx}"
                })

        trigger_lines = []
        trigger_counters = []
        trigger_labels = []

        self.l1_coincidence_modules = l1_coincidence_modules = []
        for idx in range(l1_num):
            # L1 coincidence module
            l1_module = RtioCoincidenceTriggerGenerator(
                    name=f"l1_{idx}",
                    generators=l0_coincidence_modules,
                    reset_pulse_length=50,
                    pulse_max_length=255)
            l1_coincidence_modules.append(l1_module)
            setattr(self.submodules, f"module_l1_{idx}", l1_module)
            self.add_rtio_channels(
                channel=Channel.from_phy(l1_module),
                device_id=f"{module_identifier}_l1_{idx}",
                module="mcord_daq.coredevice.wrappers",
                class_name="RtioCoincidenceTriggerGeneratorWrapper",
                arguments={
                    "mask_mapping": l1_module.get_mask_mapping(),
                    "identifier": f"{module_identifier}_l1_{idx}" 
                })

            trigger, trigger_counter = self._add_l1_output(
                l1_module.trigger, f"{module_identifier}_l1_{idx}")
            trigger_lines += [trigger]
            trigger_counters += [trigger_counter]
            trigger_labels += [f"l1_{idx}"]

        for module in l1_extra:
            for mod_trig in module.triggers:
                assert mod_trig['cd'] == "rio_phy"
                label = mod_trig['label']
                trigger, trigger_counter = self._add_l1_output(
                    mod_trig['signal'], f"{module_identifier}_l1_{label}")
                trigger_lines.append(trigger)
                trigger_counters.append(trigger_counter)
                trigger_labels += [label]
                
        # Output logic
        trigger_lines_array = Array(trigger_lines)
        trigger_counters_array = Array(trigger_counters)
        for output in outputs:
            l1_mask = getattr(output_config_phy, 
                "{}_l1_mask".format(output['label']))
            trigger_lines_vector = Cat(trigger_lines)
            trigger_lines_masked = Signal.like(trigger_lines_vector)
            self.comb += trigger_lines_masked.eq(l1_mask & trigger_lines_vector)
            output_select = Signal(max=max(len(trigger_lines), 2))
            priority_encoder = PriorityEncoder(len(trigger_lines_masked))
            self.submodules += priority_encoder
            self.comb += [
                priority_encoder.i.eq(trigger_lines_masked),
                output_select.eq(priority_encoder.o),
            ]
            self.sync.rio_phy += [
                output['trigger'].eq(0),
                If(trigger_lines_array[output_select] & ~priority_encoder.n,
                    output['trigger'].eq(trigger_lines_array[output_select]),
                    output['trigger_id'].eq(Cat(priority_encoder.o, trigger_counters_array[output_select])),
                )
            ]
        
        # Register core device
        self.register_coredevice(module_identifier, "mcord_daq.coredevice.trigger_controller", "TriggerController", arguments={
            "prefix": module_identifier,
            "l0_num": l0_num,
            "l1_num": l1_num,
            "output_config_csr": f"{module_identifier}_output_config",
            "l1_mask": trigger_labels,
            "reset_device": f"{module_identifier}_trigger_controller_reset"
        })

        if with_ila:
            for t, l, p in zip(self.l0_coincidence_modules[0].trigger_in_signals, 
                    self.l0_coincidence_modules[0].trigger_in_labels,
                    self.l0_coincidence_modules[0].pulses):
                self.submodules += [
                    ILAProbe(t, f"dbg_{l}_trig"),
                    ILAProbe(p, f"dbg_{l}_pulse")
                ]
            self.submodules += [ILAProbe(self.l0_coincidence_modules[0].pulse_length, "l0_0_pulse_length")]
            for idx, mod in enumerate(l0_coincidence_modules):
                self.submodules += [ILAProbe(mod.trigger, f"l0_trigger_{idx}")]
            for idx, mod in enumerate(l1_coincidence_modules):
                self.submodules += [ILAProbe(mod.trigger, f"l1_trigger_{idx}")]
            for idx, mod in enumerate(l1_extra):
                self.submodules += [ILAProbe(t['signal'], "l1_extra_{}".format(t['label'])) for t in mod.triggers]
            for output in outputs:
                self.submodules += [
                    ILAProbe(output['trigger'], "output_trigger_{}".format(output['label'])),
                    ILAProbe(output['trigger_id'], "output_trigger_id_{}".format(output['label']))
                ]