nmigen-soc icon indicating copy to clipboard operation
nmigen-soc copied to clipboard

[Request] A proposal for CSRs

Open ghost opened this issue 6 years ago • 6 comments

#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 "")))

ghost avatar Sep 27 '19 07:09 ghost

For reference, here are the meanings of the access type Enums:

  • ACCESS_R : Read-only
  • ACCESS_W : Write-only
  • ACCESS_R_W : Both read and write are allowed
  • ACCESS_WONCE : Write-only, and only once per reset
  • ACCESS_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

ghost avatar Sep 27 '19 07:09 ghost

Thanks, I'll take a look soon.

whitequark avatar Sep 27 '19 07:09 whitequark

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.

whitequark avatar Oct 16 '19 15:10 whitequark

@xobs - FYI

mithro avatar Apr 29 '20 05:04 mithro

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".

xobs avatar Apr 29 '20 06:04 xobs

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:

image

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.s
  • write_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]

ghost avatar May 10 '20 06:05 ghost