wishbone2lasmi: support lasmim data_width < wishbone data_width
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 18 Apr 2014 11:49:58 +0000 (13:49 +0200)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Fri, 18 Apr 2014 13:00:53 +0000 (15:00 +0200)
migen/bus/wishbone2lasmi.py

index 39a9daebedb9993c968c74f64876270007f87a66..cda742e6c6f9099dffe359c3b22255aa27a3b5d3 100644 (file)
@@ -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")
+                       )
                )