Wire assignment to output of Reg does not always work
From @nullromo on November 4, 2018 6:8
Type of issue: bug report
Other information This could be a bug with the firrtl interpreter.
If the current behavior is a bug, please provide the steps to reproduce the problem: Steps to reproduce:
This module is a pared down version of a work in progress, so the actual behavior of the module is irrelevant. The point is that byteOut is assigned to the output of the byteIn register, but the waveform output shows byteOut taking on old values.
import chisel3._
import chisel3.util._
/*
* This module has a problem. It is very sad. When it is run, byteOut is set to always
* byteIn. The output waveform shows times when byteOut is equal to old values of
* byteIn. e.g. byteIn=3, byteOut=2 after 13 steps; or byteIn=7, byteOut=5 after
* 37 steps when running the associated test.
*/
class SadModule extends Module {
val io = IO(new Bundle {
val in = Flipped(Decoupled(Input(UInt(8.W))))
val out = Decoupled(Output(UInt(8.W)))
})
val sAccept :: sSend :: Nil = Enum(2)
val state = RegInit(sAccept)
val byteIn = RegInit(0.U(8.W))
val byteOut = Wire(UInt(8.W))
byteOut := byteIn
when(state === sAccept) {
byteIn := io.in.deq()
io.out.noenq()
when(io.in.fire()) {
state := sSend
}
}.otherwise {
io.in.nodeq()
when(byteIn === 0.U) {
io.out.noenq()
state := sAccept
}.otherwise {
io.out.enq(byteOut)
}
when(io.out.fire()) {
state := sAccept
byteIn := io.in.bits
}
}
}
This is the associated test:
import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
class SadModuleTester(c: SadModule) extends PeekPokeTester(c) {
val input = List(2, 3, 0, 0, 0, 0, 0, 5, 7, 0, 8, 9, 0, 0, 0, 1).map {
_.toByte
}
var output = List[BigInt]()
poke(c.io.out.ready, true)
poke(c.io.in.valid, true)
var i = 0
while (i < input.length) {
poke(c.io.in.bits, input(i))
step(1)
if (peek(c.io.out.valid) != BigInt(0)) {
output = output :+ peek(c.io.out.bits)
i = i + 1
} else if (peek(c.io.in.ready) != BigInt(0)) {
output = output :+ peek(c.io.out.bits)
i = i + 1
}
}
println(input.toString())
println(output.toString())
}
class CompressionTester extends ChiselFlatSpec {
"SadModule" should "fail" in {
Driver.execute(Array("-fiwv", "--backend-name", "firrtl", "--target-dir", "test_run_dir/sad", "--top-name", "sad"), () => new SadModule) {
c => new SadModuleTester(c)
} should be(true)
}
}
Here is a picture of the waveform output:
What is the current behavior?
Wires assigned to certain values do not always take on that value.
What is the expected behavior?
Wires should always asynchronously have the value that they are assigned.
Please tell us about your environment:
- OS: Windows 10
Copied from original issue: freechipsproject/chisel3#925
From @edwardcwang on November 4, 2018 6:11
Does it work with either verilator or treadle?
I do not have verilator installed, and treadle does not produce a vcd, so I cannot immediately answer that.
From @edwardcwang on November 4, 2018 7:42
If you use val args = Array("--backend-name", "treadle", "--tr-write-vcd") you can get treadle to produce VCDs.
Ah yes. Adding dontTouch(byteOut) and using treadle with --tr-write-vcd produced a waveform that looks correct (byteOut always has the same value as byteIn). Does that imply that this is in fact a potential firrtl interpreter bug?
From @edwardcwang on November 4, 2018 20:55
It's possible; I've run into bugs where firrtl-interpreter was doing weird things like this in VCD output. IIRC the plan was for treadle to replace firrtl-interpreter though, so...
Should I migrate this to the firrtl repo then?
From @chick on November 5, 2018 3:11
Migrate to the firrtl-interpreter repo.