freechipsproject / firrtl-interpreter

A scala based simulator for circuits described by a LoFirrtl file
Other
46 stars 23 forks source link

Ivalid Clock interpretation #138

Closed tampler closed 5 years ago

tampler commented 6 years ago

I wanna derive a rising edge event from the Clock() as below:

class RisingEdge () extends Module {
  val io = IO (new Bundle {
  })  
  val ev  = Clock().asUInt  // <---- FAILS HERE
  val risingEdge  = ev & ~RegNext(ev)
}

[info] firrtl.passes.CheckChirrtl$UndeclaredReferenceException: @[Property.scala 26:21:@8.4]: [module RisingEdge] Reference _T_11 is not declared.

jackkoenig commented 6 years ago

Clock() declares a new Clock type, what you want is the implicit Clock from the Module class clock

tampler commented 6 years ago

Thank you Jack, worked fine. Another question is how to output a repetitive event, using this risingEdge. I'd expect to print 5 strings "Event high" with the following code, but instead I get a single print during elaboration. What's wrong with that ?

class RisingEdge () extends Module {
  val io = IO (new Bundle {  
    val a  = Input (Bool())
    val b  = Input (Bool())    
    val out = Output(Bool()) 
  })  
  val ev  = clock.asUInt
  val risingEdge  = ev & ~RegNext(ev)

  when (risingEdge === 1.U) {
    println (s"Event high")
  }

class RisingEdgeTester (c:RisingEdge) extends PeekPokeTester(c) {
  val uut  = c.io  
  reset()
  (0 until 5) foreach { tic =>
    poke(uut.a, 0) 
    poke(uut.b, 0) 
    step(1)    
  }
}
jackkoenig commented 6 years ago

The problem is println which is a Scala elaboration time print, what you what is printf (which corresponds to hardware simulation time; you'll see an $fdisplay in the emitted Verilog)

tampler commented 6 years ago

Haha nice gotcha, thank you. Still doesn't work. I get all zeros on Clock to UInt translation: https://github.com/Neurodyne/chat/blob/58d63a74988bb7007f2805255420eb6d34a1c757/src/test/scala/Property.scala#L29

[info] [0.004] SEED 1541533026699 ev = 0 risingEdge = 0 ev = 0 risingEdge = 0 ev = 0 risingEdge = 0 ev = 0 risingEdge = 0 ev = 0 risingEdge = 0

jackkoenig commented 6 years ago

Oh yeah, the issue is that register updates, printfs, etc. only occur on rising clock edges in Chisel. Thus ~RegNext(clock.asUInt) is a constant since it only updates on the rising edge of the clock (presumably clock.asUInt will always be 1 on rising edges, thus the output of it will always be 0)

chick commented 6 years ago

I agree with @jackkoenig last comment, but there is a difference here with the same unittest run with the verilator backend whose output is

STARTING test_run_dir/gcd.EventSpec592162601/VRisingEdge
[info] [0.002] SEED 1541534068446
[info] [0.013] ev = 1 risingEdge = 0 
[info] [0.015] ev = 1 risingEdge = 0 
[info] [0.016] ev = 1 risingEdge = 0 
[info] [0.017] ev = 1 risingEdge = 0 
[info] [0.017] ev = 1 risingEdge = 0 
Enabling waves..
Exit Code: 0

Any theory on that @jackkoenig

tampler commented 6 years ago

Great, so we have a problem then. SVA has 7 regions for each evaluation. We'll need to sample input signals and the clocking event (a rising edge) before evaluating assertion itself. We'll discuss that.

Check the picture here: https://verificationacademy.com/forums/systemverilog/sva-evaluation