Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

csr: A proposal for DSL design #7

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open

Conversation

ghost
Copy link

@ghost ghost commented Apr 23, 2020

This pull request was based on the initial design (3195de9) here on M-Lab's repo, so its usage might be different from the more recent nmigen-soc branch on nMigen's repo and the syntax might be incompatible with that. The main focus of this PR is to introduce a domain-specific language (DSL) subset of nMigen just for implementing CSRs. Below shown is an example showing possible ways to declare a hierarchy of CSRs:

with Bank("decoder_bank", addr_width=5, data_width=8, alignment=2, type="dec") as bank:
    bank.r += [
        Register("read_only", "r", width=8,
                 fields=[Field("val", width=8, reset_value=0x22)])
    ]
    with Register("read_write", "rw", width=16) as csr_rw:
        csr.f += [
            Field("ro", access="r", width=5, reset_value=0x16),
            Field("wo", access="w", width=4, reset_value=0x3),
            Field("rw", width=7, reset_value=0x4c,
                  enums=[("MIN", 0), ("MAX", 0x7F)]),
        ]
    with Register("write_only", "w") as csr_w:
        with Field("val", width=2, startbit=2, reset_value=0x4) as field_val:
            field_val.e += [
                ("EXTREME_HIGH", 3), ("HIGH", 2),
                ("EXTREME_LOW", 0), ("LOW", 1)
            ]
        csr_w.f += field_val
    bank.r += [csr_rw, csr_w]

Its equivalent CSR design can be described with the following picture:
csr-example-001

Another main change to the existing code in the master branch here is a fix on WishboneCSRBridge such that the Wishbone ACK can be asserted properly per read or write.


To-do / Possible improvement

  1. Bitmasked Enums: As per discussion, an enum value could be a "bitmask" where certain bits are "don't care", as in the SVD format. One concern is that whether or not each bitmask value should have a unique name as the key.
  2. Re-test using latest CSR bus definitions: By simulation and preferably on an actual platform as well.
  3. @property tags: Currently they are here to prevent users from editing the values after instantiating the CSR fields as their Signals are named the same way. Is this necessary?
  4. Automatic address width: Is it possible to assign/re-assign the address width for the register and bank dynamically as the user adds more fields or registers to them?

* Field is now a context manager: enums must be added using `with field` block, but can be read from outside using `field.Enums`
* Bank & Register no longer needs `with <object> as <var>` block, only `with <object>` in order to build them with regs and fields
* Bank now only aligns register addresses without resizing the registers
* Register bits in locations that are not occupied by any Fields are now regular Signals, with no access restrictions (i.e. treated as don't care).
* Any attempt to read or write these bits via a bus will return or change their values without any restrictions.
* Instead of storing a Signal in each Field, each Register now store a single Signal comprising of both Field bits and "don't care" bits
* Each Field object no longer carries a value, but only the information needed to describe a Register (e.g. bit locations, access mode, enumerated values)
* Add an internal write strobe (`set_stb`/`set_enable`/`set_en`/`int_w_stb`) to Register and Field; asserted when the logic reassigns the values and overrides any writes from the bus.
* Add an internal write data signal (`set_val`/`set_value`/`int_w_data`) to Register; contains the data that the logic uses to reassign the Register or Field values when `set_stb` is asserted.
* Each Field now allows value assignments from the following sources: (The smaller the number, the higher the priority)
  (1) Bank reset strobe (`Bank.rst_stb`): when asserted, reset all its Registers in the Bank to their reset values at the next clock
  (2) Register reset strobe (`Register.rst_stb`): when asserted, reset all its Fields to their reset values and the remaining bits to 0 at the next clock
  (3) Register internal write strobe (`Register.set_stb`): when asserted, set all its Fields to their own current `Field.set_val` value at the next clock
  (4) Field internal write strobe (`Field.set_stb`): when asserted, set the Field to its own current `Field.set_val` value at the next clock
  (5) Register bus write strobe (`Register.w_stb`): when asserted, set all its Fields to the current `Element.w_data` value at the next clock
* When either `Bank.rst_stb` or `Register.rst_stb` is asserted while `bus.rst_stb` is high, each Register now returns the reset value to `Element.r_data` for reading immediately
@ghost ghost mentioned this pull request May 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant