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:
Florent Kermarrec 2020-08-05 08:56:35 +02:00
parent ee7a7f4693
commit 00629c45b0
4 changed files with 39 additions and 12 deletions

View File

@ -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(

View File

@ -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=\"\"")

View File

@ -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)

View File

@ -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))