Skip to content

Inconsistent width for ChiselEnums cast to UInt #4159

@jackkoenig

Description

@jackkoenig

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: #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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions