I already asked a similar question for chisel2 in case of C++ backend.
But now I'm using The template example with iotester (peek and poke) with chisel3.
With the following code (can be found on my github project page):
class TapTempoUnitTester(t: TapTempo) extends PeekPokeTester(t) {
private val tptmp = t
def pushbutton(button: Bool) {
poke(button, 0)
step(1)
poke(button, 1)
step(10)
poke(button, 0)
}
val tclk = 10
val tus = 1000/tclk
val tms = 1000*tus
val ts = 1000*tms
//0
pushbutton(tptmp.io.button)
step(2*tms)
//1
pushbutton(tptmp.io.button)
step(1*tms)
//2
pushbutton(tptmp.io.button)
step(1*tms)
}
If I run the testbench with sbt following command :
sbt 'test:runMain taptempo.TapTempoMain --backend-name verilator'
It's launching the testbench and generate a VCD file that can be seen with gtkwave in following directory :
test_run_dir/taptempo.TapTempoMain962904038/TapTempo.vcd
But the timescale in this vcd file is :
$timescale 1ns $end
What is the right way to change this timescale (other than open vcd file an change it directly) ?
I believe there is limited support for modifying VCS flags, but I don't think there is equivalent support for the Verilator backend. You could ask for such support on this issue: https://github.com/freechipsproject/chisel-testers/issues/148
Related
I have imported mockk library in commonTest -> shared module. There are no import errors in the test classes, but when I run the test I get errors like:
Unresolved reference: every
Unresolved reference: mockk
Unresolved reference: verify
in all places where i use mock library methods. What could be the reason for the errors?
example of my test with errors in console:
class DefaultAppPreferenceStorageTest {
val appPreference = mockk<AppPreference>() //Unresolved reference: mockk
val jsonService = mockk<JsonService>() //Unresolved reference: mockk
val jsonKey = "key"
val value = 1
val stringValue = "$value"
val defaultIntValue = Random.nextInt()
val storage = DefaultAppPreferenceStorage(
appPreference,
jsonService
)
inner class PutJsonTest {
#BeforeTest
fun beforeEachTest() {
every { jsonService.mapToString(value) } returns stringValue //Unresolved reference: every
storage.putJson(jsonKey, value)
}
#Test
fun testPutJson() {
verify(verifyBlock = { jsonService.mapToString(value) }) //Unresolved reference: verify
verify(verifyBlock = { appPreference.putString(jsonKey, stringValue) }) //Unresolved reference: verify
}
}
...
}
UPDATE
Dependencies
const val mockk = "1.12.5"
const val mockk = "io.mockk:mockk-common:${Version.mockk}"
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation(ShareTestDependencies.mockk)
implementation(ShareTestDependencies.coroutinesTest)
}
}
I see the mentioned errors (Unresolved reference: every and other) when upgrading from mockk 1.12.5 to 1.13.2. I can work around it by adding a dependency to mockk-jvm (instead of or next to the existing mockk dependency).
<dependency>
<groupId>io.mockk</groupId>
<artifactId>mockk-jvm</artifactId>
<version>${mockk.version}</version>
</dependency>
The problem was addressed earlier (see https://github.com/mockk/mockk/issues/889) and assumed to be solved. Apparently this is not yet so in all cases.
If you are using KMP to build native targets (iOS, Linux, Windows, etc), mockk doesn't support native. It does support JVM and JS, and has a common source definition to support those 2 platforms. The IDE may not have an error because there is a common mockk definition (although I've never tried that).
Look at the test task that's actually being run. If it's for a native target, that's definitely what's happening.
If we run the following Chisel3 code
class Controller extends Module {
val io = IO(new Bundle {
})
val sff = Module(new SFF)
val frame: Vec[UInt] = Reg(Vec(ProcedureSpaceSize, Integer32Bit))
for(i <- 0 until ProcedureSpaceSize)
frame(i) := 99.U
sff.io.inputDataVector := frame
}
class SFF extends Module {
val io = IO(new Bundle {
val inputDataVector: Vec[UInt] = Input(Vec(ProcedureSpaceSize, Integer32Bit))
})
}
in REPL debug mode. First do
reset;step
peek sff.io_inputDataVector_0;peek sff.io_inputDataVector_1;peek sff.io_inputDataVector_2
The REPL returns
Error: exception Error: getValue(sff.io_inputDataVector_0) returns value not found
Error: exception Error: getValue(sff.io_inputDataVector_1) returns value not found
Error: exception Error: getValue(sff.io_inputDataVector_2) returns value not found
Then do
eval sff.io_inputDataVector_0
which will be a success, yielding
...
resolve dependencies
evaluate sff.io_inputDataVector_0 <= frame_0
evaluated sff.io_inputDataVector_0 <= 99.U<32>
Then perform the above peek again
peek sff.io_inputDataVector_0;peek sff.io_inputDataVector_1;peek sff.io_inputDataVector_2;
This time, it returns
peek sff.io_inputDataVector_0 99
peek sff.io_inputDataVector_1 99
peek sff.io_inputDataVector_2 99
which is more expected.
Why does the REPL act in this way? Or was there something I missed? Thanks!
*chisel-iotesters is in version 1.4.2, and chiseltest is in version 0.2.2. Both should be the newest version.
The firrtl interpreter REPL does not necessarily compute or store values that on a branch of a mux that is not used. This can lead to problems noted above like
Error: exception Error: getValue(sff.io_inputDataVector_0) returns value not found.
eval can be used to force unused branches to be evaluated anyway. The REPL is an experimental feature that has not had a lot of use.
treadle is the more modern chisel scala-based simulator. It is better supported and faster than the interpreter. It has a REPL of its own, but does not have an executeFirrtlRepl equivalent.
It must be run from the command line via the ./treadle.sh script in the root directory. One can also run sbt assembly to create a much faster launching jar that is placed in utils/bin. This REPL also has not been used a lot but I am interested on feedback that will make it better and easier to use.
I think the problem that you are seeing is that all your wires are being eliminated due to dead code elimination. There are a couple of things you should try to fix this.
Make sure you have meaningful connections of your wires. Hardware that does not ultimately affect an output is likely to get eliminated. In your example you do not have anything driving a top level output
You probably need your circuit to compute something with those registers. If the registers are initialized to 99 then constant propagation will likely eliminate them. I'm not sure what you are trying to get the circuit to do so it is hard to make a specific recommendation.
If you get the above done I think the repl will work as expected. I do have a question about which repl you are using (there are two: firrtl-interpreter and treadle) I recommend using the latter. It is more modern and better supported. It also has two commands that would be useful
show lofirrtl will show you the lowered firrtl, this is how you can see that lots of stuff from the high firrtl emitted by chisel3 has been changed.
symbol . shows you all symbols in circuit (. is a regex that matches everything.
Here is a somewhat random edit of your circuit that drives and output based on your frame Vec. This circuit will generate firrtl that will not eliminated the wires you are trying to see.
class Controller extends Module {
val io = IO(new Bundle {
val out = Output(UInt(32.W))
})
val sff = Module(new SFF)
val frame: Vec[UInt] = Reg(Vec(ProcedureSpaceSize, Integer32Bit))
when(reset.asBool()) {
for (i <- 0 until ProcedureSpaceSize) {
frame(i) := 99.U
}
}
frame.zipWithIndex.foreach { case (element, index) => element := element + index.U }
sff.io.inputDataVector := frame
io.out := sff.io.outputDataVector.reduce(_ + _)
}
class SFF extends Module {
val io = IO(new Bundle {
val inputDataVector: Vec[UInt] = Input(Vec(ProcedureSpaceSize, Integer32Bit))
val outputDataVector: Vec[UInt] = Output(Vec(ProcedureSpaceSize, Integer32Bit))
})
io.outputDataVector <> io.inputDataVector
}
I would like to test my code, so I'm doing a testbench. I wanted to know if it was possible to check the internal signals -like the value of the state register in this example- or if the peek was available only for the I/O
class MatrixMultiplier(matrixSize : UInt, cellSize : Int) extends Module {
val io = IO(new Bundle {
val writeEnable = Input(Bool())
val bufferSel = Input(Bool())
val writeAddress = Input(UInt(14.W)) //(matrixSize * matrixSize)
val writeData = Input(SInt(cellSize.W))
val readEnable = Input(Bool())
val readAddress = Input(UInt(14.W)) //(matrixSize * matrixSize)
val readReady = Output(Bool())
val readData = Output(SInt((2 * cellSize).W))
})
val s_idle :: s_writeMemA :: s_writeMemB :: s_multiplier :: s_ready :: s_readResult :: Nil = Enum(6)
val state = RegInit(s_idle)
...
and for the testbench :
class MatrixUnitTester(matrixMultiplier: MatrixMultiplier) extends PeekPokeTester(matrixMultiplier) { //(5.asUInt(), 32.asSInt())
println("State is: " + peek(matrixMultiplier.state).toString) // is it possible to have access to state ?
poke(matrixMultiplier.io.writeEnable, true.B)
poke(matrixMultiplier.io.bufferSel, false.B)
step(1)
...
EDIT : Ok, with VCD + GTKWave it is possible to graphically see these variables ;)
Good question. There's several parts to this answer
The Chisel supplied unit testing frameworks older chisel-testers and the newer chiseltest. Do not provide a mechanism to look into the wires directly.
Currently the chisel team is looking into ways of doing that.
Both provide indirect ways of doing it. Writing VCD output and using printf to see internal values
The Treadle firrtl simulator, which can directly simulate a firrtl (the direct output of the Chisel compiler) does allow for peek, and poking any signal directly. There are lots of examples of how its use in Treadle's unit tests. Treadle also provides a REPL shell which can be useful for exploring a circuit with manual peeks and pokes
The older chiseltesters (io-testers) and current chiseltest frameworks allow debugging the signal values with .peek() function that works well for the interface signals.
I haven't found a way to peek() an internal signal while debugging a testcase. However, Treadle simulator can dump the values of internal signals when it is running in verbose mode:
Add the annotation treadle.VerboseAnnotation to the test:
`test(new DecoupledGcd(16)).withAnnotations(Seq(WriteVcdAnnotation, treadle.VerboseAnnotation))`
When debugging in the IDEA and the test stops at breakpoint, the changes in the values of all internal signals up to this point are dumped to the Console.
This example will also generate the VCD wave file for further debugging.
I have a chisel3 module with a data bus IO that can be reinterpreted to some instruction/command
using bundle, aka(in the module):
......
//io.data is for example UInt(64.W)
val cmdInterface = new CommandInterface() // this is a bundle of signals
val cmd = io.data.asTypeof(cmdInterface)
......
I can do the reinterpretation inside Module definition but this is not possible inside the PeekPokeTester:
//using the tester:
poke(c.io.data.asTypeof(cmdInterface).cmd, 1) // this is not ok
the compiling gives:
chisel3.internal.ChiselException: Error: Not in a UserModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox.
at the line of the asTypeOf(xxxx)
So, how to reinterpret IO signals when testing?
This is not a direct answer, but chisel-testers2 is designed to resolve this difficulty. Here is an example from its unit tests BundleLiteralsSpec
it should "roundtrip Bundle literals" in {
test(new PassthroughModule(new DoubleElements)) { c =>
c.in.poke(chiselTypeOf(c.in).Lit(_.a -> 0.U, _.b -> 1.U))
c.in.poke(c.out.peek())
c.out.expect(chiselTypeOf(c.in).Lit(_.a -> 0.U, _.b -> 1.U))
}
}
In this example it is getting the BundleType from the input itself but could as easily be re-written with direct BundleReferences e.g.
c.in.poke((new DoubleElements).Lit(_.a -> 0.U, _.b -> 1.U))
val cmdInterface = Module(new CommandInterface()) // this is a bundle of signals
Try this instead. It should work.
I have a huge message file which i need to split into multiples files for different languages.
For example :
I created one folder for English locale i.e. en and another for French locale , fr inside conf folder.
en contains messages1_en.properties and messages2_en.properties
fr contains messages1_fr.properties and messages2_fr.properties
How to access these properties files inside my view.
Thanks
The only way to do that without introducing your own alternative implementation and use that instead of the built in Messages is to use hacked locales, so you would do fr_type1, fr_type2 or something like that to select the right alternative.
This is probably a bad idea since it's always risky to use an API in a different way from how it was intended to be used, there is a high risk of unexpected behaviour and it might be brittle since there is no guarantee that you will be able to use made up locales in future versions etc.
If you look at the Messages implementation you could probably get some ideas of how to implement your own without much fuss.
Good luck!
That's an old question, but i had a close issue, and i didn't find a solution anywhere.
This example use a configuration key to load messages from a file with a custom name. But you can easily modify it to load messages file from a subdirectory and/or multiple messages files.
Override play.api.i18n.DefaultMessagesApiProvider
#Singleton
class CustomMessagesApiProvider #Inject() (
environment: Environment,
config: Configuration,
langs: Langs,
httpConfiguration: HttpConfiguration)
extends DefaultMessagesApiProvider(environment, config, langs, httpConfiguration) {
def filename =
config.get[String]("play.i18n.filename")
override protected def loadAllMessages: Map[String, Map[String, String]] = {
langs.availables.map(_.code).map { lang =>
(lang, loadMessages(filename +"." + lang))
}.toMap
.+("default" -> loadMessages(filename))
.+("default.play" -> loadMessages(filename+".default"))
}
}
Add Guice binding in Module.java
#Override
public void configure() {
bind(DefaultMessagesApiProvider.class).to(CustomMessagesApiProvider.class);
}
It's my first Scala class, so maybe it can be improved. But it works.
To load multiple files (it compiles but not tested)
override protected def loadAllMessages: Map[String, Map[String, String]] = {
langs.availables.map(_.code).map { lang =>
(lang,
loadMessageFiles("." + lang))
}.toMap
.+("default" -> loadMessageFiles(""))
.+("default.play" -> loadMessageFiles(".default"))
}
private def loadMessageFiles(suffix: String) = {
loadMessages("messages-1" + suffix) ++ loadMessages("messages-2" + suffix)
}