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_address_width = [14+i for i in range(4)]
|
||||||
supported_alignment = [32]
|
supported_alignment = [32]
|
||||||
supported_paging = [0x800*2**i for i in range(4)]
|
supported_paging = [0x800*2**i for i in range(4)]
|
||||||
|
supported_ordering = ["big", "little"]
|
||||||
|
|
||||||
# Creation -------------------------------------------------------------------------------------
|
# 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)
|
SoCLocHandler.__init__(self, "CSR", n_locs=alignment//8*(2**address_width)//paging)
|
||||||
self.logger = logging.getLogger("SoCCSRHandler")
|
self.logger = logging.getLogger("SoCCSRHandler")
|
||||||
self.logger.info("Creating CSR Handler...")
|
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))))
|
colorer(", ".join("0x{:x}".format(x) for x in self.supported_paging))))
|
||||||
raise
|
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
|
# Create CSR Handler
|
||||||
self.data_width = data_width
|
self.data_width = data_width
|
||||||
self.address_width = address_width
|
self.address_width = address_width
|
||||||
self.alignment = alignment
|
self.alignment = alignment
|
||||||
self.paging = paging
|
self.paging = paging
|
||||||
|
self.ordering = ordering
|
||||||
self.masters = {}
|
self.masters = {}
|
||||||
self.regions = {}
|
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.data_width),
|
||||||
colorer(self.alignment),
|
colorer(self.alignment),
|
||||||
colorer(2**self.address_width/2**10),
|
colorer(2**self.address_width/2**10),
|
||||||
colorer(self.paging),
|
colorer(self.paging),
|
||||||
|
colorer(self.ordering),
|
||||||
colorer(self.n_locs)))
|
colorer(self.n_locs)))
|
||||||
|
|
||||||
# Adding reserved CSRs
|
# Adding reserved CSRs
|
||||||
|
@ -586,11 +597,12 @@ class SoCCSRHandler(SoCLocHandler):
|
||||||
|
|
||||||
# Str ------------------------------------------------------------------------------------------
|
# Str ------------------------------------------------------------------------------------------
|
||||||
def __str__(self):
|
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.data_width),
|
||||||
colorer(self.alignment),
|
colorer(self.alignment),
|
||||||
colorer(2**self.address_width/2**10),
|
colorer(2**self.address_width/2**10),
|
||||||
colorer(self.paging),
|
colorer(self.paging),
|
||||||
|
colorer(self.ordering),
|
||||||
colorer(self.n_locs))
|
colorer(self.n_locs))
|
||||||
r += SoCLocHandler.__str__(self)
|
r += SoCLocHandler.__str__(self)
|
||||||
r = r[:-1]
|
r = r[:-1]
|
||||||
|
@ -678,6 +690,7 @@ class SoC(Module):
|
||||||
csr_data_width = 32,
|
csr_data_width = 32,
|
||||||
csr_address_width = 14,
|
csr_address_width = 14,
|
||||||
csr_paging = 0x800,
|
csr_paging = 0x800,
|
||||||
|
csr_ordering = "big",
|
||||||
csr_reserved_csrs = {},
|
csr_reserved_csrs = {},
|
||||||
|
|
||||||
irq_n_irqs = 32,
|
irq_n_irqs = 32,
|
||||||
|
@ -718,6 +731,7 @@ class SoC(Module):
|
||||||
address_width = csr_address_width,
|
address_width = csr_address_width,
|
||||||
alignment = 32,
|
alignment = 32,
|
||||||
paging = csr_paging,
|
paging = csr_paging,
|
||||||
|
ordering = csr_ordering,
|
||||||
reserved_csrs = csr_reserved_csrs,
|
reserved_csrs = csr_reserved_csrs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -947,6 +961,7 @@ class SoC(Module):
|
||||||
address_width = self.csr.address_width,
|
address_width = self.csr.address_width,
|
||||||
alignment = self.csr.alignment,
|
alignment = self.csr.alignment,
|
||||||
paging = self.csr.paging,
|
paging = self.csr.paging,
|
||||||
|
ordering = self.csr.ordering,
|
||||||
soc_bus_data_width = self.bus.data_width)
|
soc_bus_data_width = self.bus.data_width)
|
||||||
if len(self.csr.masters):
|
if len(self.csr.masters):
|
||||||
self.submodules.csr_interconnect = csr_bus.InterconnectShared(
|
self.submodules.csr_interconnect = csr_bus.InterconnectShared(
|
||||||
|
|
|
@ -84,6 +84,7 @@ class SoCCore(LiteXSoC):
|
||||||
csr_data_width = 8,
|
csr_data_width = 8,
|
||||||
csr_address_width = 14,
|
csr_address_width = 14,
|
||||||
csr_paging = 0x800,
|
csr_paging = 0x800,
|
||||||
|
csr_ordering = "big",
|
||||||
# Identifier parameters
|
# Identifier parameters
|
||||||
ident = "",
|
ident = "",
|
||||||
ident_version = False,
|
ident_version = False,
|
||||||
|
@ -111,6 +112,7 @@ class SoCCore(LiteXSoC):
|
||||||
csr_data_width = csr_data_width,
|
csr_data_width = csr_data_width,
|
||||||
csr_address_width = csr_address_width,
|
csr_address_width = csr_address_width,
|
||||||
csr_paging = csr_paging,
|
csr_paging = csr_paging,
|
||||||
|
csr_ordering = csr_ordering,
|
||||||
csr_reserved_csrs = self.csr_map,
|
csr_reserved_csrs = self.csr_map,
|
||||||
|
|
||||||
irq_n_irqs = 32,
|
irq_n_irqs = 32,
|
||||||
|
@ -289,6 +291,9 @@ def soc_core_args(parser):
|
||||||
help="CSR bus address-width")
|
help="CSR bus address-width")
|
||||||
parser.add_argument("--csr-paging", default=0x800, type=auto_int,
|
parser.add_argument("--csr-paging", default=0x800, type=auto_int,
|
||||||
help="CSR bus paging")
|
help="CSR bus paging")
|
||||||
|
parser.add_argument("--csr-ordering", default="big",
|
||||||
|
help="CSR registers ordering (default=big)")
|
||||||
|
|
||||||
# Identifier parameters
|
# Identifier parameters
|
||||||
parser.add_argument("--ident", default=None, type=str,
|
parser.add_argument("--ident", default=None, type=str,
|
||||||
help="SoC identifier (default=\"\"")
|
help="SoC identifier (default=\"\"")
|
||||||
|
|
|
@ -295,9 +295,9 @@ class CSRStatus(_CompoundCSR):
|
||||||
for field in fields:
|
for field in fields:
|
||||||
self.comb += self.status[field.offset:field.offset + field.size].eq(getattr(self.fields, field.name))
|
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
|
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)
|
nbits = min(self.size - i*busword, busword)
|
||||||
sc = CSR(nbits, self.name + str(i) if nwords > 1 else self.name)
|
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])
|
self.comb += sc.w.eq(self.status[i*busword:i*busword+nbits])
|
||||||
|
@ -384,11 +384,11 @@ class CSRStorage(_CompoundCSR):
|
||||||
else:
|
else:
|
||||||
self.comb += field_assign
|
self.comb += field_assign
|
||||||
|
|
||||||
def do_finalize(self, busword):
|
def do_finalize(self, busword, ordering):
|
||||||
nwords = (self.size + busword - 1)//busword
|
nwords = (self.size + busword - 1)//busword
|
||||||
if nwords > 1 and self.atomic_write:
|
if nwords > 1 and self.atomic_write:
|
||||||
backstore = Signal(self.size - busword, name=self.name + "_backstore")
|
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)
|
nbits = min(self.size - i*busword, busword)
|
||||||
sc = CSR(nbits, self.name + str(i) if nwords else self.name)
|
sc = CSR(nbits, self.name + str(i) if nwords else self.name)
|
||||||
self.simple_csrs.append(sc)
|
self.simple_csrs.append(sc)
|
||||||
|
@ -479,7 +479,8 @@ class AutoCSR:
|
||||||
|
|
||||||
|
|
||||||
class GenericBank(Module):
|
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
|
# Turn description into simple CSRs and claim ownership of compound CSR modules
|
||||||
self.simple_csrs = []
|
self.simple_csrs = []
|
||||||
for c in description:
|
for c in description:
|
||||||
|
@ -487,7 +488,7 @@ class GenericBank(Module):
|
||||||
assert c.size <= busword
|
assert c.size <= busword
|
||||||
self.simple_csrs.append(c)
|
self.simple_csrs.append(c)
|
||||||
else:
|
else:
|
||||||
c.finalize(busword)
|
c.finalize(busword, ordering)
|
||||||
self.simple_csrs += c.get_simple_csrs()
|
self.simple_csrs += c.get_simple_csrs()
|
||||||
self.submodules += c
|
self.submodules += c
|
||||||
self.decode_bits = bits_for(len(self.simple_csrs)-1)
|
self.decode_bits = bits_for(len(self.simple_csrs)-1)
|
||||||
|
|
|
@ -163,7 +163,7 @@ class SRAM(Module):
|
||||||
# CSR Bank -----------------------------------------------------------------------------------------
|
# CSR Bank -----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class CSRBank(csr.GenericBank):
|
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:
|
if bus is None:
|
||||||
bus = Interface()
|
bus = Interface()
|
||||||
self.bus = bus
|
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()
|
sel = Signal()
|
||||||
self.comb += sel.eq(self.bus.adr[log2_int(aligned_paging):] == address)
|
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
|
# address_map is called exactly once for each object at each call to
|
||||||
# scan(), so it can have side effects.
|
# scan(), so it can have side effects.
|
||||||
class CSRBankArray(Module):
|
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.source = source
|
||||||
self.address_map = address_map
|
self.address_map = address_map
|
||||||
self.paging = paging
|
self.paging = paging
|
||||||
|
self.ordering = ordering
|
||||||
self.soc_bus_data_width = soc_bus_data_width
|
self.soc_bus_data_width = soc_bus_data_width
|
||||||
self.scan(ifargs, ifkwargs)
|
self.scan(ifargs, ifkwargs)
|
||||||
|
|
||||||
|
@ -246,6 +251,7 @@ class CSRBankArray(Module):
|
||||||
rmap = CSRBank(csrs, mapaddr,
|
rmap = CSRBank(csrs, mapaddr,
|
||||||
bus = bank_bus,
|
bus = bank_bus,
|
||||||
paging = self.paging,
|
paging = self.paging,
|
||||||
|
ordering = self.ordering,
|
||||||
soc_bus_data_width = self.soc_bus_data_width)
|
soc_bus_data_width = self.soc_bus_data_width)
|
||||||
self.submodules += rmap
|
self.submodules += rmap
|
||||||
self.banks.append((name, csrs, mapaddr, rmap))
|
self.banks.append((name, csrs, mapaddr, rmap))
|
||||||
|
|
Loading…
Reference in New Issue