From: Florent Kermarrec Date: Wed, 5 Aug 2020 06:56:35 +0000 (+0200) Subject: interconnect/csr: add CSR registers ordering support. X-Git-Tag: 24jan2021_ls180~23 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=00629c45b0ecb44149893439d040d4b4267ba4ea;p=litex.git interconnect/csr: add CSR registers ordering support. The original CSR registers ordering (big: MSB on lower addresses) is not convenient when the SoC is interfaced with a real OS (for example as a PCIe add-on board or with a CPU running Linux). With this, the original ordering is kept as default (big), but it can now be switched to little to avoid software workarounds in drivers and should probably be in the future the default for PCIe/Linux SoCs. --- diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index feff41c7..480b67e3 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -479,9 +479,10 @@ class SoCCSRHandler(SoCLocHandler): supported_address_width = [14+i for i in range(4)] supported_alignment = [32] supported_paging = [0x800*2**i for i in range(4)] + supported_ordering = ["big", "little"] # Creation ------------------------------------------------------------------------------------- - def __init__(self, data_width=32, address_width=14, alignment=32, paging=0x800, reserved_csrs={}): + def __init__(self, data_width=32, address_width=14, alignment=32, paging=0x800, ordering="big", reserved_csrs={}): SoCLocHandler.__init__(self, "CSR", n_locs=alignment//8*(2**address_width)//paging) self.logger = logging.getLogger("SoCCSRHandler") self.logger.info("Creating CSR Handler...") @@ -524,18 +525,28 @@ class SoCCSRHandler(SoCLocHandler): colorer(", ".join("0x{:x}".format(x) for x in self.supported_paging)))) raise + # Check Ordering + if ordering not in self.supported_ordering: + self.logger.error("Unsupported {} {}, supporteds: {:s}".format( + colorer("Ordering", color="red"), + colorer("{}".format(paging)), + colorer(", ".join("{}".format(x) for x in self.supported_ordering)))) + raise + # Create CSR Handler self.data_width = data_width self.address_width = address_width self.alignment = alignment self.paging = paging + self.ordering = ordering self.masters = {} self.regions = {} - self.logger.info("{}-bit CSR Bus, {}-bit Aligned, {}KiB Address Space, {}B Paging (Up to {} Locations).".format( + self.logger.info("{}-bit CSR Bus, {}-bit Aligned, {}KiB Address Space, {}B Paging, {} Ordering (Up to {} Locations).".format( colorer(self.data_width), colorer(self.alignment), colorer(2**self.address_width/2**10), colorer(self.paging), + colorer(self.ordering), colorer(self.n_locs))) # Adding reserved CSRs @@ -586,11 +597,12 @@ class SoCCSRHandler(SoCLocHandler): # Str ------------------------------------------------------------------------------------------ def __str__(self): - r = "{}-bit CSR Bus, {}-bit Aligned, {}KiB Address Space, {}B Paging (Up to {} Locations).\n".format( + r = "{}-bit CSR Bus, {}-bit Aligned, {}KiB Address Space, {}B Paging, {} Ordering (Up to {} Locations).\n".format( colorer(self.data_width), colorer(self.alignment), colorer(2**self.address_width/2**10), colorer(self.paging), + colorer(self.ordering), colorer(self.n_locs)) r += SoCLocHandler.__str__(self) r = r[:-1] @@ -678,6 +690,7 @@ class SoC(Module): csr_data_width = 32, csr_address_width = 14, csr_paging = 0x800, + csr_ordering = "big", csr_reserved_csrs = {}, irq_n_irqs = 32, @@ -718,6 +731,7 @@ class SoC(Module): address_width = csr_address_width, alignment = 32, paging = csr_paging, + ordering = csr_ordering, reserved_csrs = csr_reserved_csrs, ) @@ -947,6 +961,7 @@ class SoC(Module): address_width = self.csr.address_width, alignment = self.csr.alignment, paging = self.csr.paging, + ordering = self.csr.ordering, soc_bus_data_width = self.bus.data_width) if len(self.csr.masters): self.submodules.csr_interconnect = csr_bus.InterconnectShared( diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 6fff7704..281f34e4 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -84,6 +84,7 @@ class SoCCore(LiteXSoC): csr_data_width = 8, csr_address_width = 14, csr_paging = 0x800, + csr_ordering = "big", # Identifier parameters ident = "", ident_version = False, @@ -111,6 +112,7 @@ class SoCCore(LiteXSoC): csr_data_width = csr_data_width, csr_address_width = csr_address_width, csr_paging = csr_paging, + csr_ordering = csr_ordering, csr_reserved_csrs = self.csr_map, irq_n_irqs = 32, @@ -289,6 +291,9 @@ def soc_core_args(parser): help="CSR bus address-width") parser.add_argument("--csr-paging", default=0x800, type=auto_int, help="CSR bus paging") + parser.add_argument("--csr-ordering", default="big", + help="CSR registers ordering (default=big)") + # Identifier parameters parser.add_argument("--ident", default=None, type=str, help="SoC identifier (default=\"\"") diff --git a/litex/soc/interconnect/csr.py b/litex/soc/interconnect/csr.py index 9922117f..fbc66d84 100644 --- a/litex/soc/interconnect/csr.py +++ b/litex/soc/interconnect/csr.py @@ -295,9 +295,9 @@ class CSRStatus(_CompoundCSR): for field in fields: self.comb += self.status[field.offset:field.offset + field.size].eq(getattr(self.fields, field.name)) - def do_finalize(self, busword): + def do_finalize(self, busword, ordering): nwords = (self.size + busword - 1)//busword - for i in reversed(range(nwords)): + for i in reversed(range(nwords)) if ordering == "big" else range(nwords): nbits = min(self.size - i*busword, busword) sc = CSR(nbits, self.name + str(i) if nwords > 1 else self.name) self.comb += sc.w.eq(self.status[i*busword:i*busword+nbits]) @@ -384,11 +384,11 @@ class CSRStorage(_CompoundCSR): else: self.comb += field_assign - def do_finalize(self, busword): + def do_finalize(self, busword, ordering): nwords = (self.size + busword - 1)//busword if nwords > 1 and self.atomic_write: backstore = Signal(self.size - busword, name=self.name + "_backstore") - for i in reversed(range(nwords)): + for i in reversed(range(nwords)) if ordering == "big" else range(nwords): nbits = min(self.size - i*busword, busword) sc = CSR(nbits, self.name + str(i) if nwords else self.name) self.simple_csrs.append(sc) @@ -479,7 +479,8 @@ class AutoCSR: class GenericBank(Module): - def __init__(self, description, busword): + def __init__(self, description, busword, ordering="big"): + assert ordering in ["big", "little"] # Turn description into simple CSRs and claim ownership of compound CSR modules self.simple_csrs = [] for c in description: @@ -487,7 +488,7 @@ class GenericBank(Module): assert c.size <= busword self.simple_csrs.append(c) else: - c.finalize(busword) + c.finalize(busword, ordering) self.simple_csrs += c.get_simple_csrs() self.submodules += c self.decode_bits = bits_for(len(self.simple_csrs)-1) diff --git a/litex/soc/interconnect/csr_bus.py b/litex/soc/interconnect/csr_bus.py index cded5ae2..c09bfe5d 100644 --- a/litex/soc/interconnect/csr_bus.py +++ b/litex/soc/interconnect/csr_bus.py @@ -163,7 +163,7 @@ class SRAM(Module): # CSR Bank ----------------------------------------------------------------------------------------- class CSRBank(csr.GenericBank): - def __init__(self, description, address=0, bus=None, paging=0x800, soc_bus_data_width=32): + def __init__(self, description, address=0, bus=None, paging=0x800, ordering="big", soc_bus_data_width=32): if bus is None: bus = Interface() self.bus = bus @@ -171,7 +171,11 @@ class CSRBank(csr.GenericBank): # # # - csr.GenericBank.__init__(self, description, len(self.bus.dat_w)) + csr.GenericBank.__init__(self, + description = description, + busword = len(self.bus.dat_w), + ordering = ordering, + ) sel = Signal() self.comb += sel.eq(self.bus.adr[log2_int(aligned_paging):] == address) @@ -201,10 +205,11 @@ class CSRBank(csr.GenericBank): # address_map is called exactly once for each object at each call to # scan(), so it can have side effects. class CSRBankArray(Module): - def __init__(self, source, address_map, *ifargs, paging=0x800, soc_bus_data_width=32, **ifkwargs): + def __init__(self, source, address_map, *ifargs, paging=0x800, ordering="big", soc_bus_data_width=32, **ifkwargs): self.source = source self.address_map = address_map self.paging = paging + self.ordering = ordering self.soc_bus_data_width = soc_bus_data_width self.scan(ifargs, ifkwargs) @@ -246,6 +251,7 @@ class CSRBankArray(Module): rmap = CSRBank(csrs, mapaddr, bus = bank_bus, paging = self.paging, + ordering = self.ordering, soc_bus_data_width = self.soc_bus_data_width) self.submodules += rmap self.banks.append((name, csrs, mapaddr, rmap))