nmigen-soc
nmigen-soc copied to clipboard
[Request] A proposal for CSRs
#1 Following the general ideas discussed, I have made a new abstraction for CSR objects in my fork (https://github.com/HarryHo90sHK/nmigen-soc/commit/ba5f354de8b1b06bff577c753e967c3b2a514a54 fixed). An example script is given below, which will print all the fields and their properties in a CSR named "test". You might also test the slicing functionality using the format mycsr[beginbit:endbit], but please note that the upper boundary is exclusive.
from nmigen import *
from nmigen_soc.csr import *
if __name__ == "__main__":
mycsr = CSRGeneric("test", size=64, access=ACCESS_R_W, desc="A R/W test register")
mycsr.f += CSRField("enable", desc="Enable signal", enums=['OFF', 'ON'])
mycsr.f += CSRField("is_writing", size=2, access=ACCESS_R, desc="Status signal of writing or not",
enums=[
("YES", 1),
("NO", 0),
("UNDEFINED", 2)
])
mycsr.f += CSRField("is_reading", size=2, access=ACCESS_R, desc="Status signal of reading or not")
mycsr.f.is_reading.e += [
("UNDEFINED", 2),
("YES", 1),
("NO", 0)
]
mycsr.f += CSRField("is_busy", size=2, access=ACCESS_R_WONCE, desc="Busy signal",
enums=[
("YES", 1),
("NO", 0),
("UNKNOWN", -1)
])
mycsr.f += [
CSRField("misc_a", size=32),
CSRField("misc_b"),
CSRField("misc_c")
]
mycsr.f.misc_a.e += [
("HOT", 100000000),
("COLD", -100000000),
("NEUTRAL", 0)
]
#mycsr.f += CSRField("impossible", size=30, startbit=6)
print("{} (size={}) is {} : {}".format(
mycsr.name,
mycsr.size,
mycsr.access,
mycsr.desc))
for x in mycsr._fields:
print(" {} [{},{}] (size={}) is {}{}".format(
mycsr._fields[x].name,
mycsr._fields[x].startbit,
mycsr._fields[x].endbit,
mycsr._fields[x].size,
mycsr._fields[x].access,
(" : "+mycsr._fields[x].desc if mycsr._fields[x].desc is not None else "")))
For reference, here are the meanings of the access type Enums:
ACCESS_R: Read-onlyACCESS_W: Write-onlyACCESS_R_W: Both read and write are allowedACCESS_WONCE: Write-only, and only once per resetACCESS_R_WONCE: Both read and write are allowed, but only one write is allowed per reset
Please also refer to: http://www.keil.com/pack/doc/CMSIS/SVD/html/elem_special.html#elem_access
Thanks, I'll take a look soon.
Thank you for the proposal. I have in mind some ways to simplify the code in your branch. I'm going to sketch out an implementation I have in mind, and then ask you for feedback to make sure I didn't miss anything important.
@xobs - FYI
How does this work for don't care fields?
For example, in the SVD format you can specify x for values that should be marked "do not care".
Edit: my pull request has overlooked this specification where "don't care" exists within enumerated values themselves. This should be open for discussion.
@mithro @xobs My implementation is now a pull request in #7.
Each register has a Signal storing its whole value. The value of each of its fields are Slices of this signal, e.g. [ start_bit : end_bit+1 ]. Thus, while fields can be referred to either by name or bit locations, "don't care" bits can be referred to only by their bit locations. Take the following example:

The register write_only only has a field val on bits 2-3, whose value can be represented as any one of the following expressions:
write_only.f.val.swrite_only.f.val[:]write_only[2:]
The bits 0-1 are not represented using any field name, but only as the following expression:
write_only[0:2]