csr: add we signal to CSR, CSRStatus

Doing actions on register read is generally not a good design practice (it's
better to do separate register write to trigger actions) but in some very
specific cases being able to know that register has been read can solve cases
that are difficult to do with the recommended practives and that can justify
doing an exception.


This commit add a we signal to CSR, CSRStatus and this allow the logic to know
when the CSR, CSRStatus is read.
This commit is contained in:
Florent Kermarrec 2019-09-24 17:51:06 +02:00
parent 47dc332498
commit ffd2be2ba0
2 changed files with 23 additions and 5 deletions

View File

@ -94,17 +94,26 @@ class CSR(_CSRBase):
w : Signal(size), in w : Signal(size), in
The value to be read from the bus. The value to be read from the bus.
Must be provided at all times. Must be provided at all times.
we : Signal(), out
The strobe signal for ``w``.
It is active for one cycle, after or during a read from the bus.
""" """
def __init__(self, size=1, name=None): def __init__(self, size=1, name=None):
_CSRBase.__init__(self, size, name) _CSRBase.__init__(self, size, name)
self.re = Signal(name=self.name + "_re") self.re = Signal(name=self.name + "_re")
self.r = Signal(self.size, name=self.name + "_r") self.r = Signal(self.size, name=self.name + "_r")
self.we = Signal(name=self.name + "_we")
self.w = Signal(self.size, name=self.name + "_w") self.w = Signal(self.size, name=self.name + "_w")
def read(self): def read(self):
"""Read method for simulation.""" """Read method for simulation."""
return (yield self.w) yield self.we.eq(1)
value = (yield self.w)
yield
yield self.we.eq(0)
return value
def write(self, value): def write(self, value):
"""Write method for simulation.""" """Write method for simulation."""
@ -282,6 +291,7 @@ class CSRStatus(_CompoundCSR):
_CompoundCSR.__init__(self, size, name) _CompoundCSR.__init__(self, size, name)
self.description = description self.description = description
self.status = Signal(self.size, reset=reset) self.status = Signal(self.size, reset=reset)
self.we = Signal()
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))
@ -292,10 +302,15 @@ 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)
self.comb += self.we.eq(sc.we)
def read(self): def read(self):
"""Read method for simulation.""" """Read method for simulation."""
return (yield self.status) yield self.we.eq(1)
value = (yield self.status)
yield
yield self.we.eq(0)
return value
# CSRStorage --------------------------------------------------------------------------------------- # CSRStorage ---------------------------------------------------------------------------------------

View File

@ -171,7 +171,10 @@ class CSRBank(csr.GenericBank):
c.r.eq(self.bus.dat_w[:c.size]), c.r.eq(self.bus.dat_w[:c.size]),
c.re.eq(sel & \ c.re.eq(sel & \
self.bus.we & \ self.bus.we & \
(self.bus.adr[adr_shift:adr_shift+self.decode_bits] == i)) (self.bus.adr[adr_shift:adr_shift+self.decode_bits] == i)),
c.we.eq(sel & \
~self.bus.we & \
(self.bus.adr[adr_shift:adr_shift+self.decode_bits] == i)),
] ]
brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs)) brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs))