开云体育

ctrl + shift + ? for shortcuts
© 2025 开云体育

crossing reset domains


 

Is there an equivalent to mkNullCrossingWire for moving between reset domains?? I'm getting BSC warnings (G0043 and G0043) about combining reset domains but I believe I have the logic worked out such that it shouldn't matter.? I'd like to silence those warnings--but only exactly here where I've put the effort into thinking it though and not anywhere else where I might accidentally mess up the domains.? I found the "-suppress-warnings" compiler flag, but didn't find anything to be more surgical.
?
I'm also open to approaching this differently if this just isn't the Bluespec way.? I'm trying to implement an inner module in one reset domain and an outer module in a subsuming domain that has a method to assert/release that inner module's reset and wraps the inner module's interface with one that forwards the method to the inner module when enabled and returns a failed indicator if the inner module is not enabled.? The appended code is representative of what I'm trying to do.? (The motivator for this is the "dmcontrol.dmactive" bit from the risc-v debug spec if that helps establish context.)
?
I've read through the various reset related posts from the last couple years and the only ideas/suggestions I uncovered were to rewrite the code to have the "enable" be explicitly represented in logic instead of leveraging reset, to slip a dual-domain fifo between the two modules, or to write some custom verilog with appropriate annotations.
?
I'm hesitant to use that first option because that would be a lot of repetitions of "if (is_enabled) ..." instead of just feeding it into the existing reset tree and would make it easy to accidentally miss a bit of state that needs to be reset.
?
I'm hesitant to use the second option because it feels like a sledgehammer/fly type solution given that both modules are in the same clock domain and one reset is a strict subset of the other.? Also it would add unnecessary latency to accessing the inner module.
?
And I'm hesitant to use the third option because it seems like I'd also have to write a custom bluesim primitive and end up with a forked bsc or give up on bluesim and just use verilator.? (I think--I haven't actually looked at the details so I don't know if it would be that bad or if there is an easy plugin interface I could leverage.? My trepidation over leveraging BDPI turned out to be totally warranted--I now have a simple BDPI based jtag proxy that talks OpenOCD's remote bit bang protocol.)
?
-William
?
?
--- cut here ---
package ResetTest;
import Clocks::*;
interface Inner;
? ?// Indicator that we are awake and ready to do something.
? ?method Bool awake();
? ?// Do something critical and amazing.
? ?method ActionValue#(Bit#(32)) do_something(Bit#(32) arg);
endinterface
interface Outer;
? ?// Turn the inner device on or off. ?Transition from off to on can
? ?// take time. ?Check for when it is done by invoking is_on().
? ?// Turning the device off resets it.
? ?method Action set_on(Bool on);
? ?// Returns true iff the inner device is on and ready to do
? ?// something.
? ?method Bool is_on();
? ?// Do something, but return Invalid if the inner device isn't
? ?// ready.
? ?method ActionValue#(Maybe#(Bit#(32))) do_something(Bit#(32) arg);
endinterface

module mkInner(Inner);
? ?Reg#(Bit#(3)) wakeup_delay <- mkReg('1);
? ?rule wakeup if (wakeup_delay != 0);
? ? ? wakeup_delay <= wakeup_delay - 1;
? ?endrule
? ?method Bool awake();
? ? ? return wakeup_delay == 0;
? ?endmethod
? ?method ActionValue#(Bit#(32)) do_something(Bit#(32) arg);
? ? ? return arg;
? ?endmethod
endmodule
(* synthesize *)
module mkOuter(Outer);
? ?Reg#(Bool) on <- mkReg(False);
? ?Clock cur_clock <- exposeCurrentClock;
? ?MakeResetIfc inner_reset <- mkResetSync(1, True, cur_clock);
? ?Inner inner <- mkInner(reset_by inner_reset.new_rst);
? ?method Action set_on(Bool v);
? ? ? on <= v;
? ?endmethod
? ?method Bool is_on();
? ? ? return on && inner.awake();
? ?endmethod
? ?method ActionValue#(Maybe#(Bit#(32))) do_something(Bit#(32) arg);
? ? ? if (on && inner.awake()) begin
? ? ? ? ?let result <- inner.do_something(arg);
? ? ? ? ?return tagged Valid result;
? ? ? end
? ? ? else
? ? ? ? ?return Invalid;
? ?endmethod
endmodule
endpackage


 

My trepidation over leveraging BDPI turned out to be totally warranted
?
Unwarranted!? My trepidation was totally unwarranted!
?
Sigh.? Proofreading fail.
?
-William
?


 

I don't believe there is a way to surgically suppress the warning.? If you have thoughts on how you would want to specify it, that would be a reasonable enhancement request.? I can imagine allowing an attribute on rules or modules, that adds to the suppression list for those scope of that rule or module.? But that may still not be surgical enough, because you probably want to specify what resets or what methods are causing the warning, so that you are informed if some other reset shows up.

I don't recall a reset laundering module, although you might try using the mkNullCrossingWire or mkNullCrossingReg modules and giving it the same source and destination clocks, and that might be work to scrub the attached reset -- and then just be careful to only use the output where it's safe.? Reset handling didn't have as thorough a think-through as clocks, so there may be things missing -- if you have ideas, feel free to suggest them.

I haven't thought about this kind of design to know if there's a better way to write it, but I can ask around.

One thought is that you could store the result of "inner.awake" in a register without a reset (mkRegU).? That (a rule that writes the submodule output to an unreset register) appears to silence all the warnings in your example.? I would guess that using mkNullCrossingWire (or the like) would be doing the same thing (though possibly with less state or delay, if that's a concern).

It is currently not possible for users to provide their own Bluesim implementations for imported modules.? That would be a good enhancement to BSC, but would require some thinking.? On the other hand, if you have an idea for a generally useful module for crossing reset domains, we could add it to BSC.

J


On Fri, Mar 14, 2025 at 11:10?AM William Howe-Lott via <william=[email protected]> wrote:
My trepidation over leveraging BDPI turned out to be totally warranted
?
Unwarranted!? My trepidation was totally unwarranted!
?
Sigh.? Proofreading fail.
?
-William
?


 

Thanks for the reply!? I gave up on trying to have multiple reset domains and instead just plummed a Bool through to all the places that needed to operate differently when the unit was "active."? But I'm going to run into the problem again if I try to implement the separate "whole system sans debug module" reset and "just the cpu/hart" reset, so I'll see if I can prototype some enhancement suggestions.? The first that comes to mind is adding:
?
funciton Maybe#(t) unlessReset(t v);
?
that returns Invalid if v's associated reset is asserted and returns Valid(v) it it isn't and erases the dependency on v's associated reset but would preserve the clock domain.
?
-William
?