Search code examples
chiselriscv

Conditional port in a Chisel Module


I have a selectable feature which is not normally required. However to support this feature, some I/O ports should be added to the origin Module I/O port.

I am doing it in this way:

import Chisel._

class TestModule extends Module {

  class IOBundle extends Bundle {
    val i = Bool(INPUT)
    val o = Bool(OUTPUT)
  }

  class IOBundle_EXT extends IOBundle {
    val o_ext = Bool(OUTPUT)
  }

  val io = if(true) new IOBundle_EXT else new IOBundle;

  io.o := io.i
  io.o_ext := io.i

}

After running sbt "run TestModule --backend c --compile --test --genHarness", the compiler complains:

[error] xxxx/test/condi_port.scala:17: value o_ext is not a member of TestModule.this.IOBundle
[error]   io.o_ext := io.i
[error]      ^
[error] one error found
[error] (compile:compile) Compilation failed

So the if statement has no effect. val io is still assigned to IOBundle, rather than the extended IOBoundle_EXT, which makes no sense to me.


Solution

  • Chisel now supports Options in IO bundles.

    As an example, I explored Options here (https://github.com/ucb-bar/riscv-boom/commit/da6edcb4b7bec341e31a55567ee04c8a1431d659), but here's a summary:

    class MyBundle extends Bundle
    {
       val my_ext = if (SOME_SWITCH) Some(ExtBundle) else None
    }
    
    ...
    
    io.my_ext match
    {
       case Some(b: ExtBundle) =>
          my_ext.a := Bool(false)
          ...
       case _ => require (!SOME_SWITCH)
    }
    

    It's incredibly verbose, but I was able to get it working even when doing bulk connects and hiding bundles within bundles, etc.