-
-
Notifications
You must be signed in to change notification settings - Fork 771
Port to LiteX+VexRiscv-based SoCs #2203
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
Conversation
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.
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".
There was a problem hiding this 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.
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 For instance, with
whereas with
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 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.
There was a problem hiding this 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.
There was a problem hiding this 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.
@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.
7a2f6e1
to
32a6b1a
Compare
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 |
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]>
This mirrors the way Nordic boards are shipped in upstream Tock.
490d57f
to
fa98a94
Compare
There was a problem hiding this 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!
@bradjc Addressed your documentation comments, which unfortunately dismissed the reviews @alistair23 @bradjc. |
d5460a5
to
df4f522
Compare
bors r+ |
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
andlitex_arty
boards target the defaultlitex_sim.py
andarty.py
SoC definitions of a specific release of LiteX respectively.litex_arty
targets the Digilent Arty-A7 FPGA development boardA working bitstream (
arty.bit
) is provided in a companion repository, tock-litex-support.litex_sim
is a verilated simulation of a LiteX SoC, with UART, Timer and Ethernet coresLiteX
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 theLiteXSoCRegisterConfiguration
trait. Register structs can then be made generic over this trait. Refer tochips/litex/src/timer.rs
for a usage example. This comment futher explains how theLiteXSoCRegisterConfiguration
works.To avoid a massive amount of repetitive code,The procedural macro to generate the LiteX register types is removed from this PR and the generated output is statically placed intolitex_registers.rs
generates these types using a procedural macro defined inlibraries/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.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
litex_arty
andlitex_sim
litex_arty
andlitex_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
litex_registers
andlitex-register-gen
there is some weird behaviour with the scheduler timer, which needs to be further diagnosedVirtualSchedulerTimer
issue identified to be independent of this PR, fix proposed in VirtualSchedulerTimer: fix incorrect set_alarm invocation #2267LiteXAlarm
(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
/docs
, or no updates are required.Formatting
make prepush
.New Platform Checklist
Console
, includingdebug!()
and userspaceprintf()
.GPIO with interrupts.LEDs work through a special LED driver core, LiteX does not include a GPIO core in the default target definitions