-
Notifications
You must be signed in to change notification settings - Fork 651
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
Revamp the config system for Top/Harness #347
Conversation
142205e
to
c5990c2
Compare
d0d2522
to
d743f3f
Compare
[I know this WIP, these are mostly just thoughts on the current implementation.] I think this is a step in the right direction but i think the problem with the current implementation is that leans heavily on there existing only a single top class with the complete set of all possible It might be better to relax the type BuildTop elaborates (say, all the way to a Module or LazyModule), and then engineer a more flexible solution to generate the harness around it. The partial-function-based solution we use in FireSim (see BridgeBinders.scala) is one attempt at this, but it too has its limitations. A second independent point is that relying on |
I'm assuming a world where all the traits can be parameterized to be no-ops. In that case, I'm not sure what issues would arise from making the standard pattern "add your custom trait to the base Top". Ideally we would be able to define new Tops with custom Traits at runtime, but I'm not sure how to do that, and this seems like a better middle-ground for now.
The partial function stuff is interesting. My concern with that approach is that it would require defining another layer of abstraction wrapping all the methods defined in the various traits, if I understand correctly.
Yeah, the examples for this case I can think of are the block device and success ports. I hope that in the documentation, we can explain clearly enough why things like |
d743f3f
to
02eff5e
Compare
a9b5cc3
to
6a0cb03
Compare
757eb76
to
0418a90
Compare
I added more documentation on how custom traits work. This should be good to go now, pending sub-project PRs. I'd like to get this in before the upcoming Chipyard release. |
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 pretty good. Just a few questions.
val top = up(BuildTop, site)(clock, reset, p, success) | ||
for (gpio <- top.gpio) { | ||
for (pin <- gpio.pins) { | ||
pin.i.ival := false.B |
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.
Is this tying all of the GPIO inputs to 0 inside the DUT?
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.
This code was copied from the older WithGPIOTop
mixin. I'm not sure what the right thing to do here is, but I would be happy to implement it
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.
This is called from outside the DUT (in the TestHarness), so it should be tying them to 0 outside the DUT.
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 think we want a separate PR that adds IO cell blackboxes to have "Correct" functionality. That's been a work in progress for a while, but we can reprioritize it.
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.
While I agree with John on this, I don't think we need to block on this? Also, it might be good to add a comment that this is connecting from outside the DUT.
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.
separate PR
means it's not blocking
class WithDTM extends Config((site, here, up) => { | ||
case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => { | ||
val top = up(BuildTop, site)(clock, reset, p, success) | ||
top.reset := reset.asBool | top.debug.get.ndreset |
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.
Is this circumventing reset synchronizers?
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.
Could you clarify? This was copied from the old DTMTop module, and I'm not familiar with some of its mechanics.
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.
Unless something's changed (which is possible), this is connecting the test-harness-level clock and reset to the DUT. That should be fine for simulation, but we might want to note that in a real chip you'd probably have an async top-level reset and a ResetCatchAndSync
somewhere inside the chip. I was asking the question because I don't actually know if that ResetCatchAndSync
is in the RocketSubsystem
already or not (maybe @colinschmidt can chime in).
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.
It looks like Rocket Chip's TestHarness does
dut.reset := reset | dut.debug.map { debug => AsyncResetReg(debug.ndreset) }.getOrElse(false.B)
I guess we should be using the AsyncResetReg
here?
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.
Yeah, we should fix that, but it wasn't the only problem I was referring to. The other thing was that you likely won't have a clock
pin; you probably have a PLL, etc. that would generate a clock you need to synchronize reset
to.
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.
So in Chipyard currently the hierarchy is TestHarness -> Top
, while for real chips the hierarchy would likely look like TestHarness -> ChipTop -> Top
. In BEAGLE the chip-specific clocking and reset needs are handled within ChipTop
.
With the current BuildTop rules, it looks like the way to do this would be to call p(BuildTop)
within ChipTop
, creating something like:
class ChipTop(implicit val p: Parameters) extends RawModule {
val sys_clk = Wire(Clock())
val sys_rst = Wire(Bool())
val sys_success = Wire(Bool())
val sys = p(BuildTop)(sys_clock, sys_reset, p, sys_success)
...
}
The issue is currently we don't have this extra ChipTop
layer within Chipyard. It seems like that would be a good thing to add in the future.
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 don't think rocket-chip currently does catch and sync for the top-level reset. They may be moving in that direction based on recent PRs, but its certainly not in our tagged version yet.
I like it would be cool to have something that is a "reasonable" ChipTop
in chipyard so we can make the knowledge of how to do this "safely" more widely known.
I think thats outside of the scope of this PR, in that this doesn't change the current state of chipyard w.r.t. clock&reset. But we should file an issue to track a "realistic clock and reset mixin".
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'll file an issue for ChipTop
, while I'll leave it to someone more familiar with the clock&reset issues to write that.
Overall seems fine with me. John covered most of my cleanliness comments on the GCD stuff. |
0418a90
to
165725a
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'm still skeptical this will scale out how we'd like (see previous comment) and i'm a little worried the BuildTop trick might be a little too cute but otherwise this looks great to me.
:start-after: DOC include start: gpio mixin | ||
:end-before: DOC include end: gpio mixin | ||
|
||
When ``WithGPIO ++ WithTSI`` is evaluated right to left, the call to ``up(BuildTop, site)`` in ``WithGPIO`` will reference the function defined in the ``BuildTop`` key of ``WithTSI``. Thus, at elaboration time, when the ``BuildTop`` function is called by the ``TestHarness``, first the ``BuildTop`` function in ``WithTSI`` will be evaluated. This connects the ``success`` signal of the ``TestHarness`` to the ``SerialAdapter`` enabled by ``WithTSI``. Then, the rest of the code in the ``BuildTop`` function of ``WithGPIO`` will execute, tieing off the top-level GPIO input pins. Thus the evaluation of the ``BuildTop`` functions in a completed config is "right-to-left", matching how the evaluation of the mixins at compile-time is also "right-to-left". |
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.
This may be an appropriate time to explain, or at least allude to, what site
is.
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.
+1
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 found it difficult to mention site
without discussing the rest of the CDE system. I added a sub-section on CDEs to the Advanced-Concepts section, and linked to it from here.
@davidbiancolin @alonamid do you mind reviewing that page I just added? Its docs/Advanced-Concepts/CDEs.rst
. I think that's the final set of changes that need reviewing.
165725a
to
38293fb
Compare
38293fb
to
869989d
Compare
Can you confirm that all the configs in Chipyard at least build with this approach? |
869989d
to
59782ed
Compare
Good call @abejgonzalez . Turns out the SHA3 Configs were all broken after the recent rocket chip bump. I fixed that and bumped the SHA3 submodule in this PR as well. All RocketConfigs elaborated verilog successfully. The BlockDevice and GCD configs (which utilize scala resources) also compiled in VCS correctly. This is still waiting on several submodule PRs to get merged |
59782ed
to
25e280b
Compare
Did you also check the FireChip configs (make sure things build with FireSim)? |
Both FireSim and FireSimNoNIC targets work. Perhaps we should add these to the regressions. |
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.
LGTM
25e280b
to
9a44f6c
Compare
9a44f6c
to
cfccf1c
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.
LGTM pending passing tests.
Merging. CI fails because I did not merge the FireSim submodule PR, so @davidbiancolin can deal with the circular dependency madness. |
It is strange that we use the config/mixin system to parameterize everything except for the Top/Harness, for which we still have to use a system of maintaining copies of Tops and Harnesses with precisely chosen traits to do what we want. There is also a lack of concrete documentation regarding the interactions between keys, traits, and mixins, and the standard patterns for using them. I restuctured the config system around what I believe should be the correct patterns for using these, and I define them below.
None
should mean no change to the system. (The custom widget is not instantiated and connected)Option
type, with the default value set toNone
, preferablyCanHave
semantics. Many Rocketchip traits already haveCanHave
semantics, since they are no-ops if their corresponding keys are set to None.CanHave
trait and add it to whatever Top they are using (either example/Top or a copy of it).BuildTop
key to instantiate whatever custom block is needed in the Harness and wire the Top ports to whatever is desired. See the WithTSI or WithGPIO mixins for examples. Mixins should also set the parameters key for the custom widget (for example,BlockDeviceKey
)Some other notes from these changes:
BuildTop
key. Adding ports to a Top is done by finding the top viap(BuildTop, site)
, and calling the method of that top which connects the ports.WithGPIO ++ WithPWMTL
results in a Top with both GPIO and PWM pins, with no other changes necessary.success
signal to theBuildTop
function, we avoid the need to instantiate a separate TestHarness for DTM-bringup.ConfigMixins
now contain mixins that set both theBuildTop
key (which controls the Top ports), as well as the widget keys (which control the instantiation and parameterization of the widgets). Thus one mixin is sufficient to both set custom ports, and connect those custom ports to a custom module.WithNoGPIO
mixin is an unfortunate byproduct ofsifive-blocks
not setting a default value forPeripheryGPIOKey
. I currently have a PR open for this which should allow us to remove all those mixins from the default. Set PeripheryKey defaults to Nil sifive/sifive-blocks#123CanHave
semantics simplifies convergence between FireSim/Chipyard targetsFireSimDUT
and Chipyard'sTop
can be merged into oneTop
with a superset of allCanHave
traits. Then, the divergence between the two designs can be configured at the mixin level, rather than the trait level