lasmi: simplify usage for the user (it's the job of the controller to manage write/read latencies on acks)
This commit is contained in:
parent
f58394f6af
commit
6d83a112e6
|
@ -18,7 +18,8 @@ class Interface(Record):
|
||||||
("we", 1, DIR_M_TO_S),
|
("we", 1, DIR_M_TO_S),
|
||||||
("stb", 1, DIR_M_TO_S),
|
("stb", 1, DIR_M_TO_S),
|
||||||
("req_ack", 1, DIR_S_TO_M),
|
("req_ack", 1, DIR_S_TO_M),
|
||||||
("dat_ack", 1, DIR_S_TO_M),
|
("dat_w_ack", 1, DIR_S_TO_M),
|
||||||
|
("dat_r_ack", 1, DIR_S_TO_M),
|
||||||
("lock", 1, DIR_S_TO_M)
|
("lock", 1, DIR_S_TO_M)
|
||||||
]
|
]
|
||||||
if nbanks > 1:
|
if nbanks > 1:
|
||||||
|
@ -77,7 +78,9 @@ class Crossbar(Module):
|
||||||
else:
|
else:
|
||||||
controller_selected = [1]*nmasters
|
controller_selected = [1]*nmasters
|
||||||
master_req_acks = [0]*nmasters
|
master_req_acks = [0]*nmasters
|
||||||
master_dat_acks = [0]*nmasters
|
master_dat_w_acks = [0]*nmasters
|
||||||
|
master_dat_r_acks = [0]*nmasters
|
||||||
|
|
||||||
rrs = [roundrobin.RoundRobin(nmasters, roundrobin.SP_CE) for n in range(self._nbanks)]
|
rrs = [roundrobin.RoundRobin(nmasters, roundrobin.SP_CE) for n in range(self._nbanks)]
|
||||||
self.submodules += rrs
|
self.submodules += rrs
|
||||||
for nb, rr in enumerate(rrs):
|
for nb, rr in enumerate(rrs):
|
||||||
|
@ -109,11 +112,28 @@ class Crossbar(Module):
|
||||||
]
|
]
|
||||||
master_req_acks = [master_req_ack | ((rr.grant == nm) & bank_selected[nm] & bank.req_ack)
|
master_req_acks = [master_req_ack | ((rr.grant == nm) & bank_selected[nm] & bank.req_ack)
|
||||||
for nm, master_req_ack in enumerate(master_req_acks)]
|
for nm, master_req_ack in enumerate(master_req_acks)]
|
||||||
master_dat_acks = [master_dat_ack | ((rr.grant == nm) & bank.dat_ack)
|
master_dat_w_acks = [master_dat_w_ack | ((rr.grant == nm) & bank.dat_w_ack)
|
||||||
for nm, master_dat_ack in enumerate(master_dat_acks)]
|
for nm, master_dat_w_ack in enumerate(master_dat_w_acks)]
|
||||||
|
master_dat_r_acks = [master_dat_r_ack | ((rr.grant == nm) & bank.dat_r_ack)
|
||||||
|
for nm, master_dat_r_ack in enumerate(master_dat_r_acks)]
|
||||||
|
|
||||||
|
for nm, master_dat_w_ack in enumerate(master_dat_w_acks):
|
||||||
|
for i in range(self._write_latency):
|
||||||
|
new_master_dat_w_ack = Signal()
|
||||||
|
self.sync += new_master_dat_w_ack.eq(master_dat_w_ack)
|
||||||
|
master_dat_w_ack = new_master_dat_w_ack
|
||||||
|
master_dat_w_acks[nm] = master_dat_w_ack
|
||||||
|
|
||||||
|
for nm, master_dat_r_ack in enumerate(master_dat_r_acks):
|
||||||
|
for i in range(self._read_latency):
|
||||||
|
new_master_dat_r_ack = Signal()
|
||||||
|
self.sync += new_master_dat_r_ack.eq(master_dat_r_ack)
|
||||||
|
master_dat_r_ack = new_master_dat_r_ack
|
||||||
|
master_dat_r_acks[nm] = master_dat_r_ack
|
||||||
|
|
||||||
self.comb += [master.req_ack.eq(master_req_ack) for master, master_req_ack in zip(self._masters, master_req_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)]
|
self.comb += [master.dat_w_ack.eq(master_dat_w_ack) for master, master_dat_w_ack in zip(self._masters, master_dat_w_acks)]
|
||||||
|
self.comb += [master.dat_r_ack.eq(master_dat_r_ack) for master, master_dat_r_ack in zip(self._masters, master_dat_r_acks)]
|
||||||
|
|
||||||
# route data writes
|
# route data writes
|
||||||
controller_selected_wl = controller_selected
|
controller_selected_wl = controller_selected
|
||||||
|
|
|
@ -105,8 +105,6 @@ class WB2LASMI(Module, AutoCSR):
|
||||||
fsm = FSM(reset_state="IDLE")
|
fsm = FSM(reset_state="IDLE")
|
||||||
self.submodules += 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",
|
fsm.act("IDLE",
|
||||||
If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT"))
|
If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT"))
|
||||||
|
@ -135,7 +133,7 @@ class WB2LASMI(Module, AutoCSR):
|
||||||
If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK"))
|
If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK"))
|
||||||
)
|
)
|
||||||
fsm.act("EVICT_WAIT_DATA_ACK",
|
fsm.act("EVICT_WAIT_DATA_ACK",
|
||||||
If(lasmim.dat_ack, NextState("EVICT_DATAD"))
|
If(lasmim.dat_w_ack, NextState("EVICT_DATA"))
|
||||||
)
|
)
|
||||||
fsm.act("EVICT_DATA",
|
fsm.act("EVICT_DATA",
|
||||||
write_to_lasmi.eq(1),
|
write_to_lasmi.eq(1),
|
||||||
|
@ -155,12 +153,10 @@ class WB2LASMI(Module, AutoCSR):
|
||||||
)
|
)
|
||||||
fsm.act("REFILL_REQUEST",
|
fsm.act("REFILL_REQUEST",
|
||||||
lasmim.stb.eq(1),
|
lasmim.stb.eq(1),
|
||||||
If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK"))
|
If(lasmim.req_ack, NextState("REFILL_DATA"))
|
||||||
)
|
|
||||||
fsm.act("REFILL_WAIT_DATA_ACK",
|
|
||||||
If(lasmim.dat_ack, NextState("REFILL_DATAD"))
|
|
||||||
)
|
)
|
||||||
fsm.act("REFILL_DATA",
|
fsm.act("REFILL_DATA",
|
||||||
|
If(lasmim.dat_r_ack,
|
||||||
write_from_lasmi.eq(1),
|
write_from_lasmi.eq(1),
|
||||||
word_inc.eq(1),
|
word_inc.eq(1),
|
||||||
If(word_is_last(word),
|
If(word_is_last(word),
|
||||||
|
@ -169,3 +165,4 @@ class WB2LASMI(Module, AutoCSR):
|
||||||
NextState("REFILL_REQUEST")
|
NextState("REFILL_REQUEST")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -41,7 +41,7 @@ class BankMachine(Module):
|
||||||
self.req_fifo.we.eq(req.stb),
|
self.req_fifo.we.eq(req.stb),
|
||||||
req.req_ack.eq(self.req_fifo.writable),
|
req.req_ack.eq(self.req_fifo.writable),
|
||||||
|
|
||||||
self.req_fifo.re.eq(req.dat_ack),
|
self.req_fifo.re.eq(req.dat_w_ack | req.dat_r_ack),
|
||||||
req.lock.eq(self.req_fifo.readable)
|
req.lock.eq(self.req_fifo.readable)
|
||||||
]
|
]
|
||||||
reqf = self.req_fifo.dout
|
reqf = self.req_fifo.dout
|
||||||
|
@ -100,7 +100,8 @@ class BankMachine(Module):
|
||||||
If(hit,
|
If(hit,
|
||||||
# NB: write-to-read specification is enforced by multiplexer
|
# NB: write-to-read specification is enforced by multiplexer
|
||||||
self.cmd.stb.eq(1),
|
self.cmd.stb.eq(1),
|
||||||
req.dat_ack.eq(self.cmd.ack),
|
req.dat_w_ack.eq(self.cmd.ack & reqf.we),
|
||||||
|
req.dat_r_ack.eq(self.cmd.ack & ~reqf.we),
|
||||||
self.cmd.is_read.eq(~reqf.we),
|
self.cmd.is_read.eq(~reqf.we),
|
||||||
self.cmd.is_write.eq(reqf.we),
|
self.cmd.is_write.eq(reqf.we),
|
||||||
self.cmd.cas_n.eq(0),
|
self.cmd.cas_n.eq(0),
|
||||||
|
|
Loading…
Reference in New Issue