Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bit width inference issue #209

Open
RajKamal1 opened this issue Aug 2, 2018 · 0 comments
Open

Bit width inference issue #209

RajKamal1 opened this issue Aug 2, 2018 · 0 comments

Comments

@RajKamal1
Copy link

RajKamal1 commented Aug 2, 2018

The chisel code (provided below) passes the tests and gets compiled, however there occurs an error when trying to generate the verilog file.

Chisel Code:

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
}

Test Harness:

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)    
    }    
  }    
}

Error encountered:

> 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

Here, we are trying to calculate the sum of two 4-bit numbers, and converting it to thermometer code.

We have been able to isolate the problem, it appears that the error is due to bit-width inference. It seems that SumTherm does not get bit width in a proper way because Btc.io.therm doesn't have it explicitly defined either. If, however, the port is defined in the following way: val SumTherm = Output(UInt(15.W)) everything works great.

But this problem should not have occurred because val w = ((math.pow(2,n).toInt)-1) is there to calculate the appropriate width for thermometer code, and the variables z, x should be of appropriate sizes. So Btc.io.therm should get a UInt value of width w, and so should io.SumTherm.

Any ideas for this strange behavior?

I received the following feedback on stackoverflow: This appears to be a bug in the chisel-testers. Verilog actually is being generated but it appears that the chisel-testers Verilator backend is trying to get the width of the Chisel objects which do not have defined width as you noted. Rather, it should get the widths from the resulting FIRRTL or at least be able to handle ports that don't have defined width.
Link -> https://stackoverflow.com/questions/51537418/bit-width-inference-issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant