Merge pull request #701 from enjoy-digital/csr_eventmanager_cleanup

interconnect/csr/EventManager: simpifly/cleanup code that documents C…
This commit is contained in:
bunnie 2020-11-20 03:24:09 +08:00 committed by GitHub
commit 8e39060d26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 78 additions and 100 deletions

View File

@ -198,7 +198,7 @@ class S7I2S(Module, AutoCSR, AutoDoc):
] ]
# Interrupts # Interrupts
self.submodules.ev = EventManager(document_fields=document_interrupts) self.submodules.ev = EventManager()
if hasattr(pads, 'rx'): if hasattr(pads, 'rx'):
self.ev.rx_ready = EventSourcePulse(description="Indicates FIFO is ready to read") # Rising edge triggered self.ev.rx_ready = EventSourcePulse(description="Indicates FIFO is ready to read") # Rising edge triggered
self.ev.rx_error = EventSourcePulse(description="Indicates an Rx error has happened (over/underflow)") self.ev.rx_error = EventSourcePulse(description="Indicates an Rx error has happened (over/underflow)")

View File

@ -219,7 +219,7 @@ def get_csr_header(regions, constants, csr_base=None, with_access_functions=True
for csr in region.obj: for csr in region.obj:
nr = (csr.size + region.busword - 1)//region.busword nr = (csr.size + region.busword - 1)//region.busword
r += _get_rw_functions_c(name + "_" + csr.name, origin, nr, region.busword, alignment, r += _get_rw_functions_c(name + "_" + csr.name, origin, nr, region.busword, alignment,
isinstance(csr, CSRStatus), with_access_functions) getattr(csr, "read_only", False), with_access_functions)
origin += alignment//8*nr origin += alignment//8*nr
if hasattr(csr, "fields"): if hasattr(csr, "fields"):
for field in csr.fields.fields: for field in csr.fields.fields:

View File

@ -286,16 +286,19 @@ class CSRStatus(_CompoundCSR):
The value of the CSRStatus register. The value of the CSRStatus register.
""" """
def __init__(self, size=1, reset=0, fields=[], name=None, description=None): def __init__(self, size=1, reset=0, fields=[], name=None, description=None, read_only=True):
if fields != []: if fields != []:
self.fields = CSRFieldAggregate(fields, CSRAccess.ReadOnly) self.fields = CSRFieldAggregate(fields, CSRAccess.ReadOnly)
size = self.fields.get_size() size = self.fields.get_size()
reset = self.fields.get_reset() reset = self.fields.get_reset()
_CompoundCSR.__init__(self, size, name) _CompoundCSR.__init__(self, size, name)
self.description = description self.description = description
self.read_only = read_only
self.status = Signal(self.size, reset=reset) self.status = Signal(self.size, reset=reset)
self.we = Signal() self.we = Signal()
self.re = Signal() self.re = Signal()
if not read_only:
self.r = Signal(self.size)
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))
@ -306,8 +309,12 @@ class CSRStatus(_CompoundCSR):
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])
self.simple_csrs.append(sc) self.simple_csrs.append(sc)
if not self.read_only:
lo = i*busword
hi = lo+nbits
self.sync += If(sc.re, self.r[lo:hi].eq(sc.r))
self.comb += self.we.eq(sc.we) self.comb += self.we.eq(sc.we)
self.comb += self.re.eq(sc.re) self.sync += self.re.eq(sc.re)
def read(self): def read(self):
"""Read method for simulation.""" """Read method for simulation."""

View File

@ -135,116 +135,87 @@ class EventManager(Module, AutoCSR):
asserted. asserted.
""" """
def __init__(self, document_fields=False): def __init__(self):
self.irq = Signal() self.irq = Signal()
self.document_fields = document_fields
def do_finalize(self): def do_finalize(self):
def source_description(src): sources_u = [v for k, v in xdir(self, True) if isinstance(v, _EventSource)]
if hasattr(src, "name") and src.name is not None: sources = sorted(sources_u, key=lambda x: x.duid)
base_text = "`1` if a `{}` event occurred. ".format(src.name) n = len(sources)
# Common
def get_source_name(src, i):
r = getattr(src, "name", None)
if r is None:
r = f"event{i}"
return r
def get_pending_source_description(src):
r = ""
if getattr(src, "name", None) is not None:
r += "`1` if a `{}` event occurred. ".format(src.name)
else: else:
base_text = "`1` if a this particular event occurred. " r += "`1` if a this particular event occurred. "
if hasattr(src, "description") and src.description is not None: if getattr(src, "description", None) is not None:
return src.description return src.description
elif isinstance(src, EventSourceLevel): elif isinstance(src, EventSourceLevel):
return base_text + "This Event is **level triggered** when the signal is **high**." return r + "This Event is **level triggered** when the signal is **high**."
elif isinstance(src, EventSourcePulse): elif isinstance(src, EventSourcePulse):
return base_text + "This Event is triggered on a **rising** edge." return r + "This Event is triggered on a **rising** edge."
elif isinstance(src, EventSourceProcess): elif isinstance(src, EventSourceProcess):
return base_text + "This Event is triggered on a **falling** edge." return r + "This Event is triggered on a **falling** edge."
else: else:
return base_text + "This Event uses an unknown method of triggering." return r + "This Event uses an unknown method of triggering."
sources_u = [v for k, v in xdir(self, True) if isinstance(v, _EventSource)] # Status register
sources = sorted(sources_u, key=lambda x: x.duid) fields = []
n = len(sources) for i, source in enumerate(sources):
# Get source name and use default if None.
name = get_source_name(source, i)
# Get description and use default description if None.
desc = getattr(source, "description", None)
if desc is None:
desc = "This register contains the current raw level of the {} event trigger. Writes to this register have no effect.".format(str(name))
# Add CSRField
fields.append(CSRField(name=name, size=1, description=f"Level of the ``{name}`` event"))
self.status = CSRStatus(n, description=desc, fields=fields)
if self.document_fields: # Pending Register
# annotate status fields = []
fields = [] for i, source in enumerate(sources):
for i, source in enumerate(sources): # Get source name and use default if None.
if source.description == None: name = get_source_name(source, i)
desc = "This register contains the current raw level of the {} event trigger. Writes to this register have no effect.".format(str(source.name)) # Get description and use default description if None.
else: desc = getattr(source, "description", None)
desc = source.description if desc is None:
desc = "When a {} event occurs, the corresponding bit will be set in this register. To clear the Event, set the corresponding bit in this register.".format(str(name))
# Add CSRField
fields.append(CSRField(name=name, size=1, description=get_pending_source_description(source)))
self.pending = CSRStatus(n, description=desc, fields=fields, read_only=False)
if hasattr(source, "name") and source.name is not None: # Enable Register
fields.append(CSRField( fields = []
name=source.name, for i, source in enumerate(sources):
size=1, # Get source name and use default if None.
description="Level of the ``{}`` event".format(source.name))) name = get_source_name(source, i)
else: # Get description and use default description if None.
fields.append(CSRField( desc = getattr(source, "description", None)
name="event{}".format(i), if desc is None:
size=1, desc = "This register enables the corresponding {} events. Write a ``0`` to this register to disable individual events.".format(str(name))
description="Level of the ``event{}`` event".format(i))) # Add CSRField
self.status = CSRStatus(n, description=desc, fields=fields) fields.append(CSRField(name=name, offset=i, description=f"Write a ``1`` to enable the ``{name}`` Event"))
self.enable = CSRStorage(n, description=desc, fields=fields)
# annotate pending
fields = []
for i, source in enumerate(sources):
if source.description is None:
desc = "When a {} event occurs, the corresponding bit will be set in this register. To clear the Event, set the corresponding bit in this register.".format(str(source.name))
else:
desc = source.description
if hasattr(source, "name") and source.name is not None:
fields.append(CSRField(
name=source.name,
size=1,
description=source_description(source)))
else:
fields.append(CSRField(
name="event{}".format(i),
size=1,
description=source_description(source)))
self.pending = CSRStatus(n, description=desc, fields=fields)
# annotate enable
fields = []
for i, source in enumerate(sources):
if source.description is None:
desc = "This register enables the corresponding {} events. Write a ``0`` to this register to disable individual events.".format(str(source.name))
else:
desc = source.description
if hasattr(source, "name") and source.name is not None:
fields.append(CSRField(
name=source.name,
offset=i,
description="Write a ``1`` to enable the ``{}`` Event".format(source.name)))
else:
fields.append(CSRField(
name="event{}".format(i),
offset=i,
description="Write a ``1`` to enable the ``{}`` Event".format(i)))
self.enable = CSRStorage(n, description=desc, fields=fields)
for i, source in enumerate(sources):
if source.name == None:
src_name = "event{}".format(i)
else:
src_name = source.name
self.comb += [
getattr(self.status.fields, src_name).eq(source.status),
getattr(self.pending.fields, src_name).eq(source.pending),
If(self.pending.re & getattr(self.pending.fields, src_name), source.clear.eq(1)),
]
# Connect Events/Fields
for i, source in enumerate(sources):
# Get source name and use default if None.
name = get_source_name(source, i)
self.comb += [
getattr(self.status.fields, name).eq(source.status),
getattr(self.pending.fields, name).eq(source.pending),
If(self.pending.re & self.pending.r[i], source.clear.eq(1)),
]
irqs = [self.pending.status[i] & self.enable.storage[i] for i in range(n)] irqs = [self.pending.status[i] & self.enable.storage[i] for i in range(n)]
else:
self.status = CSR(n)
self.pending = CSR(n)
self.enable = CSRStorage(n)
for i, source in enumerate(sources):
self.comb += [
self.status.w[i].eq(source.status),
If(self.pending.re & self.pending.r[i], source.clear.eq(1)),
self.pending.w[i].eq(source.pending)
]
irqs = [self.pending.w[i] & self.enable.storage[i] for i in range(n)]
self.comb += self.irq.eq(reduce(or_, irqs)) self.comb += self.irq.eq(reduce(or_, irqs))
def __setattr__(self, name, value): def __setattr__(self, name, value):