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.
This commit is contained in:
parent
ee7a7f4693
commit
00629c45b0
|
@ -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(
|
||||
|
|
|
@ -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=\"\"")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue