lasmi: separate request and data ack to support bankmachine FIFOs (buggy/incomplete)
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 17 Jun 2013 21:36:03 +0000 (23:36 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 17 Jun 2013 21:36:03 +0000 (23:36 +0200)
migen/actorlib/dma_lasmi.py
migen/bus/lasmibus.py
migen/bus/wishbone2lasmi.py

index 41ac1f44b9f2d483d4ed0a377d4bdc1a32335502..691c771f09b176f8072be6112793da90ee1ea4cc 100644 (file)
@@ -11,8 +11,7 @@ class Reader(Module):
                ###
 
                if fifo_depth is None:
-                       fifo_depth = lasmim.read_latency + 2
-               assert(fifo_depth >= lasmim.read_latency)
+                       fifo_depth = lasmim.req_queue_size + lasmim.read_latency + 2
        
                # request issuance
                request_enable = Signal()
@@ -22,8 +21,8 @@ class Reader(Module):
                        lasmim.we.eq(0),
                        lasmim.stb.eq(self.address.stb & request_enable),
                        lasmim.adr.eq(self.address.payload.a),
-                       self.address.ack.eq(lasmim.ack),
-                       request_issued.eq(lasmim.stb & lasmim.ack)
+                       self.address.ack.eq(lasmim.req_ack),
+                       request_issued.eq(lasmim.stb & lasmim.req_ack)
                ]
 
                # FIFO reservation level counter
@@ -44,7 +43,7 @@ class Reader(Module):
                ]
 
                # data available
-               data_available = request_issued
+               data_available = lasmim.dat_ack
                for i in range(lasmim.read_latency):
                        new_data_available = Signal()
                        self.sync += new_data_available.eq(data_available)
@@ -66,42 +65,38 @@ class Reader(Module):
 
 
 class Writer(Module):
-       def __init__(self, lasmim):
+       def __init__(self, lasmim, fifo_depth=None):
                self.address_data = Sink([("a", lasmim.aw), ("d", lasmim.dw)])
                self.busy = Signal()
 
                ###
 
+               if fifo_depth is None:
+                       fifo_depth = lasmim.req_queue_size + lasmim.read_latency + 2
+
+               fifo = SyncFIFO(lasmim.dw, fifo_depth)
+               self.submodules += fifo
+
                self.comb += [
                        lasmim.we.eq(1),
-                       lasmim.stb.eq(self.address_data.stb),
+                       lasmim.stb.eq(fifo.writable & self.address_data.stb),
                        lasmim.adr.eq(self.address_data.payload.a),
-                       self.address_data.ack.eq(lasmim.ack)
-               ]
-
-               busy_expr = 0
-               data_valid = Signal()
-               data = Signal(lasmim.dw)
-               self.comb += [
-                       data_valid.eq(lasmim.stb & lasmim.ack),
-                       data.eq(self.address_data.payload.d)
+                       self.address_data.ack.eq(fifo.writable & lasmim.req_ack),
+                       fifo.we.eq(self.address_data.stb & lasmim.req_ack),
+                       fifo.din.eq(self.address_data.payload.d)
                ]
 
+               data_valid = lasmim.dat_ack
                for i in range(lasmim.write_latency):
                        new_data_valid = Signal()
-                       new_data = Signal(lasmim.dw)
-                       self.sync += [
-                               new_data_valid.eq(data_valid),
-                               new_data.eq(data)
-                       ]
-                       busy_expr = busy_expr | new_data_valid
+                       self.sync += new_data_valid.eq(data_valid),
                        data_valid = new_data_valid
-                       data = new_data
 
                self.comb += [
+                       fifo.re.eq(data_valid),
                        If(data_valid,
                                lasmim.dat_we.eq(2**(lasmim.dw//8)-1),
-                               lasmim.dat_w.eq(data)
+                               lasmim.dat_w.eq(fifo.dout)
                        ),
-                       self.busy.eq(busy_expr)
+                       self.busy.eq(fifo.readable)
                ]
index be724ac13d66a2b61692bd9e3733a30d6d043b6f..949530a570360ce178265b4d2230c76b40e73795 100644 (file)
@@ -5,10 +5,11 @@ from migen.genlib.record import *
 from migen.genlib.misc import optree
 
 class Interface(Record):
-       def __init__(self, aw, dw, nbanks, read_latency, write_latency):
+       def __init__(self, aw, dw, nbanks, req_queue_size, read_latency, write_latency):
                self.aw = aw
                self.dw = dw
                self.nbanks = nbanks
+               self.req_queue_size = req_queue_size
                self.read_latency = read_latency
                self.write_latency = write_latency
 
@@ -16,7 +17,9 @@ class Interface(Record):
                        ("adr",         aw,             DIR_M_TO_S),
                        ("we",          1,              DIR_M_TO_S),
                        ("stb",         1,              DIR_M_TO_S),
-                       ("ack",         1,              DIR_S_TO_M)
+                       ("req_ack",     1,              DIR_S_TO_M),
+                       ("dat_ack",     1,              DIR_S_TO_M),
+                       ("lock",        1,              DIR_S_TO_M)
                ]
                if nbanks > 1:
                        layout = [("bank"+str(i), bank_layout) for i in range(nbanks)]
@@ -43,12 +46,13 @@ class Crossbar(Module):
                rca_bits = _getattr_all(controllers, "aw")
                dw = _getattr_all(controllers, "dw")
                nbanks = _getattr_all(controllers, "nbanks")
+               req_queue_size = _getattr_all(controllers, "req_queue_size")
                read_latency = _getattr_all(controllers, "read_latency")
                write_latency = _getattr_all(controllers, "write_latency")
 
                bank_bits = log2_int(nbanks, False)
                controller_bits = log2_int(ncontrollers, False)
-               self.masters = [Interface(rca_bits + bank_bits + controller_bits, dw, 1, read_latency, write_latency)
+               self.masters = [Interface(rca_bits + bank_bits + controller_bits, dw, 1, req_queue_size, read_latency, write_latency)
                        for i in range(nmasters)]
 
                ###
@@ -60,16 +64,20 @@ class Crossbar(Module):
                                controller_selected = [ca == nc for ca in m_ca]
                        else:
                                controller_selected = [1]*nmasters
-                       master_acks = [0]*nmasters
+                       master_req_acks = [0]*nmasters
+                       master_dat_acks = [0]*nmasters
                        for nb in range(nbanks):
                                bank = getattr(controller, "bank"+str(nb))
 
                                # arbitrate
-                               rr = roundrobin.RoundRobin(nmasters, roundrobin.SP_WITHDRAW)
+                               rr = roundrobin.RoundRobin(nmasters, roundrobin.SP_CE)
                                self.submodules += rr
                                bank_selected = [cs & (ba == nb) for cs, ba in zip(controller_selected, m_ba)]
                                bank_requested = [bs & master.stb for bs, master in zip(bank_selected, self.masters)]
-                               self.comb += rr.request.eq(Cat(*bank_requested)),
+                               self.comb += [
+                                       rr.request.eq(Cat(*bank_requested)),
+                                       rr.ce.eq(~bank.stb & ~bank.lock)
+                               ]
 
                                # route requests
                                self.comb += [
@@ -77,10 +85,13 @@ class Crossbar(Module):
                                        bank.we.eq(Array(self.masters)[rr.grant].we),
                                        bank.stb.eq(Array(bank_requested)[rr.grant])
                                ]
-                               master_acks = [master_ack | ((rr.grant == nm) & bank.ack)
-                                       for nm, master_ack in enumerate(master_acks)]
+                               master_req_acks = [master_req_ack | ((rr.grant == nm) & Array(bank_selected)[rr.grant] & bank.req_ack)
+                                       for nm, master_req_ack in enumerate(master_req_acks)]
+                               master_dat_acks = [master_dat_ack | ((rr.grant == nm) & bank.dat_ack)
+                                       for nm, master_dat_ack in enumerate(master_dat_acks)]
 
-                       self.comb += [master.ack.eq(master_ack) for master, master_ack in zip(self.masters, master_acks)]
+                       self.comb += [master.req_ack.eq(master_req_ack) for master, master_req_ack in zip(self.masters, master_req_acks)]
+                       self.comb += [master.dat_ack.eq(master_dat_ack) for master, master_dat_ack in zip(self.masters, master_dat_acks)]
 
                        # route data writes
                        controller_selected_wl = controller_selected
index 2aa48ff160a4f9278f793180518cc5e8abd53e52..c9a538661a8c791137b4433fa6a75120dd0cd1d1 100644 (file)
@@ -72,8 +72,8 @@ class WB2LASMI(Module):
                # Control FSM
                assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
                fsm = FSM("IDLE", "TEST_HIT",
-                       "EVICT_REQUEST", "EVICT_DATA",
-                       "REFILL_WRTAG", "REFILL_REQUEST", "REFILL_DATA",
+                       "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)
@@ -103,7 +103,10 @@ class WB2LASMI(Module):
                fsm.act(fsm.EVICT_REQUEST,
                        lasmim.stb.eq(1),
                        lasmim.we.eq(1),
-                       If(lasmim.ack, fsm.next_state(fsm.EVICT_DATAD))
+                       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),
@@ -117,7 +120,10 @@ class WB2LASMI(Module):
                )
                fsm.act(fsm.REFILL_REQUEST,
                        lasmim.stb.eq(1),
-                       If(lasmim.ack, fsm.next_state(fsm.REFILL_DATAD))
+                       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),