From 86f852a5f1568952c5d342f837e7deda7a7db162 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 18 Apr 2014 13:49:58 +0200 Subject: [PATCH] wishbone2lasmi: support lasmim data_width < wishbone data_width --- migen/bus/wishbone2lasmi.py | 71 +++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 19 deletions(-) diff --git a/migen/bus/wishbone2lasmi.py b/migen/bus/wishbone2lasmi.py index 39a9daeb..cda742e6 100644 --- a/migen/bus/wishbone2lasmi.py +++ b/migen/bus/wishbone2lasmi.py @@ -6,29 +6,29 @@ from migen.genlib.record import Record, layout_len # cachesize (in 32-bit words) is the size of the data store, must be a power of 2 class WB2LASMI(Module): - def __init__(self, cachesize, lasmim, wbm=None): - if wbm is None: - wbm = wishbone.Interface() - self.wishbone = wbm + def __init__(self, cachesize, lasmim): + self.wishbone = wishbone.Interface() ### 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: + 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(lasmim.dw//data_width) + 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**linebits) + 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 @@ -43,16 +43,16 @@ class WB2LASMI(Module): 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)) + 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, lasmim.dw//data_width)), + 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, - lasmim.dat_w.eq(data_port.dat_r), + 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) @@ -73,13 +73,34 @@ class WB2LASMI(Module): self.comb += [ tag_port.adr.eq(adr_line), - tag_di.tag.eq(adr_tag), - lasmim.adr.eq(Cat(adr_line, tag_do.tag)) + 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() + fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1) @@ -89,6 +110,7 @@ class WB2LASMI(Module): 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, @@ -115,12 +137,18 @@ class WB2LASMI(Module): ) fsm.act("EVICT_DATA", write_to_lasmi.eq(1), - NextState("REFILL_WRTAG") + 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", @@ -132,5 +160,10 @@ class WB2LASMI(Module): ) fsm.act("REFILL_DATA", write_from_lasmi.eq(1), - NextState("TEST_HIT") + word_inc.eq(1), + If(word_is_last(word), + NextState("TEST_HIT"), + ).Else( + NextState("REFILL_REQUEST") + ) ) -- 2.30.2