Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

lschuermann
Copy link
Member

@lschuermann lschuermann commented Nov 18, 2020

Pull Request Overview

This PR introduces support for LiteX SoCs built around a VexRiscv CPU. Timer, UART, LED and LiteEth cores are currently supported. The litex_sim and litex_arty boards target the default litex_sim.py and arty.py SoC definitions of a specific release of LiteX respectively.

LiteX

LiteX is a Migen/MiSoC based Core/SoC builder that provides the infrastructure to easily create Cores/SoCs (with or without CPU).

By its nature, LiteX supports generating a plethora of different SoCs. This PR implements drivers for a selection of LiteX cores (Timer, UART, LED, Ethernet). Naturally, these cores - being described in the hardware description language Migen - can be changed to break compatibility with the drivers in Tock. The idea is to pin, per board in the README, a specific version of LiteX and parameters for generating the SoC definition with which Tocks is compatible. Variations in the design should be reflected in Tock by adjustable constants, types and other compile time options wherever it makes sense.

Ethernet

Both the Arty A7 board and the verilated simulation feature an Ethernet MAC, which connects to an on-board PHY or a tap network interface respectively. In the near future, I will create a PR for VirtIO-based network interfaces. This deliberately does not try to define a HIL yet, as at least two different implementations should be considered for the design. Hence the interface of the Ethernet MAC is subject to change.

litex_registers.rs / litex-register-gen

LiteX has the notion of Configuration Status Registers, which are not to be confused with RISC-V's CSRs. These registers are exposed on a Wishbone bus over the SoC. The CSRs can be generated with different data widths (for efficient routing on small FPGAs), aligment settings, bus widths, etc. litex_registers.rs abstracts these unconventional and varying layouts using structs named according to the scheme <AccessTypes><RegisterWidth>C<CSRDataWidth>B<BaseWidth>. Register abstraction types of a common layout configuration are grouped using the LiteXSoCRegisterConfiguration trait. Register structs can then be made generic over this trait. Refer to chips/litex/src/timer.rs for a usage example. This comment futher explains how the LiteXSoCRegisterConfiguration works.

To avoid a massive amount of repetitive code, litex_registers.rs generates these types using a procedural macro defined in libraries/litex-register-gen. If this macro should not be included within Tock, I will moved it to the companion support repository and include the expanded Rust code instead. The procedural macro to generate the LiteX register types is removed from this PR and the generated output is statically placed into litex_registers.rs instead. It can be reviewed in a followup PR instead.

As generic associated types are an unstable Rust feature, the wrapper types {Read,Write,ReadWrite}RegWrapper are required to access bitfields of registers. As soon as this feature lands in stable Rust, the zero-cost wrappers can be removed.

Testing Strategy

This pull request was tested by

  • running different userspace apps on both litex_arty and litex_sim
  • implementing a small IPv6 ND/ping stack in the kernel and pinging both litex_arty and litex_sim

TODO or Help Wanted

VexRiscv is still missing PMP support upstream! While there is a pull request for adding support, currently the boards lack memory protection entirely. This is expliclity documented in the respective board READMEs.

There are still some minor TODOs until this is ready

  • document the litex_registers and litex-register-gen
  • there is some weird behaviour with the scheduler timer, which needs to be further diagnosed VirtualSchedulerTimer issue identified to be independent of this PR, fix proposed in VirtualSchedulerTimer: fix incorrect set_alarm invocation #2267
  • in general, method documentation of the peripherals should be improved / added
  • check that 64-bit timer overflows are handled correctly in LiteXAlarm (overflows after >5000 years @100MHz)
  • (the Ethernet MAC TX currently only supports a single slot -> non-blocking issue, Ethernet should still work fine)

Documentation Updated

  • Updated the relevant files in /docs, or no updates are required.

Formatting

  • Ran make prepush.

New Platform Checklist

  • Hardware is widely available: yes, and the verilated simulation does not require hardware
  • I can support the platform, which includes release testing for the platform, at least initially.
  • Basic features are implemented:
    • Console, including debug!() and userspace printf().
    • Timers.
    • GPIO with interrupts. LEDs work through a special LED driver core, LiteX does not include a GPIO core in the default target definitions

This introduces support for LiteX SoCs built around a VexRiscv
CPU. Timer, UART, Led and LiteEth cores are currently supported.

The arty.py and litex_sim.py SoC definitions of a specific release of
LiteX are supported as boards.
@lschuermann lschuermann changed the title Dev/litex port Port to LiteX+VexRiscv-based SoCs Nov 18, 2020
This makes boards depend only on the crate implementing a specific CPU
architecture, while still having access to all LiteX core drivers and
support modules.
This adds an explanation as to why the InterruptService needs to be
defined in the board crates instead of the chip crates.

As LiteX is no single chip and the softcores have sequentially
numbered interrupts, a default implementation would not make sense.
As pointed out by Alistair Francis, PLIC is specified within RISC-V
and VexRiscv has its own custom implementation. Hence the module
should not be called "plic".
Copy link
Contributor

@alistair23 alistair23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused by the need for the LiteXSoCRegisterConfiguration.

Is the problem that the Tock register interface assumes a usize length for register accesses, while LiteX allows any length (8/6/32/64 bits) registers?

This also changes the heading from "Warning" to "Please note" as
suggested by Alistair Francis. While a missing PMP is worth noting,
it should not be a "Warning".
This method is not used, since the pending interrupts are always first
saved to an internal state and then accessed. This method might not do
what users expect, hence remove it.
This replaces a custom iterator-based search for the number of
trailing zeros by an LLVM intrinsic, as recommended by Alistair
Francis.
@lschuermann
Copy link
Member Author

I'm a little confused by the need for the LiteXSoCRegisterConfiguration.

Right, it's a little confusing. LiteX generates SoC with peripherals on a bus (for instance Wishbone), which then expose so called configuration status registers (CSRs). Because routing wide buses on an FPGA is difficult and may consume more resources, LiteX allows you to specify the bus data width, to for instance 8 or 32 bits. Also endianness of the CSRs or the base integer width of the CPU may vary. This leads to predictable changes in the CSR layouts, which the LiteXSoCRegisterConfiguration abstracts over with different register types.

For instance, with --csr-data-width=32, the ethmac registers look like this:

Addr Register
0x00 rx_slot (2 bits wide)
0x04 rx_length (32 bits wide)

whereas with --csr-data-width=8 it would look like this:

Addr Register
0x00 rx_slot (2 bits wide)
0x04 rx_length MSB byte 0
0x08 rx_length MSB byte 1
0x0C rx_length MSB byte 2
0x10 rx_length MSB byte 3

We could just opt for supporting one of these variants. Limiting ourselves to 8 bits data width is very inefficient on large platforms, whereas limiting to 32 bits could exceed the HW limits of potentially interesting small targets such as FOMU. LiteX has just recently switched to 32 as the default, as the impact is not too bad on most FPGAs, whereas on the iCE40 we're really close to the FPGA limits, so 8 might be beneficial.

My suggestion: we keep this complexity for now (since it's written anyways, and IMHO is an interesting example of how hardware-software codesign could look in Tock). I'm trying to get Tock to run on FOMU. LiteX is also an interesting experimentation candidate to try 64bit RISC-V CPUs, for which we'd need this abstraction too. If 8 bit wide CSRs loose significance within the interesting targets in Tock+LiteX and/or we decide that we don't want 64-bit RISC-V support, we can always replace it by standard tock-registers types later.

I'm going to throw out the macro for generating these types from this PR and just insert the generated code. The macro could then be reviewed in a follow-up PR.

This makes the constructor of the LiteEth MAC non-const to not require
the const_mut_refs feature.

Also reverts the change done to make the TakeCell constructor const.
This feature is no longer required with a non-const constructor on
LiteXLed.
This instead uses the generated Rust-code directly in the
litex_registers.rs register abstraction module. The litex-register-gen
macro can be reintroduced as as follow-up changeset, to be review
separately.
bradjc
bradjc previously approved these changes Dec 2, 2020
Copy link
Contributor

@bradjc bradjc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

I'm a little hesitant about having two boards and the potential difficulty of maintaining them, but I suspect that either it won't be a problem or we can re-evaluate in the future.

Also, the register thing is pretty weird, but the new register interface is self contained, so that seems like a good solution.

@bradjc bradjc added the arch/risc-v RISC-V architecture label Dec 2, 2020
Copy link
Contributor

@alistair23 alistair23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good.

I think it would be great if the duplicate board code could be reduced between the two boards. The new component method of creating boards should hopefully be able to help with that.

For the Litex Registers I would like to see that functionality added to Tock registers instead. Although it seems to be a specific LiteX use case it would still remove a lot of duplicate code by allowing non target length accesses in Tock registers. Maybe there are other platforms where this would be useful as well. In saying that if it ends up a pain to implement maybe this is better. I just see it diverging from Tock registers and as bugs are fixes there, they won't be fixed here.

Also the current timer implementation seems a little sketchy and doesn't handle overflows. That should be improved.

I don't think any of those 3 issues block merging this though, they can be future improvements.

@lschuermann
Copy link
Member Author

@lindemer That's pretty awesome! It makes this a much more viable target for Tock. I'll fix the LiteX timers today though, and since this is a long and large PR already I'd prefer not to switch the CPU or LiteX release in this, but rather in a follow up PR. 👍

This fixes TODOs, improves documentation and event manager operations
of the LiteXTimer timer core implementation.
This changes LiteXAlarm to store both the passed alarm time and
reference and uses the Ticks::within_range method to check whether the
alarm expired.
This removes the option to mark the LED controller as "active low", as
signal inversion of a high level LED controller should be done in
hardware.

Furthermore, it automatically deregisters LiteXLed instances with the
controller when dropped.
@lschuermann lschuermann removed the Work in Progress PR that is still being updated, feedback is likely helpful. label Dec 14, 2020
@lschuermann
Copy link
Member Author

lschuermann commented Dec 14, 2020

I rewrote large parts of the timer and alarm infrastructure which should now be more reliable and handle a wrapping uptime register reliably (although it's very unlikely given it's a 64-bit timer at ~100MHz-1GHz). In general, the documentation is improved and many rough edges have been removed. With the scheduler timer bug identified to be independent of this PR and a solution proposed in #2267, I think this could be ready to go! I'll take care of the (now integrated) PMP and Ethernet improvements (along with a trait and TAP-networking driver) in followup PRs.

I have opted to put the LiteX boards into their own respective subdirectory, to avoid cluttering the boards directory and make sharing a common codebase easier in the future.

Thank you for your reviews and patience, @alistair23 @bradjc @hudson-ayers!

I think with PMP, Ethernet, a Verilated simulation and potential ibex CPU support LiteX could be a really interesting target.

bors bot added a commit that referenced this pull request Dec 14, 2020
2267: VirtualSchedulerTimer: fix incorrect set_alarm invocation r=bradjc a=lschuermann

### Pull Request Overview

This fixes a subtle bug in the `VirtualSchedulerTimer` implementation, where a call to `set_alarm` would pass in the reference, along with the future alarm time, where it should be just the delta between the reference and alarm time.

This issue manifests itself when a round-robin scheduler is used in combination with the `VirtualSchedulerTimer`. It was probably unnoticed because no such combination exists in the upstream repository.

I think calling `.set_alarm(` by passing the absolute reference timestamp, along with the relative delta, is the correct invocation method (and have implemented my `Alarm` implementation in LiteX accordingly) based on this comment:

https://github.com/tock/tock/blob/d63f97706125b59c974a9438f70b5011a55f3b48/kernel/src/hil/time.rs#L178-L186


### Testing Strategy

This pull request was tested by running on `litex_sim` (of #2203) using the round robin scheduler. The application is no longer blocked for 15+ seconds.


### TODO or Help Wanted

N/A


### Documentation Updated

- [x] Updated the relevant files in `/docs`, or no updates are required.

### Formatting

- [x] Ran `make prepush`.


Co-authored-by: Leon Schuermann <[email protected]>
bradjc
bradjc previously approved these changes Dec 14, 2020
Copy link
Contributor

@bradjc bradjc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't look through all the files in detail, but looks like a good new platform addition!

alistair23
alistair23 previously approved these changes Dec 14, 2020
@lschuermann lschuermann dismissed stale reviews from alistair23 and bradjc via d5460a5 December 15, 2020 08:03
@lschuermann
Copy link
Member Author

@bradjc Addressed your documentation comments, which unfortunately dismissed the reviews @alistair23 @bradjc.

@bradjc bradjc added the last-call Final review period for a pull request. label Dec 17, 2020
@bradjc
Copy link
Contributor

bradjc commented Dec 17, 2020

bors r+

@bors
Copy link
Contributor

bors bot commented Dec 17, 2020

@bors bors bot merged commit 3cd2c2d into tock:master Dec 17, 2020
@lschuermann lschuermann deleted the dev/litex-port branch January 16, 2021 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch/risc-v RISC-V architecture last-call Final review period for a pull request.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants