def __init__(self, width, packet_size=512): super().__init__(width, 0) self.submodules.inner = _FIFOInterface(width, 0) self.flush = Signal() self.flush_s = Signal() self.queued = Signal(max=1 + packet_size) self.complete = Signal() self.pending = Signal() self.flushed = Signal()
def __init__(self, width): super().__init__(width, 0) self.submodules.fifo = _FIFOInterface(width, 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")))