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

Poke in PeekPokeTester always happens at negedge??? #159

Open
dingqingy opened this issue Jul 11, 2017 · 9 comments
Open

Poke in PeekPokeTester always happens at negedge??? #159

dingqingy opened this issue Jul 11, 2017 · 9 comments

Comments

@dingqingy
Copy link

I am testing a hardware that has streaming IO. From vcd waveform, it looks like that "poke" always happens at negedge. Is there a way to poke at the posedge of the clock?

@chick
Copy link
Contributor

chick commented Jul 17, 2017

There is not currently a way to do this. I will link this to our list of things to consider in a testers refactoring project we are reviewing.

@johnsbrew
Copy link
Contributor

johnsbrew commented Jul 5, 2019

Hi @chick
This "feature" or most likely "design choice" is getting very annoying for testing Ready/Valid interfaces.
Consider the following case:

class DumpBufferRegister(width : Int) extends Module {
  val io = IO(new Bundle {
    val in  = Flipped(Decoupled(UInt(width.W)))
    val out = Decoupled(UInt(width.W))
  })
  val reg_valid = RegInit(Bool(), false.B)
  val reg_data  = Reg(UInt(width.W))
  val reg_ready = Wire(Bool())

  when(reg_ready){
    reg_valid :=  io.in.valid
    reg_data  :=  io.in.bits
  }
  reg_ready := io.out.ready || !reg_valid
  
  io.in.ready  := reg_ready
  io.out.valid := reg_valid
  io.out.bits  := reg_data
}

In this example io.in.ready depends on both a combinational entry io.out.ready which is driven at negedge by the PeekPokeTester and the synchronous reg_valid, driven at posedge.

The issue is pretty simple:

  • at cycle N
    • poke(io.out.ready, <value>)
    • By design peek(io.in.ready) will NOT reflect immediately the combinational change so it is impossible to know at that point if the transaction will be validated or not
  • at cycle N+1
    • One might think that peek(io.in.ready) will reflect the actual status of ready at posedge but ... NO!
    • Indeed since the io.in.ready is also clock dependent so it might have changed at posedge (and in the small example this will always be the case)

Conclusion, as far as I know :

  • there is no way of safely testing a generic module relying on DecoupledIOs (without compromising on io.out.ready random generation or doing some kind of white-box testing trick on ready signals)
  • this is due (and only due) to the design choice of at negedge stepping (since combinationally updated peek does not seem to be technically feasible: eg: what if multiple poke/peek comb update at the same step ? ... and other issues)
  • so why @chick ?

@jackkoenig I would be interested to know how you overcome this major flaw in your everyday (real-industrial)-life ?

I have seen in VCS and IVL backend that an option isGateLevel exists at the bottom of the backend stack (in the verilog harness generation)

writer write " always @(%s clock) begin\n".format(if (isGateLevel) "posedge" else "negedge")

  • Why is not forwarded up to the testerOptions ?
  • Would it be complicated to have the same kind of option for verilator and treadle ?
  • What about tester2 ?

That being said, thank you for your great work on the tester 👍

@chick
Copy link
Contributor

chick commented Jul 5, 2019

This has come up before and I don't have an answer for it IIRC @ducky64 had a reasoned argument about this in the last year but I was unable to find it. I think he will be back in the lab next week and can weigh in. In the meantime:

In my efforts to add verilator support to testers2 I have been hitting what I believe are related problems. I am working my way through verilator. Up to now, it's has been a black box to me. Treadle was built to do things, as much as possible, the same as the verilator backend. It is capable of doing a lot more than the testers API allows, including I think what you are looking for here, but the only way to do it now is writing your own native treadle harness. Probably not what you want to do.

It would be really helpful if you could provide a chisel-testers test for the circuit described above that exposes the problem. Use pseudo-code if necessary, or perhaps to show some idea of what you'd like the API to do. That would be helpful guiding me through verilator.

I am leaving tomorrow for a week vacation with very limited internet access, but I will try to get to this as soon as possible. Maybe @ducky64 or @jackkoenig will have some solution in the interim. Thanks for the thorough explanation.

@ducky64
Copy link
Contributor

ducky64 commented Jul 7, 2019

I don't remember any explicit rationale, but one nice side effect of clock high for register transitions and clock low for pokes is that it might be easier to visually differentiate register propagation and test stimulus change on waveform dumps.

Side note: for testers2, I think I want to introduce a half-step construct that gives higher control and allows both posedge and negedge pokes. I don't know if I formalized the semantics for full step (either rising then falling, or falling then rising) though.

I'm not sure I completely understand your example, but I think you're looking for some guarantee that a some peek happens after a particular poke? I believe that PeekPokeTesters follows an imperative programming model and peeks after pokes should reflect the results of the pokes - and in your example negedge is kind of a hack to achieve that. In testers2, I've implemented the concept of regions so that operations can be ordered within a time step especially when threading concurrency is involved. The idea is there would be a dedicated monitor region which happens after the main region, with the convention being that no poke operations should happen in the monitor region.

@johnsbrew
Copy link
Contributor

johnsbrew commented Jul 17, 2019

Hi @chick & @ducky64 and thank you for your answers
FYI, my current solution consists in wrapping the DUT with a Module that registers all the input signals at posedge.

Concerning this tiny example, I've just tried to make a simple PeekPokeTester that exposes the issue.
I couldn't.
The reason is with this example whenever I poke io.out.ready, io.in.ready does reflect the combinational changes. (both with treadle and verilator)
In such a case my above-explained proof does not hold anymore.
I will have to extract a more complex example and come back with it.

Do you think that it might depend of the number of deltas/steps the simulator has to compute to solve the combinational path ?

@ducky64
Copy link
Contributor

ducky64 commented Jul 17, 2019

My understanding is that combinational paths are re-evaluated on a peek-after-poke. Peeking stale combinational paths would be a bug.

@johnsbrew
Copy link
Contributor

I have at last found back my notes explaining my previous issues:
Actually there are no issues most of the time however if one introduces a blackbox on a combinational path (also purely combinational inside the blackbox), then the one would peek a stale combinational path.
As I do blackbox basic primitives provided by FPGA vendors such as FIFOs, I encounter this problem in many of my designs.
I will attempt to set up a simple example of this issue with a black box.
Conclusion : I guess my troubles are not really related to negdege poke.

@yupferris
Copy link

Hi, is this something that's still being considered in any capacity? It would be great to at least have the option to select which edge pokes should be aligned with in traces.

@nndurj
Copy link

nndurj commented Feb 16, 2024

Hi, I am also having trouble testing Decoupled because of this. please make pokes/peeks on posedge.

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

No branches or pull requests

6 participants