Skip to content

Commit

Permalink
Change the verilator generation code to call dut->eval() instead (#252)
Browse files Browse the repository at this point in the history
of dut->_eval_settle(dut->__VlSymsp)
Test in SecondClockDrivesRegisterSpec will only work with this change.
GCDSpec has code to do regression work to make sure
the above change did not significantly slow the verilator simulation.
  • Loading branch information
chick authored Jul 29, 2019
1 parent 8ee288c commit 41f4eef
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 23 deletions.
5 changes: 4 additions & 1 deletion src/main/scala/chisel3/iotesters/VerilatorBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,10 @@ class $dutApiClassName: public sim_api_t<VerilatorDataWrapper*> {
main_time++;
}
virtual inline void update() {
dut->_eval_settle(dut->__VlSymsp);
// This seems to force a full eval of circuit, so registers with alternate clocks are update correctly
dut->eval();
// This was the original call, did not refresh registers when some other clock transitioned
// dut->_eval_settle(dut->__VlSymsp);
}
};

Expand Down
69 changes: 47 additions & 22 deletions src/test/scala/examples/GCDSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import chisel3._
import chisel3.util._
import chisel3.iotesters._
import org.scalatest.{FlatSpec, Matchers}
import treadle.chronometry.Timer

object RealGCD2 {
val num_width = 16
Expand Down Expand Up @@ -54,28 +55,38 @@ class RealGCD2 extends Module {
}
}

class GCDPeekPokeTester(c: RealGCD2) extends PeekPokeTester(c) {
for {
i <- 1 to 10
j <- 1 to 10
} {
val (gcd_value, _) = GCDCalculator.computeGcdResultsAndCycles(i, j)

poke(c.io.RealGCD2in.bits.a, i)
poke(c.io.RealGCD2in.bits.b, j)
poke(c.io.RealGCD2in.valid, 1)

var count = 0
while(peek(c.io.RealGCD2out.valid) == BigInt(0) && count < 20) {
step(1)
count += 1
class GCDPeekPokeTester(c: RealGCD2, maxX: Int = 10, maxY: Int = 10, showTiming: Boolean = false)
extends PeekPokeTester(c) {
val timer = new Timer

timer("overall") {
for {
i <- 1 to maxX
j <- 1 to maxY
} {
val (gcd_value, _) = GCDCalculator.computeGcdResultsAndCycles(i, j)

timer("operation") {
poke(c.io.RealGCD2in.bits.a, i)
poke(c.io.RealGCD2in.bits.b, j)
poke(c.io.RealGCD2in.valid, 1)

var count = 0
while (peek(c.io.RealGCD2out.valid) == BigInt(0) && count < 20000) {
step(1)
count += 1
}
if (count > 30000) {
// println(s"Waited $count cycles on gcd inputs $i, $j, giving up")
System.exit(0)
}
expect(c.io.RealGCD2out.bits, gcd_value)
step(1)
}
}
if(count > 30) {
// println(s"Waited $count cycles on gcd inputs $i, $j, giving up")
System.exit(0)
}
expect(c.io.RealGCD2out.bits, gcd_value)
step(1)
}
if(showTiming) {
println(s"\n${timer.report()}")
}
}

Expand All @@ -95,7 +106,8 @@ class GCDSpec extends FlatSpec with Matchers {
new GCDPeekPokeTester(c)
} should be (true)
}
it should "run firrtl via command line arguments" in {

it should "run firrtl-interpreter via command line arguments" in {
// val args = Array.empty[String]
val args = Array("--backend-name", "firrtl", "--fint-write-vcd")
iotesters.Driver.execute(args, () => new RealGCD2) { c =>
Expand Down Expand Up @@ -138,5 +150,18 @@ class GCDSpec extends FlatSpec with Matchers {

new File("test_run_dir/gcd_make_vcd/RealGCD2.vcd").exists() should be (true)
}

it should "run verilator with larger input vector to run regressions" in {
//
// Use this test combined with changing the comments on VerilatorBackend.scala lines 153 and 155 to
// measure the consequence of that change, at the time of last using this the cost appeared to be < 3%
//
val args = Array("--backend-name", "verilator")
iotesters.Driver.execute(args, () => new RealGCD2) { c =>
new GCDPeekPokeTester(c, 100, 1000, showTiming = true)
} should be (true)
}


}

62 changes: 62 additions & 0 deletions src/test/scala/examples/SecondClockDrivesRegisterSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package examples

import chisel3._
import chisel3.experimental.MultiIOModule
import chisel3.iotesters.PeekPokeTester
import chisel3.util.Counter
import org.scalatest.{FreeSpec, Matchers}


class SecondClockDrivesRegisterSpec extends FreeSpec with Matchers {
class SecondClock extends MultiIOModule {
val inClock = IO(Input(Bool()))
val out = IO(Output(UInt(8.W)))

withClock(inClock.asClock) {
out := Counter(true.B, 8)._1
}
}

class SecondClockTester(c: SecondClock) extends PeekPokeTester(c) {
poke(c.inClock, 0)
expect(c.out, 0)

// Main clock should do nothing
step(1)
expect(c.out, 0)
step(1)
expect(c.out, 0)

// Output should advance on rising edge, even without main clock edge
poke(c.inClock, 1)
expect(c.out, 1)

step(1)
expect(c.out, 1)

// Repeated, 1should do nothing
poke(c.inClock, 1)
expect(c.out, 1)

// and again
poke(c.inClock, 0)
expect(c.out, 1)
poke(c.inClock, 1)
expect(c.out, 2)
}

"poking a clock should flip register" - {

"should work with Treadle" in {
iotesters.Driver.execute(Array(), () => new SecondClock) { c =>
new SecondClockTester(c)
} should be(true)
}

"should work with Verilator" in {
iotesters.Driver.execute(Array("--backend-name", "verilator"), () => new SecondClock) { c =>
new SecondClockTester(c)
} should be(true)
}
}
}

0 comments on commit 41f4eef

Please sign in to comment.