def __init__(self, nchan=3, depth=8): self.valid_i = Signal() self.chan_synced = Signal() self._r_channels_synced = CSRStatus() lst_control = [] all_control = Signal() for i in range(nchan): name = "data_in" + str(i) data_in = Record(channel_layout, name=name) setattr(self, name, data_in) name = "data_out" + str(i) data_out = Record(channel_layout, name=name) setattr(self, name, data_out) ### syncbuffer = RenameClockDomains(_SyncBuffer(layout_len(channel_layout), depth), "pix") self.submodules += syncbuffer self.comb += [syncbuffer.din.eq(data_in.raw_bits()), data_out.raw_bits().eq(syncbuffer.dout)] is_control = Signal() self.comb += [is_control.eq(~data_out.de), syncbuffer.re.eq(~is_control | all_control)] lst_control.append(is_control) some_control = Signal() self.comb += [all_control.eq(optree("&", lst_control)), some_control.eq(optree("|", lst_control))] self.sync.pix += If(~self.valid_i, self.chan_synced.eq(0)).Else( If(some_control, If(all_control, self.chan_synced.eq(1)).Else(self.chan_synced.eq(0))) ) self.specials += MultiReg(self.chan_synced, self._r_channels_synced.status)
def __init__(self, in_size): self.submodules.raw_slicer = ResetInserter()(RawSlicer( in_size//8, layout_len(record_layout)//8, 8)) self.submodules.record_converter = RecordConverter(self.raw_slicer) self.end_marker_found = self.record_converter.end_marker_found self.flush = self.record_converter.flush self.sink = self.raw_slicer.sink self.source = self.record_converter.source
def __init__(self, nchan=3, depth=8): self.valid_i = Signal() self.chan_synced = Signal() self._channels_synced = CSRStatus() lst_control = [] all_control = Signal() for i in range(nchan): name = "data_in" + str(i) data_in = Record(channel_layout, name=name) setattr(self, name, data_in) name = "data_out" + str(i) data_out = Record(channel_layout, name=name) setattr(self, name, data_out) # # # syncbuffer = _SyncBuffer(layout_len(channel_layout), depth) syncbuffer = ClockDomainsRenamer("pix")(syncbuffer) self.submodules += syncbuffer self.comb += [ syncbuffer.din.eq(data_in.raw_bits()), data_out.raw_bits().eq(syncbuffer.dout) ] is_control = Signal() self.comb += [ is_control.eq(~data_out.de), syncbuffer.re.eq(~is_control | all_control) ] lst_control.append(is_control) some_control = Signal() self.comb += [ all_control.eq(reduce(and_, lst_control)), some_control.eq(reduce(or_, lst_control)) ] self.sync.pix += \ If(~self.valid_i, self.chan_synced.eq(0) ).Else( If(some_control, If(all_control, self.chan_synced.eq(1) ).Else( self.chan_synced.eq(0) ) ) ) self.specials += MultiReg(self.chan_synced, self._channels_synced.status)
def __init__(self, stream_slicer): self.source = stream.Endpoint(record_layout) self.end_marker_found = Signal() self.flush = Signal() hdrlen = (layout_len(record_layout) - 512)//8 record_raw = Record(record_layout) self.comb += [ record_raw.raw_bits().eq(stream_slicer.source), self.source.channel.eq(record_raw.channel), self.source.timestamp.eq(record_raw.timestamp), self.source.address.eq(record_raw.address), Case(record_raw.length, {hdrlen+i: self.source.data.eq(record_raw.data[:i*8]) for i in range(1, 512//8+1)}), ] fsm = FSM(reset_state="FLOWING") self.submodules += fsm fsm.act("FLOWING", If(stream_slicer.source_stb, If(record_raw.length == 0, NextState("END_MARKER_FOUND") ).Else( self.source.stb.eq(1) ) ), If(self.source.ack, stream_slicer.source_consume.eq(record_raw.length) ) ) fsm.act("END_MARKER_FOUND", self.end_marker_found.eq(1), If(self.flush, stream_slicer.flush.eq(1), NextState("WAIT_FLUSH") ) ) fsm.act("WAIT_FLUSH", If(stream_slicer.flush_done, NextState("SEND_EOP") ) ) fsm.act("SEND_EOP", self.source.eop.eq(1), self.source.stb.eq(1), If(self.source.ack, NextState("FLOWING")) )
def __init__(self, width_or_layout, depth): self.we = Signal() self.writable = Signal() # not full self.re = Signal() self.readable = Signal() # not empty if isinstance(width_or_layout, list): self.din = Record(width_or_layout) self.dout = Record(width_or_layout) self.din_bits = self.din.raw_bits() self.dout_bits = self.dout.raw_bits() self.width = layout_len(width_or_layout) else: self.din = Signal(width_or_layout) self.dout = Signal(width_or_layout) self.din_bits = self.din self.dout_bits = self.dout self.width = width_or_layout
__all__ = ["Analyzer"] input_output_layout = [("message_type", 2), ("channel", 30), ("timestamp", 64), ("rtio_counter", 64), ("address_padding", 32), ("data", 64)] exception_layout = [("message_type", 2), ("channel", 30), ("padding0", 64), ("rtio_counter", 64), ("exception_type", 8), ("padding1", 88)] stopped_layout = [("message_type", 2), ("padding0", 94), ("rtio_counter", 64), ("padding1", 96)] message_len = 256 assert layout_len(input_output_layout) == message_len assert layout_len(exception_layout) == message_len assert layout_len(stopped_layout) == message_len class MessageEncoder(Module, AutoCSR): def __init__(self, kcsrs, rtio_counter, enable): self.source = stream.Endpoint([("data", message_len)]) self.overflow = CSRStatus() self.overflow_reset = CSR() # # # input_output_stb = Signal() input_output = Record(input_output_layout)
("padding0", 64), ("rtio_counter", 64), ("exception_type", 8), ("padding1", 88) ] stopped_layout = [ ("message_type", 2), ("padding0", 94), ("rtio_counter", 64), ("padding1", 96) ] message_len = 256 assert layout_len(input_output_layout) == message_len assert layout_len(exception_layout) == message_len assert layout_len(stopped_layout) == message_len class MessageEncoder(Module, AutoCSR): def __init__(self, tsc, cri, enable): self.source = stream.Endpoint([("data", message_len)]) self.overflow = CSRStatus() self.overflow_reset = CSR() # # # read_wait_event = cri.i_status[2] read_wait_event_r = Signal()
def __init__(self, cachesize, lasmim): self.wishbone = wishbone.Interface() ### data_width = flen(self.wishbone.dat_r) if lasmim.dw > data_width and (lasmim.dw % data_width) != 0: raise ValueError("LASMI data width must be a multiple of {dw}".format(dw=data_width)) if lasmim.dw < data_width and (data_width % lasmim.dw) != 0: raise ValueError("WISHBONE data width must be a multiple of {dw}".format(dw=lasmim.dw)) # Split address: # TAG | LINE NUMBER | LINE OFFSET offsetbits = log2_int(max(lasmim.dw//data_width, 1)) addressbits = lasmim.aw + offsetbits linebits = log2_int(cachesize) - offsetbits tagbits = addressbits - linebits wordbits = data_width//lasmim.dw adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits) word = Signal(wordbits) if wordbits else None # Data memory data_mem = Memory(lasmim.dw*2**wordbits, 2**linebits) data_port = data_mem.get_port(write_capable=True, we_granularity=8) self.specials += data_mem, data_port write_from_lasmi = Signal() write_to_lasmi = Signal() if adr_offset is None: adr_offset_r = None else: adr_offset_r = Signal(offsetbits) self.sync += adr_offset_r.eq(adr_offset) self.comb += [ data_port.adr.eq(adr_line), If(write_from_lasmi, displacer(lasmim.dat_r, word, data_port.dat_w), displacer(Replicate(1, lasmim.dw//8), word, data_port.we) ).Else( data_port.dat_w.eq(Replicate(self.wishbone.dat_w, max(lasmim.dw//data_width, 1))), If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack, displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True) ) ), If(write_to_lasmi, chooser(data_port.dat_r, word, lasmim.dat_w), lasmim.dat_we.eq(2**(lasmim.dw//8)-1) ), chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True) ] # Tag memory tag_layout = [("tag", tagbits), ("dirty", 1)] tag_mem = Memory(layout_len(tag_layout), 2**linebits) tag_port = tag_mem.get_port(write_capable=True) self.specials += tag_mem, tag_port tag_do = Record(tag_layout) tag_di = Record(tag_layout) self.comb += [ tag_do.raw_bits().eq(tag_port.dat_r), tag_port.dat_w.eq(tag_di.raw_bits()) ] self.comb += [ tag_port.adr.eq(adr_line), tag_di.tag.eq(adr_tag) ] if word is not None: self.comb += lasmim.adr.eq(Cat(word, adr_line, tag_do.tag)) else: self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag)) # Lasmim word computation, word_clr and word_inc will be simplified # at synthesis when wordbits=0 word_clr = Signal() word_inc = Signal() if word is not None: self.sync += \ If(word_clr, word.eq(0), ).Elif(word_inc, word.eq(word+1) ) def word_is_last(word): if word is not None: return word == 2**wordbits-1 else: return 1 # Control FSM assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1) fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1) fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1) fsm.act("IDLE", If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT")) ) fsm.act("TEST_HIT", word_clr.eq(1), If(tag_do.tag == adr_tag, self.wishbone.ack.eq(1), If(self.wishbone.we, tag_di.dirty.eq(1), tag_port.we.eq(1) ), NextState("IDLE") ).Else( If(tag_do.dirty, NextState("EVICT_REQUEST") ).Else( NextState("REFILL_WRTAG") ) ) ) fsm.act("EVICT_REQUEST", lasmim.stb.eq(1), lasmim.we.eq(1), If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK")) ) fsm.act("EVICT_WAIT_DATA_ACK", If(lasmim.dat_ack, NextState("EVICT_DATAD")) ) fsm.act("EVICT_DATA", write_to_lasmi.eq(1), word_inc.eq(1), If(word_is_last(word), NextState("REFILL_WRTAG"), ).Else( NextState("EVICT_REQUEST") ) ) fsm.act("REFILL_WRTAG", # Write the tag first to set the LASMI address tag_port.we.eq(1), word_clr.eq(1), NextState("REFILL_REQUEST") ) fsm.act("REFILL_REQUEST", lasmim.stb.eq(1), If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK")) ) fsm.act("REFILL_WAIT_DATA_ACK", If(lasmim.dat_ack, NextState("REFILL_DATAD")) ) fsm.act("REFILL_DATA", write_from_lasmi.eq(1), word_inc.eq(1), If(word_is_last(word), NextState("TEST_HIT"), ).Else( NextState("REFILL_REQUEST") ) )
def __init__(self, cachesize, lasmim): self.wishbone = wishbone.Interface() ### data_width = flen(self.wishbone.dat_r) if lasmim.dw > data_width and (lasmim.dw % data_width) != 0: raise ValueError( "LASMI data width must be a multiple of {dw}".format( dw=data_width)) if lasmim.dw < data_width and (data_width % lasmim.dw) != 0: raise ValueError( "WISHBONE data width must be a multiple of {dw}".format( dw=lasmim.dw)) # Split address: # TAG | LINE NUMBER | LINE OFFSET offsetbits = log2_int(max(lasmim.dw // data_width, 1)) addressbits = lasmim.aw + offsetbits linebits = log2_int(cachesize) - offsetbits tagbits = addressbits - linebits wordbits = log2_int(max(data_width // lasmim.dw, 1)) adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits) word = Signal(wordbits) if wordbits else None # Data memory data_mem = Memory(lasmim.dw * 2**wordbits, 2**linebits) data_port = data_mem.get_port(write_capable=True, we_granularity=8) self.specials += data_mem, data_port write_from_lasmi = Signal() write_to_lasmi = Signal() if adr_offset is None: adr_offset_r = None else: adr_offset_r = Signal(offsetbits) self.sync += adr_offset_r.eq(adr_offset) self.comb += [ data_port.adr.eq(adr_line), If(write_from_lasmi, displacer(lasmim.dat_r, word, data_port.dat_w), displacer(Replicate(1, lasmim.dw // 8), word, data_port.we)).Else( data_port.dat_w.eq( Replicate(self.wishbone.dat_w, max(lasmim.dw // data_width, 1))), If( self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack, displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True))), If(write_to_lasmi, chooser(data_port.dat_r, word, lasmim.dat_w), lasmim.dat_we.eq(2**(lasmim.dw // 8) - 1)), chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True) ] # Tag memory tag_layout = [("tag", tagbits), ("dirty", 1)] tag_mem = Memory(layout_len(tag_layout), 2**linebits) tag_port = tag_mem.get_port(write_capable=True) self.specials += tag_mem, tag_port tag_do = Record(tag_layout) tag_di = Record(tag_layout) self.comb += [ tag_do.raw_bits().eq(tag_port.dat_r), tag_port.dat_w.eq(tag_di.raw_bits()) ] self.comb += [tag_port.adr.eq(adr_line), tag_di.tag.eq(adr_tag)] if word is not None: self.comb += lasmim.adr.eq(Cat(word, adr_line, tag_do.tag)) else: self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag)) # Lasmim word computation, word_clr and word_inc will be simplified # at synthesis when wordbits=0 word_clr = Signal() word_inc = Signal() if word is not None: self.sync += \ If(word_clr, word.eq(0), ).Elif(word_inc, word.eq(word+1) ) def word_is_last(word): if word is not None: return word == 2**wordbits - 1 else: return 1 # Control FSM assert (lasmim.write_latency >= 1 and lasmim.read_latency >= 1) fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency - 1) fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency - 1) fsm.act( "IDLE", If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT"))) fsm.act( "TEST_HIT", word_clr.eq(1), If(tag_do.tag == adr_tag, self.wishbone.ack.eq(1), If(self.wishbone.we, tag_di.dirty.eq(1), tag_port.we.eq(1)), NextState("IDLE")).Else( If(tag_do.dirty, NextState("EVICT_REQUEST")).Else( NextState("REFILL_WRTAG")))) fsm.act("EVICT_REQUEST", lasmim.stb.eq(1), lasmim.we.eq(1), If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK"))) fsm.act("EVICT_WAIT_DATA_ACK", If(lasmim.dat_ack, NextState("EVICT_DATAD"))) fsm.act( "EVICT_DATA", write_to_lasmi.eq(1), word_inc.eq(1), If( word_is_last(word), NextState("REFILL_WRTAG"), ).Else(NextState("EVICT_REQUEST"))) fsm.act( "REFILL_WRTAG", # Write the tag first to set the LASMI address tag_port.we.eq(1), word_clr.eq(1), NextState("REFILL_REQUEST")) fsm.act("REFILL_REQUEST", lasmim.stb.eq(1), If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK"))) fsm.act("REFILL_WAIT_DATA_ACK", If(lasmim.dat_ack, NextState("REFILL_DATAD"))) fsm.act( "REFILL_DATA", write_from_lasmi.eq(1), word_inc.eq(1), If( word_is_last(word), NextState("TEST_HIT"), ).Else(NextState("REFILL_REQUEST")))
("timestamp", 64), ("rtio_counter", 64), ("address_padding", 32), ("data", 64) ] exception_layout = [ ("message_type", 2), ("channel", 30), ("padding0", 64), ("rtio_counter", 64), ("exception_type", 8), ("padding1", 88) ] assert layout_len(input_output_layout) == 256 assert layout_len(exception_layout) == 256 class MessageEncoder(Module, AutoCSR): def __init__(self, rtio_core): self.source = stream.Endpoint([("data", 256)]) self.overflow = CSRStatus() self.overflow_reset = CSR() # # # kcsrs = rtio_core.kcsrs input_output_stb = Signal()
def __init__(self, cachesize, lasmim): self.wishbone = wishbone.Interface() ### if lasmim.dw <= 32: raise ValueError("LASMI data width must be strictly larger than 32") if (lasmim.dw % 32) != 0: raise ValueError("LASMI data width must be a multiple of 32") # Split address: # TAG | LINE NUMBER | LINE OFFSET offsetbits = log2_int(lasmim.dw//32) addressbits = lasmim.aw + offsetbits linebits = log2_int(cachesize) - offsetbits tagbits = addressbits - linebits adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits) # Data memory data_mem = Memory(lasmim.dw, 2**linebits) data_port = data_mem.get_port(write_capable=True, we_granularity=8) self.specials += data_mem, data_port write_from_lasmi = Signal() write_to_lasmi = Signal() adr_offset_r = Signal(offsetbits) self.comb += [ data_port.adr.eq(adr_line), If(write_from_lasmi, data_port.dat_w.eq(lasmim.dat_r), data_port.we.eq(Replicate(1, lasmim.dw//8)) ).Else( data_port.dat_w.eq(Replicate(self.wishbone.dat_w, lasmim.dw//32)), If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack, displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True) ) ), If(write_to_lasmi, lasmim.dat_w.eq(data_port.dat_r), lasmim.dat_we.eq(2**(lasmim.dw//8)-1) ), chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True) ] self.sync += adr_offset_r.eq(adr_offset) # Tag memory tag_layout = [("tag", tagbits), ("dirty", 1)] tag_mem = Memory(layout_len(tag_layout), 2**linebits) tag_port = tag_mem.get_port(write_capable=True) self.specials += tag_mem, tag_port tag_do = Record(tag_layout) tag_di = Record(tag_layout) self.comb += [ tag_do.raw_bits().eq(tag_port.dat_r), tag_port.dat_w.eq(tag_di.raw_bits()) ] self.comb += [ tag_port.adr.eq(adr_line), tag_di.tag.eq(adr_tag), lasmim.adr.eq(Cat(adr_line, tag_do.tag)) ] # Control FSM assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1) fsm = FSM("IDLE", "TEST_HIT", "EVICT_REQUEST", "EVICT_WAIT_DATA_ACK", "EVICT_DATA", "REFILL_WRTAG", "REFILL_REQUEST", "REFILL_WAIT_DATA_ACK", "REFILL_DATA", delayed_enters=[ ("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1), ("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1) ]) self.submodules += fsm fsm.act(fsm.IDLE, If(self.wishbone.cyc & self.wishbone.stb, fsm.next_state(fsm.TEST_HIT)) ) fsm.act(fsm.TEST_HIT, If(tag_do.tag == adr_tag, self.wishbone.ack.eq(1), If(self.wishbone.we, tag_di.dirty.eq(1), tag_port.we.eq(1) ), fsm.next_state(fsm.IDLE) ).Else( If(tag_do.dirty, fsm.next_state(fsm.EVICT_REQUEST) ).Else( fsm.next_state(fsm.REFILL_WRTAG) ) ) ) fsm.act(fsm.EVICT_REQUEST, lasmim.stb.eq(1), lasmim.we.eq(1), If(lasmim.req_ack, fsm.next_state(fsm.EVICT_WAIT_DATA_ACK)) ) fsm.act(fsm.EVICT_WAIT_DATA_ACK, If(lasmim.dat_ack, fsm.next_state(fsm.EVICT_DATAD)) ) fsm.act(fsm.EVICT_DATA, write_to_lasmi.eq(1), fsm.next_state(fsm.REFILL_WRTAG) ) fsm.act(fsm.REFILL_WRTAG, # Write the tag first to set the LASMI address tag_port.we.eq(1), fsm.next_state(fsm.REFILL_REQUEST) ) fsm.act(fsm.REFILL_REQUEST, lasmim.stb.eq(1), If(lasmim.req_ack, fsm.next_state(fsm.REFILL_WAIT_DATA_ACK)) ) fsm.act(fsm.REFILL_WAIT_DATA_ACK, If(lasmim.dat_ack, fsm.next_state(fsm.REFILL_DATAD)) ) fsm.act(fsm.REFILL_DATA, write_from_lasmi.eq(1), fsm.next_state(fsm.TEST_HIT) )
def get_fragment(self): comb = [] sync = [] aaw = self.asmiport.hub.aw adw = self.asmiport.hub.dw # Split address: # TAG | LINE NUMBER | LINE OFFSET offsetbits = log2_int(adw//32) addressbits = aaw + offsetbits linebits = log2_int(self.cachesize) - offsetbits tagbits = addressbits - linebits adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits) # Data memory data_mem = Memory(adw, 2**linebits) data_port = data_mem.get_port(write_capable=True, we_granularity=8) write_from_asmi = Signal() write_to_asmi = Signal() adr_offset_r = Signal(offsetbits) comb += [ data_port.adr.eq(adr_line), If(write_from_asmi, data_port.dat_w.eq(self.asmiport.dat_r), data_port.we.eq(Replicate(1, adw//8)) ).Else( data_port.dat_w.eq(Replicate(self.wishbone.dat_w, adw//32)), If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack, displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True) ) ), If(write_to_asmi, self.asmiport.dat_w.eq(data_port.dat_r)), self.asmiport.dat_wm.eq(0), chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True) ] sync += [ adr_offset_r.eq(adr_offset) ] # Tag memory tag_layout = [("tag", tagbits), ("dirty", 1)] tag_mem = Memory(layout_len(tag_layout), 2**linebits) tag_port = tag_mem.get_port(write_capable=True) tag_do = Record(tag_layout) tag_di = Record(tag_layout) comb += [ tag_do.raw_bits().eq(tag_port.dat_r), tag_port.dat_w.eq(tag_di.raw_bits()) ] comb += [ tag_port.adr.eq(adr_line), tag_di.tag.eq(adr_tag), self.asmiport.adr.eq(Cat(adr_line, tag_do.tag)) ] # Control FSM write_to_asmi_pre = Signal() sync.append(write_to_asmi.eq(write_to_asmi_pre)) fsm = FSM("IDLE", "TEST_HIT", "EVICT_ISSUE", "EVICT_WAIT", "REFILL_WRTAG", "REFILL_ISSUE", "REFILL_WAIT", "REFILL_COMPLETE") fsm.act(fsm.IDLE, If(self.wishbone.cyc & self.wishbone.stb, fsm.next_state(fsm.TEST_HIT)) ) fsm.act(fsm.TEST_HIT, If(tag_do.tag == adr_tag, self.wishbone.ack.eq(1), If(self.wishbone.we, tag_di.dirty.eq(1), tag_port.we.eq(1) ), fsm.next_state(fsm.IDLE) ).Else( If(tag_do.dirty, fsm.next_state(fsm.EVICT_ISSUE) ).Else( fsm.next_state(fsm.REFILL_WRTAG) ) ) ) fsm.act(fsm.EVICT_ISSUE, self.asmiport.stb.eq(1), self.asmiport.we.eq(1), If(self.asmiport.ack, fsm.next_state(fsm.EVICT_WAIT)) ) fsm.act(fsm.EVICT_WAIT, # Data is actually sampled by the memory controller in the next state. # But since the data memory has one cycle latency, it gets the data # at the address given during this cycle. If(self.asmiport.get_call_expression(), write_to_asmi_pre.eq(1), fsm.next_state(fsm.REFILL_WRTAG) ) ) fsm.act(fsm.REFILL_WRTAG, # Write the tag first to set the ASMI address tag_port.we.eq(1), fsm.next_state(fsm.REFILL_ISSUE) ) fsm.act(fsm.REFILL_ISSUE, self.asmiport.stb.eq(1), If(self.asmiport.ack, fsm.next_state(fsm.REFILL_WAIT)) ) fsm.act(fsm.REFILL_WAIT, If(self.asmiport.get_call_expression(), fsm.next_state(fsm.REFILL_COMPLETE)) ) fsm.act(fsm.REFILL_COMPLETE, write_from_asmi.eq(1), fsm.next_state(fsm.TEST_HIT) ) return Fragment(comb, sync, specials={data_mem, tag_mem}) \ + fsm.get_fragment()
def __init__(self, cachesize, lasmim, wbm=None): if wbm is None: wbm = wishbone.Interface() self.wishbone = wbm ### data_width = flen(self.wishbone.dat_r) if lasmim.dw < data_width: raise ValueError("LASMI data width must be >= {dw}".format(dw=data_width)) if (lasmim.dw % data_width) != 0: raise ValueError("LASMI data width must be a multiple of {dw}".format(dw=data_width)) # Split address: # TAG | LINE NUMBER | LINE OFFSET offsetbits = log2_int(lasmim.dw//data_width) addressbits = lasmim.aw + offsetbits linebits = log2_int(cachesize) - offsetbits tagbits = addressbits - linebits adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits) # Data memory data_mem = Memory(lasmim.dw, 2**linebits) data_port = data_mem.get_port(write_capable=True, we_granularity=8) self.specials += data_mem, data_port write_from_lasmi = Signal() write_to_lasmi = Signal() if adr_offset is None: adr_offset_r = None else: adr_offset_r = Signal(offsetbits) self.sync += adr_offset_r.eq(adr_offset) self.comb += [ data_port.adr.eq(adr_line), If(write_from_lasmi, data_port.dat_w.eq(lasmim.dat_r), data_port.we.eq(Replicate(1, lasmim.dw//8)) ).Else( data_port.dat_w.eq(Replicate(self.wishbone.dat_w, lasmim.dw//data_width)), If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack, displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True) ) ), If(write_to_lasmi, lasmim.dat_w.eq(data_port.dat_r), lasmim.dat_we.eq(2**(lasmim.dw//8)-1) ), chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True) ] # Tag memory tag_layout = [("tag", tagbits), ("dirty", 1)] tag_mem = Memory(layout_len(tag_layout), 2**linebits) tag_port = tag_mem.get_port(write_capable=True) self.specials += tag_mem, tag_port tag_do = Record(tag_layout) tag_di = Record(tag_layout) self.comb += [ tag_do.raw_bits().eq(tag_port.dat_r), tag_port.dat_w.eq(tag_di.raw_bits()) ] self.comb += [ tag_port.adr.eq(adr_line), tag_di.tag.eq(adr_tag), lasmim.adr.eq(Cat(adr_line, tag_do.tag)) ] # Control FSM assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1) fsm = FSM() self.submodules += fsm fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1) fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1) fsm.act("IDLE", If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT")) ) fsm.act("TEST_HIT", If(tag_do.tag == adr_tag, self.wishbone.ack.eq(1), If(self.wishbone.we, tag_di.dirty.eq(1), tag_port.we.eq(1) ), NextState("IDLE") ).Else( If(tag_do.dirty, NextState("EVICT_REQUEST") ).Else( NextState("REFILL_WRTAG") ) ) ) fsm.act("EVICT_REQUEST", lasmim.stb.eq(1), lasmim.we.eq(1), If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK")) ) fsm.act("EVICT_WAIT_DATA_ACK", If(lasmim.dat_ack, NextState("EVICT_DATAD")) ) fsm.act("EVICT_DATA", write_to_lasmi.eq(1), NextState("REFILL_WRTAG") ) fsm.act("REFILL_WRTAG", # Write the tag first to set the LASMI address tag_port.we.eq(1), NextState("REFILL_REQUEST") ) fsm.act("REFILL_REQUEST", lasmim.stb.eq(1), If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK")) ) fsm.act("REFILL_WAIT_DATA_ACK", If(lasmim.dat_ack, NextState("REFILL_DATAD")) ) fsm.act("REFILL_DATA", write_from_lasmi.eq(1), NextState("TEST_HIT") )