From ed4be0b2a0723784a27b2a80cd15627f4b181e95 Mon Sep 17 00:00:00 2001 From: Date: Fri, 10 Aug 2018 00:20:13 -0400 Subject: [PATCH 1/4] Add write bank to out of order interface --- litedram/common.py | 13 +++++++++---- litedram/frontend/crossbar.py | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/litedram/common.py b/litedram/common.py index e5b600e..67a3284 100644 --- a/litedram/common.py +++ b/litedram/common.py @@ -60,6 +60,7 @@ def data_layout(dw, bankbits): return [ ("wdata", dw, DIR_M_TO_S), ("wdata_we", dw//8, DIR_M_TO_S), + ("wbank", bankbits, DIR_S_TO_M), ("rdata", dw, DIR_S_TO_M), ("rbank", bankbits, DIR_S_TO_M) ] @@ -82,14 +83,18 @@ def cmd_description(aw): ("adr", aw) ] -def wdata_description(dw): +def wdata_description(dw, nbanks): return [ ("data", dw), - ("we", dw//8) + ("we", dw//8), + ("bank", nbanks) ] def rdata_description(dw, nbanks): - return [("data", dw), ("bank", nbanks)] + return [ + ("data", dw), + ("bank", nbanks) + ] class LiteDRAMPort: @@ -103,7 +108,7 @@ class LiteDRAMPort: self.lock = Signal() self.cmd = stream.Endpoint(cmd_description(aw)) - self.wdata = stream.Endpoint(wdata_description(dw)) + self.wdata = stream.Endpoint(wdata_description(dw, bankbits)) self.rdata = stream.Endpoint(rdata_description(dw, bankbits)) self.flush = Signal() diff --git a/litedram/frontend/crossbar.py b/litedram/frontend/crossbar.py index ed7fc27..56a263f 100644 --- a/litedram/frontend/crossbar.py +++ b/litedram/frontend/crossbar.py @@ -70,6 +70,7 @@ class LiteDRAMCrossbar(Module): self.submodules += arbiters rbank = Signal(max=self.nbanks) + wbank = Signal(max=self.nbanks) for nb, arbiter in enumerate(arbiters): bank = getattr(controller, "bank"+str(nb)) @@ -84,7 +85,7 @@ class LiteDRAMCrossbar(Module): master_locked.append(locked) # arbitrate - bank_selected = [(ba == nb) & ~locked for ba, locked in zip(m_ba, master_locked)] + bank_selected = [(ba == nb) for ba, locked in zip(m_ba, master_locked)] bank_requested = [bs & master.cmd.valid for bs, master in zip(bank_selected, self.masters)] self.comb += [ arbiter.request.eq(Cat(*bank_requested)), @@ -97,6 +98,12 @@ class LiteDRAMCrossbar(Module): rbank.eq(nb) ) + # Get wdata source bank + self.sync += \ + If((arbiter.grant == nm) & bank.wdata_ready, + wbank.eq(nb) + ) + # route requests self.comb += [ bank.adr.eq(Array(m_rca)[arbiter.grant]), @@ -129,6 +136,11 @@ class LiteDRAMCrossbar(Module): new_master_rbank = Signal(max=self.nbanks) self.sync += new_master_rbank.eq(rbank) rbank = new_master_rbank + # Delay wbank output to match wready + for i in range(self.write_latency-1): + new_master_wbank = Signal(max=self.nbanks) + self.sync += new_master_wbank.eq(wbank) + wbank = new_master_wbank for master, master_ready in zip(self.masters, master_readys): self.comb += master.cmd.ready.eq(master_ready) @@ -154,6 +166,7 @@ class LiteDRAMCrossbar(Module): for master in self.masters: self.comb += master.rdata.data.eq(self.controller.rdata) self.comb += master.rdata.bank.eq(rbank) + self.comb += master.wdata.bank.eq(wbank) def split_master_addresses(self, bank_bits, rca_bits, cba_shift): m_ba = [] # bank address From 8266a6e690eb40dea6fd626d379c4cda5c643c69 Mon Sep 17 00:00:00 2001 From: Date: Fri, 10 Aug 2018 00:21:22 -0400 Subject: [PATCH 2/4] Prevent compilation failures when tRRD == 0 --- litedram/core/multiplexer.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/litedram/core/multiplexer.py b/litedram/core/multiplexer.py index fccdd07..e19cde0 100644 --- a/litedram/core/multiplexer.py +++ b/litedram/core/multiplexer.py @@ -138,16 +138,17 @@ class Multiplexer(Module, AutoCSR): # tRRD Command Timing tRRD = settings.timing.tRRD trrd_allowed = Signal(reset=1) - activate_count = Signal(max=tRRD) is_act_cmd = Signal() self.comb += is_act_cmd.eq(choose_cmd.cmd.ras & ~choose_cmd.cmd.cas & ~choose_cmd.cmd.we) - self.sync += \ - If(choose_cmd.cmd.ready & choose_cmd.cmd.valid & is_act_cmd, - activate_count.eq(tRRD-1) - ).Elif(~activate_allowed, - activate_count.eq(activate_count-1) - ) - self.comb += trrd_allowed.eq(activate_count == 0) + if tRRD > 1: + activate_count = Signal(max=tRRD) + self.sync += \ + If(choose_cmd.cmd.ready & choose_cmd.cmd.valid & is_act_cmd, + activate_count.eq(tRRD-1) + ).Elif(~activate_allowed, + activate_count.eq(activate_count-1) + ) + self.comb += trrd_allowed.eq(activate_count == 0) # tFAW Command Timing tfaw = settings.timing.tFAW From 86b3e2d2ef5633a2dec57f7f9ddfbfa2f13eddde Mon Sep 17 00:00:00 2001 From: Date: Fri, 10 Aug 2018 15:54:22 -0400 Subject: [PATCH 3/4] Add reorder flag to the crossbar --- litedram/common.py | 8 +++++--- litedram/frontend/crossbar.py | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/litedram/common.py b/litedram/common.py index dba45e1..f284c1c 100644 --- a/litedram/common.py +++ b/litedram/common.py @@ -105,7 +105,7 @@ def rdata_description(dw, with_bank): class LiteDRAMPort: def __init__(self, mode, aw, dw, cd="sys", id=0, - with_data_bank=False): + reorder=False): self.mode = mode self.aw = aw self.dw = dw @@ -115,9 +115,11 @@ class LiteDRAMPort: self.lock = Signal() self.cmd = stream.Endpoint(cmd_description(aw)) - self.wdata = stream.Endpoint(wdata_description(dw, with_data_bank)) - self.rdata = stream.Endpoint(rdata_description(dw, with_data_bank)) + self.wdata = stream.Endpoint(wdata_description(dw, reorder)) + self.rdata = stream.Endpoint(rdata_description(dw, reorder)) + if reorder: + print("WARNING: Reordering controller is experimental") self.flush = Signal() diff --git a/litedram/frontend/crossbar.py b/litedram/frontend/crossbar.py index 1936cb5..b1d2df3 100644 --- a/litedram/frontend/crossbar.py +++ b/litedram/frontend/crossbar.py @@ -26,19 +26,19 @@ class LiteDRAMCrossbar(Module): self.masters = [] - def get_port(self, mode="both", dw=None, cd="sys", reverse=False): + def get_port(self, mode="both", dw=None, cd="sys", reverse=False, reorder=False): if self.finalized: raise FinalizeError if dw is None: dw = self.dw # crossbar port - port = LiteDRAMPort(mode, self.rca_bits + self.bank_bits, self.dw, "sys", len(self.masters)) + port = LiteDRAMPort(mode, self.rca_bits + self.bank_bits, self.dw, "sys", len(self.masters), reorder) self.masters.append(port) # clock domain crossing if cd != "sys": - new_port = LiteDRAMPort(mode, port.aw, port.dw, cd, port.id) + new_port = LiteDRAMPort(mode, port.aw, port.dw, cd, port.id, reorder) self.submodules += LiteDRAMPortCDC(new_port, port) port = new_port @@ -48,7 +48,7 @@ class LiteDRAMCrossbar(Module): adr_shift = -log2_int(dw//self.dw) else: adr_shift = log2_int(self.dw//dw) - new_port = LiteDRAMPort(mode, port.aw + adr_shift, dw, cd, port.id) + new_port = LiteDRAMPort(mode, port.aw + adr_shift, dw, cd, port.id, reorder) self.submodules += ClockDomainsRenamer(cd)(LiteDRAMPortConverter(new_port, port, reverse)) port = new_port From 03a2ad6bdcdba7da1f2c0045dcd6fc751a192081 Mon Sep 17 00:00:00 2001 From: Date: Fri, 10 Aug 2018 16:35:16 -0400 Subject: [PATCH 4/4] Ensure out of order is on a per-bank basis --- litedram/common.py | 2 ++ litedram/frontend/crossbar.py | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/litedram/common.py b/litedram/common.py index f284c1c..d82fe37 100644 --- a/litedram/common.py +++ b/litedram/common.py @@ -114,6 +114,8 @@ class LiteDRAMPort: self.lock = Signal() + self.reorder = reorder + self.cmd = stream.Endpoint(cmd_description(aw)) self.wdata = stream.Endpoint(wdata_description(dw, reorder)) self.rdata = stream.Endpoint(rdata_description(dw, reorder)) diff --git a/litedram/frontend/crossbar.py b/litedram/frontend/crossbar.py index b1d2df3..e1b0935 100644 --- a/litedram/frontend/crossbar.py +++ b/litedram/frontend/crossbar.py @@ -78,14 +78,15 @@ class LiteDRAMCrossbar(Module): master_locked = [] for nm, master in enumerate(self.masters): locked = 0 - for other_nb, other_arbiter in enumerate(arbiters): - if other_nb != nb: - other_bank = getattr(controller, "bank"+str(other_nb)) - locked = locked | (other_bank.lock & (other_arbiter.grant == nm)) + if not master.reorder: + for other_nb, other_arbiter in enumerate(arbiters): + if other_nb != nb: + other_bank = getattr(controller, "bank"+str(other_nb)) + locked = locked | (other_bank.lock & (other_arbiter.grant == nm)) master_locked.append(locked) # arbitrate - bank_selected = [(ba == nb) for ba, locked in zip(m_ba, master_locked)] + bank_selected = [(ba == nb) & ~locked for ba, locked in zip(m_ba, master_locked)] bank_requested = [bs & master.cmd.valid for bs, master in zip(bank_selected, self.masters)] self.comb += [ arbiter.request.eq(Cat(*bank_requested)),