diff --git a/litex/soc/integration/export.py b/litex/soc/integration/export.py
index 2a6c01484..4d9b70c0e 100644
--- a/litex/soc/integration/export.py
+++ b/litex/soc/integration/export.py
@@ -308,7 +308,7 @@ def get_csr_svd(soc, vendor="litex", name="soc", description=None):
svd.append(' 0x{:04x}'.format(csr_address))
svd.append(' 0x{:02x}'.format(csr.reset_value))
svd.append(' {}'.format(length))
- svd.append(' {}'.format(csr.access))
+ # svd.append(' {}'.format(csr.access)) # 'access' is a lie: "read-only" registers can legitimately change state based on a write, and is in fact used to handle the "pending" field in events
csr_address = csr_address + 4
svd.append(' ')
if hasattr(csr, "fields") and len(csr.fields) > 0:
diff --git a/litex/soc/interconnect/csr_eventmanager.py b/litex/soc/interconnect/csr_eventmanager.py
index 43c57c2f5..5e4edf9a8 100644
--- a/litex/soc/interconnect/csr_eventmanager.py
+++ b/litex/soc/interconnect/csr_eventmanager.py
@@ -135,8 +135,9 @@ class EventManager(Module, AutoCSR):
asserted.
"""
- def __init__(self):
+ def __init__(self, document_fields=False):
self.irq = Signal()
+ self.document_fields = document_fields
def do_finalize(self):
def source_description(src):
@@ -159,77 +160,91 @@ class EventManager(Module, AutoCSR):
sources = sorted(sources_u, key=lambda x: x.duid)
n = len(sources)
- # annotate status
- fields = []
- for i, source in enumerate(sources):
- if source.description == None:
- desc = "This register contains the current raw level of the {} event trigger. Writes to this register have no effect.".format(str(source.name))
- else:
- desc = source.description
+ if self.document_fields:
+ # annotate status
+ fields = []
+ for i, source in enumerate(sources):
+ if source.description == None:
+ desc = "This register contains the current raw level of the {} event trigger. Writes to this register have no effect.".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="Level of the `{}` event".format(source.name)))
- else:
- fields.append(CSRField(
- name="event{}".format(i),
- size=1,
- description="Level of the `event{}` event".format(i)))
- self.status = CSRStatus(n, description=desc, fields=fields)
+ if hasattr(source, "name") and source.name is not None:
+ fields.append(CSRField(
+ name=source.name,
+ size=1,
+ description="Level of the `{}` event".format(source.name)))
+ else:
+ fields.append(CSRField(
+ name="event{}".format(i),
+ size=1,
+ description="Level of the `event{}` event".format(i)))
+ self.status = CSRStatus(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
+ # 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)
+ 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)
+ # 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)),
- ]
+ 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)),
+ ]
- 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))
def __setattr__(self, name, value):