Tuesday, April 18, 2017

PeekPokeTester and LazyModule

In Chisel, it appears that PeekPokeTester doesn't play well with LazyModule.  If ChiselTop is a LazyModule (not Module), the following will not work.

  class ChiselTopTester(c: ChiselTop) extends PeekPokeTester(c) { }

Adding a wrapper class around the LazyModule instance solves the problem.

class ChiselTopTest extends ChiselFlatSpec {

  class ChiselTopTester(c: ChiselTopWrapper) extends PeekPokeTester(c) {
    println("Hello World!")
  }

  // hint from: https://github.com/ucb-bar/rocket-chip/issues/359
  class ChiselTopWrapper(p: Parameters) extends Module {
    val top = Module(LazyModule(new ChiselTop()(p)).module)
    val io = top.io.cloneType
    io <> top.io
  }

  implicit val p: Parameters = new BlankConfig
  chisel3.iotesters.Driver(() => new ChiselTopWrapper(p)) { c => new ChiselTopTester(c) }
}

In other news, my Scala skills are improving...

Friday, April 14, 2017

Parameters and lazy modules

I haven't looked at rocket chip in ~2 years or so.  Wow, did it grow in complexity.  One area where I am lacking familiarily (and where documentation is notably absent) is in the use of TileLink2.  For the purpose of learning and exploration, I'll take it one step at a time and try to connect a single AHB master to an AHB slave using TileLink.

One stumbling block was the use of parameters and lazy modules.  Rocket uses the content dependent environment package for configuring its components.  The project template repo offers some explanation on the use of the cake pattern (design pattern) for allowing configuration to complete before hardware elaboration begins (paraphrasing, here).  Here is another thread that discusses the strategy.

On to some code (module elaboration only) ...

// Define your very own configuration object ...

case object BlankField extends Field[Boolean]

class BlankConfig extends Config((site, here, up) => {
  case BlankField => false
})

// Pay close attention to use of LazyModule and LazyModuleImp ...

object ChiselTopDriver extends App {
  implicit val p: Parameters = new BlankConfig
  chisel3.Driver.execute(args, () => LazyModule(new ChiselTop).module)
}

class ChiselTop()(implicit p: Parameters) extends LazyModule {
  val master = LazyModule(new AHBMaster)
  val slave = LazyModule(new AHBSlave)

  slave.node := master.node // does not work.. yet..

   lazy val module = new LazyModuleImp(this) {
    val io = new Bundle {
      val ddrClock = Input(Clock())
      val ddrReset = Input(UInt(1.W))
    }
  }
}

class AHBMaster()(implicit p: Parameters) extends LazyModule
{
  val node = AHBOutputNode() // does not work.. yet..

  lazy val module = new LazyModuleImp(this) {
    val io = new Bundle {
      val out = node.bundleOut
    }
  }
}

class AHBSlave()(implicit p: Parameters) extends LazyModule
{
  val node = AHBInputNode() // does not work.. yet..

  lazy val module = new LazyModuleImp(this) {
    val io = new Bundle {
      val in = node.bundleIn
    }
  }
}