Search code examples
scalageneric-programminghdlriscvchisel

Use generic type to turn off logic in datapath (Chisel)


I'm working on a Z-Scale RISCV-processor where I've implemented new functionality and logic into the datapath. I'm wondering if there exist an easy way to "power off" certain parts of the code without using a bunch of if-loops? I would like to make it easy to switch between the regular implementation of the Z-scale processor and the one with extended implementation.

The new logic I've implemented does not replace the main components of the datapath, but rather extends the functionality.


Solution

  • This question really strikes at the heart of what makes Chisel powerful. As a DSL embedded in Scala, you have access to the full power of an object-oriented and functional programming language.

    While I'm not sure of exactly what you're doing, this seems like a good place to use inheritance. You could make a new Module class that extends the datapath Module and adds the additional functionality.

    A toy example:

    import Chisel._
    
    class ParentIO extends Bundle {
      val foo = UInt(width = 32).asInput
      val bar = UInt(width = 32).asOutput
    }
    
    class Parent extends Module {
      // Note the use of lazy val
      // Due to Scala initialization order (http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html)
      //   this cannot be a val
      // Due to quirks of Chisel, this cannot be a def
      lazy val io = new ParentIO
      io.bar := io.foo
    }
    
    class ChildIO extends ParentIO {
      val isOdd = Bool().asOutput
    }
    
    class Child extends Parent {
      override lazy val io = new ChildIO
      io.isOdd := io.foo(0)
    }
    
    // Note use of call-by-name for passing gen
    // Chisel Modules must be constructed within a call to the Module(...) function
    class Top(gen: => Parent) extends Module {
      val dut = Module(gen)
      val io = dut.io.cloneType
      io <> dut.io
    }
    

    Module Top is parameterized by the type of Module it instantiates: Parent or Child. You can thus conditionally instantiate Parent or Child rather than all of the logic that differentiates them. If you want the Child to be overriding certain functionality of the parent, Chisel's last connection semantics allow any connections in the Child to overrule connections in the Parent.