凿子代码(下面提供)通过了测试并被编译,但是在尝试生成verilog文件时发生错误。
凿子代码:
import chisel3._
import chisel3.core.VecInit
import chisel3.util._
//A n-bit adder with carry in and carry out
class AdderNbit(val n: Int) extends Module {
val io = IO( new Bundle {
val A = Input(UInt(n.W))
val B = Input(UInt(n.W))
val Cin = Input(UInt(1.W))
val Sum = Output(UInt(n.W))
val Cout = Output(UInt(1.W))
})
val FAs = Vec(Seq.fill(n) {Module(new FullAdder()).io })
val carry = Wire(Vec(n+1, UInt(1.W)))
val sum = Wire(Vec(n, Bool()))
carry(0) := io.Cin
for(i <- 0 until n) {
FAs(i).a := io.A(i)
FAs(i).b := io.B(i)
FAs(i).cin := carry(i)
sum(i) := FAs(i).sum.toBool()
carry(i+1) := FAs(i).cout
}
io.Sum := sum.asUInt()
io.Cout := carry(n)
}
//Binary to thermometer code converter
class BinThermConv(n: Int) extends Module {
val io = IO(new Bundle {
val bin = Input(UInt(n.W))
val therm = Output(UInt())
})
val w = (math.pow(2,n).toInt)-1
val x = 0.U(w.W)
val z = Wire(UInt(w.W))
z := (x | ((1.U << io.bin)-1.U))
io.therm := z
}
//4-bit adder with carry in and carry out and coverts sum into thermometer code
class Adder4bit extends Module {
val io = IO(new Bundle {
val A = Input(UInt(4.W))
val B = Input(UInt(4.W))
val Cin = Input(UInt(1.W))
val SumTherm = Output(UInt())
val Cout = Output(UInt(1.W))
})
val Ad = Module(new AdderNbit(4))
Ad.io.A := io.A
Ad.io.B := io.B
Ad.io.Cin := io.Cin
val Btc = Module(new BinThermConv(Ad.n))
Btc.io.bin := Ad.io.Sum
io.SumTherm := Btc.io.therm
io.Cout := Ad.io.Cout
}
测试工具:
import chisel3.iotesters.{PeekPokeTester, Driver, ChiselFlatSpec}
class Adder4bitTests(c: Adder4bit) extends PeekPokeTester(c) {
for (t <- 0 until 1024) {
val rnd0 = rnd.nextInt(16)
val rnd1 = rnd.nextInt(16)
val rnd2 = rnd.nextInt(2)
poke(c.io.A, rnd0)
poke(c.io.B, rnd1)
poke(c.io.Cin, rnd2)
step(1)
val rsum = (rnd0 & 0xF) + (rnd1 & 0xF) + (rnd2 & 0x1)
val rsumTherm = 1 << (rsum & 0xF)
expect(c.io.SumTherm, ((rsumTherm-1) & 0x7FFF))
expect(c.io.Cout, rsum >> 4)
}
}
class Adder4bitTester extends ChiselFlatSpec {
behavior of "Adder4bit"
backends foreach {backend =>
it should s"correctly add randomly generated numbers $backend" in {
Driver(() => new Adder4bit,backend)((c) => new Adder4bitTests(c)) should be (true)
}
}
}
遇到错误:
> test:run-main examples.Launcher Adder4bit --backend-name=verilator
[info] Running examples.Launcher Adder4bit --backend-name=verilator
Starting tutorial Adder4bit
[info] [0.001] Elaborating design...
[info] [0.086] Done elaborating.
Total FIRRTL Compile Time: 345.5 ms
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:347)
at chisel3.internal.firrtl.UnknownWidth.get(IR.scala:183)
at chisel3.core.Data.getWidth(Data.scala:371)
at chisel3.iotesters.VerilatorCppHarnessGenerator$$anonfun$codeGen$2.apply(VerilatorBackend.scala:92)
at chisel3.iotesters.VerilatorCppHarnessGenerator$$anonfun$codeGen$2.apply(VerilatorBackend.scala:90)
at scala.collection.immutable.List.foreach(List.scala:392)
at chisel3.iotesters.VerilatorCppHarnessGenerator$.codeGen(VerilatorBackend.scala:90)
at chisel3.iotesters.setupVerilatorBackend$.apply(VerilatorBackend.scala:247)
at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply$mcZ$sp(Driver.scala:53)
at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply(Driver.scala:38)
at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply(Driver.scala:38)
at logger.Logger$$anonfun$makeScope$1.apply(Logger.scala:129)
at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
at logger.Logger$.makeScope(Logger.scala:127)
at chisel3.iotesters.Driver$$anonfun$execute$1.apply$mcZ$sp(Driver.scala:38)
at chisel3.iotesters.Driver$$anonfun$execute$1.apply(Driver.scala:38)
at chisel3.iotesters.Driver$$anonfun$execute$1.apply(Driver.scala:38)
at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
at chisel3.iotesters.Driver$.execute(Driver.scala:37)
at examples.Launcher$$anonfun$22.apply(Launcher.scala:125)
at examples.Launcher$$anonfun$22.apply(Launcher.scala:124)
at utils.TutorialRunner$$anonfun$apply$2.apply(TutorialRunner.scala:43)
at utils.TutorialRunner$$anonfun$apply$2.apply(TutorialRunner.scala:36)
at scala.collection.immutable.List.foreach(List.scala:392)
at utils.TutorialRunner$.apply(TutorialRunner.scala:36)
at examples.Launcher$.main(Launcher.scala:131)
at examples.Launcher.main(Launcher.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sbt.Run.invokeMain(Run.scala:67)
at sbt.Run.run0(Run.scala:61)
at sbt.Run.sbt$Run$$execute$1(Run.scala:51)
at sbt.Run$$anonfun$run$1.apply$mcV$sp(Run.scala:55)
at sbt.Run$$anonfun$run$1.apply(Run.scala:55)
at sbt.Run$$anonfun$run$1.apply(Run.scala:55)
at sbt.Logger$$anon$4.apply(Logger.scala:84)
at sbt.TrapExit$App.run(TrapExit.scala:248)
at java.lang.Thread.run(Thread.java:748)
================================================================================
Errors: 1: in the following tutorials
Tutorial Adder4bit: exception None.get
================================================================================
Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-1"
java.lang.RuntimeException: Nonzero exit code: 1
at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last test:runMain for the full output.
[error] (test:runMain) Nonzero exit code: 1
[error] Total time: 1 s, completed Jul 15, 2018 10:39:45 AM
在这里,我们试图计算两个4位数字的总和,并将其转换为温度计代码。
我们已经能够隔离问题,看来该错误是由于位宽推断引起的。似乎SumTherm
没有以适当的方式获得位宽,因为Btc.io.therm
也没有明确定义。但是,如果通过以下方式定义端口:val SumTherm = Output(UInt(15.W))
一切正常。
但是应该不会发生此问题,因为val w = ((math.pow(2,n).toInt)-1)
可以为温度计代码计算适当的宽度,并且变量z
,x
的大小应适当。因此Btc.io.therm
应该获得UInt
宽度为w
的值,io.SumTherm
也应该如此。
对这种奇怪行为有任何想法吗?
答案 0 :(得分:1)
感谢您对此问题的详细说明!
这似乎是凿子测试仪中的错误。 Verilog实际上是在生成的,但看来Verilator凿子测试器后端试图获取凿子对象的宽度,这些对象的宽度未如您所述。相反,它应该从生成的FIRRTL中获取宽度,或者至少能够处理未定义宽度的端口。
您介意将所有这些信息作为问题提交到chisel-testers Github repo上,以便该项目的维护者可以看看吗?