Chisel IO bundle that works for any width for a given Chisel hardware type

46 Views Asked by At

In chisel you can have a hardware generating function like the following:

def hw_func(x: Vec[UInt]) : Vec[UInt] = x  // useless I know

Where the formal argument and return value do not specify the width of the vector(s), meaning the following is valid:

val x4 = Wire(Vec(6, UInt()))
val y4 = Wire(Vec(6, UInt()))

y4 := hw_func(y32)

val x32 = Wire(Vec(32, UInt()))
val y32 = Wire(Vec(32, UInt()))

y32 := hw_func(x32)

However say I have a Module class rather than a function:

class hw_module(widthX: Int, widthY: Int) extends Module {
  val io = IO( new Bundle {
    val x = Input(Vec(widthX, UInt))
    val y = Input(Vec(widthY, UInt))
  })
  y := x
}

I have to use generics to parameterize the input and output, meaning when I instantiate the module class, I have to explicitly pass in width parameters, rather than having the compiler infer the widths as in the case of functions, like so:

val x4 = Wire(Vec(6, UInt()))
val y4 = Wire(Vec(6, UInt()))
val inst4 = hw_module(4, 4)

inst4.io.x := x4
y4 := inst4.io.y

val x32 = Wire(Vec(32, UInt()))
val y32 = Wire(Vec(32, UInt()))
val inst4 = hw_module(32, 32)

inst32.io.x := x32
y4 := inst32.io.y

Which is quite a bit more verbose (especially if say, I have a lot of i/o and they all potentially have different widths!).

Is there a way to achieve the inference of io widths seen in function hw generators with Module classes?

1

There are 1 best solutions below

0
SpaceCowboy max On

You can use type parameter(chisel-doc) to create a more generic modules or bundles

class Foo[T <: Data](gen: T) extends Module {
  val io = IO(new Bundle {
    val x = Input(gen)
    val y = Output(gen)
  })

  io.x <> io.y
}


class Bar extends Module {
  val io = IO(new Bundle {
    val x1 = Input(Vec(6, UInt(32.W)))
    val x2 = Input(UInt(16.W))
    val x3 = Input(Bool())
    val y1 = Output(Vec(6, UInt(32.W)))
    val y2 = Output(UInt(16.W))
    val y3 = Output(Bool())
  })

  val foo1 = Module(new Foo(io.x1.cloneType))
  val foo2 = Module(new Foo(io.x2.cloneType))
  val foo3 = Module(new Foo(io.x3.cloneType))

  io.x1 <> foo1.io.x
  io.x2 <> foo2.io.x
  io.x3 <> foo3.io.x
  
  io.y1 <> foo1.io.y
  io.y2 <> foo2.io.y
  io.y3 <> foo3.io.y 
}