chipsalliance / chisel

Chisel: A Modern Hardware Design Language

Home Page:https://www.chisel-lang.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Calling .pad on Bool results in requirement failure with no explanation

jackkoenig opened this issue · comments

Type of issue: Bug Report

Please provide the steps to reproduce the problem:

Run the following Scala-CLI

//> using scala "2.13.12"
//> using dep "org.chipsalliance::chisel:6.4.0"
//> using plugin "org.chipsalliance:::chisel-plugin:6.4.0"
//> using options "-unchecked", "-deprecation", "-language:reflectiveCalls", "-feature", "-Xcheckinit", "-Xfatal-warnings", "-Ywarn-dead-code", "-Ywarn-unused", "-Ymacro-annotations"

import chisel3._
// _root_ disambiguates from package chisel3.util.circt if user imports chisel3.util._
import _root_.circt.stage.ChiselStage

class Foo extends Module {
  val in = IO(Input(Bool()))
  val out = IO(Output(UInt(8.W)))

  out := in.pad(8)
}

object Main extends App {
  println(
    ChiselStage.emitSystemVerilog(
      gen = new Foo,
      firtoolOpts = Array("-disable-all-randomization", "-strip-debug-info")
    )
  )
}

What is the current behavior?

You will get the following exception:

Exception in thread "main" java.lang.IllegalArgumentException: requirement failed
        at ... ()
        at Foo.$anonfun$new$1(chisel-example.scala:14)
        at chisel3.Data.$anonfun$$colon$eq$1(Data.scala:754)
        at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
        at chisel3.experimental.prefix$.apply(prefix.scala:33)
        at chisel3.Data.$colon$eq(Data.scala:754)
        at Foo.<init>(chisel-example.scala:14)
        at Main$.$anonfun$new$2(chisel-example.scala:20)
        at chisel3.Module$.evaluate(Module.scala:88)
        at chisel3.Module$.do_apply(Module.scala:35)
        at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:52)
        at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1018)
        at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)
        at chisel3.internal.Builder$.buildImpl(Builder.scala:1012)
        at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1003)
        at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)
        at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)
        at logger.Logger$.makeScope(Logger.scala:146)
        at logger.Logger$.makeScope(Logger.scala:133)
        at ... ()
        at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)

What is the expected behavior?

At a bare minimum, this should give a decent error message.

In an ideal world, Bool (a logical type) would not extend UInt (an arithmetic type), because I would think pad should not be defined on Bool at all. With the inheritance relationship, calling .pad on a Bool probably should return a UInt of the padded width, however, .pad in Chisel is defined to return this.type so Bool.pad returns Bool (.this.type). I suspect this was a mistake but it does imply that attemping to pad a Bool beyond 1-bit is illegal.

So in my opinion, the least bad option is to error, but with a reasonable message.

Please tell us about your environment:

Other Information

What is the use case for changing the behavior?

You can work around this with .asTypeOf(UInt(<n>.W)) or .asTypeOf(UInt(1.W)).pad(<n>) instead of just calling .pad(<n>).