chisel icon indicating copy to clipboard operation
chisel copied to clipboard

Inconsistent width for ChiselEnums cast to UInt

Open jackkoenig opened this issue 1 year ago • 0 comments

Type of issue: Bug Report

Please provide the steps to reproduce the problem:

Consider the following Chisel:

//> 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

object MyEnum extends ChiselEnum {
  val e0, e1, e2 = Value

  val e10 = Value(10.U)
}

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

  val x = MyEnum.e1.asUInt
  val y = WireInit(x)
  val z = WireInit(chiselTypeOf(x), x)
  dontTouch(y)
  dontTouch(z)

  out := x
}

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

What is the current behavior?

Running the above gives:

FIRRTL version 3.3.0
circuit Foo :%[[
  {
    "class":"firrtl.transforms.DontTouchAnnotation",
    "target":"~Foo|Foo>y"
  },
  {
    "class":"firrtl.transforms.DontTouchAnnotation",
    "target":"~Foo|Foo>z"
  }
]]
  module Foo : @[Users/koenig/work/t/chiselenum/chisel-example.scala 16:7]
    input clock : Clock @[Users/koenig/work/t/chiselenum/chisel-example.scala 16:7]
    input reset : UInt<1> @[Users/koenig/work/t/chiselenum/chisel-example.scala 16:7]
    output out : UInt<8> @[Users/koenig/work/t/chiselenum/chisel-example.scala 17:15]

    node x = asUInt(UInt<1>(0h1)) @[Users/koenig/work/t/chiselenum/chisel-example.scala 19:21]
    wire y : UInt @[Users/koenig/work/t/chiselenum/chisel-example.scala 20:19]
    connect y, x @[Users/koenig/work/t/chiselenum/chisel-example.scala 20:19]
    wire z : UInt<4> @[Users/koenig/work/t/chiselenum/chisel-example.scala 21:19]
    connect z, x @[Users/koenig/work/t/chiselenum/chisel-example.scala 21:19]
    connect out, x @[Users/koenig/work/t/chiselenum/chisel-example.scala 25:7]
// Generated by CIRCT firtool-1.62.0
module Foo(
  input        clock,
               reset,
  output [7:0] out
);

  wire       y = 1'h1;
  wire [3:0] z = 4'h1;
  assign out = 8'h1;
endmodule

The type Chisel thinks x has and the type it emits into the FIRRTL are inconsistent. At Scala time, it thinks x is a 4-bit UInt (matching the type of the Enum rather than the minimum width needed by the literal for e1). The emitted FIRRTL has x as a 1-bit UInt as that is the minimum width needed to hold 1 bit.

What is the expected behavior?

The values need to be consistent. In my opinion, the correct answer is 4-bit and Chisel needs to emit the correct FIRRTL reflecting that. Regardless though, it needs to be the same for both. This is a very dangerous thing to change, it is similar (but probably less prevalent) to the recent change to the width of shift right: https://github.com/chipsalliance/chisel/pull/3824.

IMO we should change this in Chisel 7 and take a similar approach to #3824, adding an option for users to temporarily restore the old semantic so they can diff the Verilog to see if they are affected.

Please tell us about your environment:

Other Information

What is the use case for changing the behavior?

jackkoenig avatar Jun 10 '24 22:06 jackkoenig