CoreMini / KelvinMini with 128-bit memory config

Change-Id: I813d37358e7c4094c0033db08fcfc1490572a6a0
diff --git a/hdl/chisel/src/kelvin/BUILD b/hdl/chisel/src/kelvin/BUILD
index 9414e08..10ab8c8 100644
--- a/hdl/chisel/src/kelvin/BUILD
+++ b/hdl/chisel/src/kelvin/BUILD
@@ -203,6 +203,9 @@
     verilog_file_path = "CoreMini.sv",
     gen_flags = [
         "--enableFetchL0=False",
+        "--fetchDataBits=128",
+        "--lsuDataBits=128",
+        "--enableVector=False",
         "--moduleName=CoreMini",
     ],
     extra_outs = [
diff --git a/hdl/chisel/src/kelvin/Core.scala b/hdl/chisel/src/kelvin/Core.scala
index d1b803a..b93593e 100644
--- a/hdl/chisel/src/kelvin/Core.scala
+++ b/hdl/chisel/src/kelvin/Core.scala
@@ -119,6 +119,8 @@
       p.fetchDataBits = arg.split("=")(1).toInt
     } else if (arg.startsWith("--enableVector")) {
       p.enableVector = arg.split("=")(1).toBoolean
+    } else if (arg.startsWith("--lsuDataBits")) {
+      p.lsuDataBits = arg.split("=")(1).toInt
     } else if (arg.startsWith("--target-dir")) {
       nextIsTargetDir = true
       chiselArgs = chiselArgs :+ arg
diff --git a/hdl/chisel/src/kelvin/Interfaces.scala b/hdl/chisel/src/kelvin/Interfaces.scala
index 7ba3945..302bb63 100644
--- a/hdl/chisel/src/kelvin/Interfaces.scala
+++ b/hdl/chisel/src/kelvin/Interfaces.scala
@@ -111,7 +111,7 @@
   val write = Output(Bool())
   val addr = Output(UInt((p.lsuAddrBits - (if (bank) 1 else 0)).W))
   val adrx = Output(UInt((p.lsuAddrBits - (if (bank) 1 else 0)).W))
-  val size = Output(UInt((log2Ceil(p.lsuDataBits / 8) + 1).W))
+  val size = Output(UInt(p.dbusSize.W))
   val wdata = Output(UInt(p.lsuDataBits.W))
   val wmask = Output(UInt((p.lsuDataBits / 8).W))
   // Read Phase.
diff --git a/hdl/chisel/src/kelvin/L1DCache.scala b/hdl/chisel/src/kelvin/L1DCache.scala
index fed6e11..6e78791 100644
--- a/hdl/chisel/src/kelvin/L1DCache.scala
+++ b/hdl/chisel/src/kelvin/L1DCache.scala
@@ -42,7 +42,7 @@
   })
 
   assert(p.axi1IdBits == 4)
-  assert(p.axi1DataBits == 256)
+  assert(p.axi1DataBits == 256 || p.axi1DataBits == 128)
 
   val bank0 = Module(new L1DCacheBank(p))
   val bank1 = Module(new L1DCacheBank(p))
@@ -282,8 +282,8 @@
   val bytes = p.lsuDataBits / 8
 
   def Mem8to9(d: UInt, m: UInt): UInt = {
-    assert(d.getWidth == p.lsuDataBits)
-    assert(m.getWidth == p.lsuDataBits / 8)
+    assert(d.getWidth == 256)
+    assert(m.getWidth == 256 / 8)
     val data = Wire(Vec(bytes, UInt(9.W)))
     for (i <- 0 until bytes) {
       data(i) := Cat(m(i), d(7 + i * 8, 0 + i * 8))
@@ -292,7 +292,7 @@
   }
 
   def Mem9to8(d: UInt): UInt = {
-    assert(d.getWidth == p.lsuDataBits * 9 / 8)
+    assert(d.getWidth == 256 * 9 / 8)
     val data = Wire(Vec(bytes, UInt(8.W)))
     for (i <- 0 until bytes) {
       data(i) := d(7 + i * 9, 0 + i * 9)
@@ -301,7 +301,7 @@
   }
 
   def Mem9to1(d: UInt): UInt = {
-    assert(d.getWidth == p.lsuDataBits * 9 / 8)
+    assert(d.getWidth == 256 * 9 / 8)
     val data = Wire(Vec(bytes, UInt(1.W)))
     for (i <- 0 until bytes) {
       data(i) := Cat(d(8 + i * 9))
@@ -324,9 +324,9 @@
       val valid     = Input(Bool())
       val write     = Input(Bool())
       val addr      = Input(UInt(slotBits.W))
-      val wdata     = Input(UInt((p.axi1DataBits * 9 / 8).W))
-      val wmask     = Input(UInt((p.axi1DataBits * 1 / 8).W))
-      val rdata     = Output(UInt((p.axi1DataBits * 9 / 8).W))
+      val wdata     = Input(UInt((256 * 9 / 8).W))
+      val wmask     = Input(UInt((256 * 1 / 8).W))
+      val rdata     = Output(UInt((256 * 9 / 8).W))
       val volt_sel  = Input(Bool())
     })
   }
@@ -682,8 +682,14 @@
   mem.io.write    := rsel && !axiwrite || io.dbus.valid && io.dbus.write && !ractive
   mem.io.addr     := Mux(rsel || axiwrite, replaceIdReg, foundId)
   mem.io.wmask    := Mux(rsel, ~0.U(wmbits.W), io.dbus.wmask)
-  mem.io.wdata    := Mux(rsel, Mem8to9(io.axi.read.data.bits.data, 0.U(wmbits.W)),
-                            Mem8to9(io.dbus.wdata, ~0.U(wmbits.W)))
+  mem.io.wdata    :=
+    Mux(rsel,
+      Mem8to9(
+        Cat(0.U((256 - io.axi.read.data.bits.data.getWidth).W), io.axi.read.data.bits.data),
+        Cat(0.U((32 - wmbits).W), 0.U(wmbits.W))),
+      Mem8to9(
+        Cat(0.U((256 - io.dbus.wdata.getWidth).W), io.dbus.wdata),
+        Cat(0.U((32 - wmbits).W), ~0.U(wmbits.W))))
   mem.io.volt_sel := io.volt_sel
 
 
diff --git a/hdl/chisel/src/kelvin/L1ICache.scala b/hdl/chisel/src/kelvin/L1ICache.scala
index 7f2dedc..ac98d41 100644
--- a/hdl/chisel/src/kelvin/L1ICache.scala
+++ b/hdl/chisel/src/kelvin/L1ICache.scala
@@ -31,11 +31,11 @@
   // A relatively simple cache block. Only one transaction may post at a time.
   // 2^8 * 256  / 8 = 8KiB    4-way  Tag[31,11] + Index[10,5] + Data[4,0]
   assert(p.axi0IdBits == 4)
-  assert(p.axi0DataBits == 256)
+  assert(p.axi0DataBits == 256 || p.axi0DataBits == 128)
 
   val slots = p.l1islots
   val slotBits = log2Ceil(slots)
-  val assoc = 4
+  val assoc = p.l1iassoc
   val sets = slots / assoc
   val setLsb = log2Ceil(p.fetchDataBits / 8)
   val setMsb = log2Ceil(sets) + setLsb - 1
@@ -52,10 +52,10 @@
   })
 
   assert(assoc == 2 ||  assoc == 4 || assoc == 8 || assoc == 16 || assoc == slots)
-  assert(assoc != 2 ||  setLsb == 5 && setMsb == 11 && tagLsb == 12)
-  assert(assoc != 4 ||  setLsb == 5 && setMsb == 10 && tagLsb == 11)
-  assert(assoc != 8 ||  setLsb == 5 && setMsb == 9  && tagLsb == 10)
-  assert(assoc != 16 || setLsb == 5 && setMsb == 8  && tagLsb == 9)
+  assert(assoc != 2 || (setLsb == 5 && setMsb == 11 && tagLsb == 12) || (setLsb == 4 && setMsb == 10 && tagLsb == 11))
+  assert(assoc != 4 || (setLsb == 5 && setMsb == 10 && tagLsb == 11) || (setLsb == 4 && setMsb == 9 && tagLsb == 10))
+  assert(assoc != 8 || (setLsb == 5 && setMsb == 9  && tagLsb == 10) || (setLsb == 4 && setMsb == 8 && tagLsb == 9))
+  assert(assoc != 16 || (setLsb == 5 && setMsb == 8  && tagLsb == 9) || (setLsb == 4 && setMsb == 7 && tagLsb == 8))
   assert(assoc != slots || tagLsb == 5)
 
   class Sram_1rw_256x256 extends BlackBox {
@@ -64,8 +64,8 @@
       val valid    = Input(Bool())
       val write    = Input(Bool())
       val addr     = Input(UInt(slotBits.W))
-      val wdata    = Input(UInt(p.axi0DataBits.W))
-      val rdata    = Output(UInt(p.axi0DataBits.W))
+      val wdata    = Input(UInt(256.W))
+      val rdata    = Output(UInt(256.W))
       val volt_sel = Input(Bool())
     })
   }
@@ -265,7 +265,7 @@
   mem.io.valid    := memread || memwrite
   mem.io.write    := axiready
   mem.io.addr     := Mux(axiready, replaceIdReg, readId)
-  mem.io.wdata    := io.axi.read.data.bits.data
+  mem.io.wdata    := Cat(0.U((256 - p.axi0DataBits).W), io.axi.read.data.bits.data)
   mem.io.volt_sel := io.volt_sel
 }
 
diff --git a/hdl/chisel/src/kelvin/Parameters.scala b/hdl/chisel/src/kelvin/Parameters.scala
index 1d9f8f8..a7f1cf7 100644
--- a/hdl/chisel/src/kelvin/Parameters.scala
+++ b/hdl/chisel/src/kelvin/Parameters.scala
@@ -32,7 +32,16 @@
 
 }
 
-case class Parameters(m: Seq[MemoryRegion] = Seq(), hartId: UInt = 0.U(32.W)) {
+object Parameters {
+  def apply(): Parameters = {
+    return new Parameters()
+  }
+  def apply(m: Seq[MemoryRegion]): Parameters = {
+    return new Parameters(m)
+  }
+}
+
+class Parameters(val m: Seq[MemoryRegion] = Seq(), val hartId: Int = 0) {
   case object Core {
     val tiny = 0
     val little = 1
@@ -75,32 +84,40 @@
   // Scalar Core Fetch bus.
   val fetchAddrBits = 32   // do not change
   var fetchDataBits = 256  // do not change
+  def fetchInstrSlots: Int = {
+    assert(fetchDataBits % 32 == 0)
+    assert(instructionBits % 32 == 0)
+    assert(fetchDataBits % instructionBits == 0)
+    fetchDataBits / instructionBits
+  }
 
   // Scalar Core Load Store Unit bus.
   val lsuAddrBits = 32  // do not change
-  val lsuDataBits = vectorBits
+  var lsuDataBits = vectorBits
+  def dbusSize: Int = { log2Ceil(lsuDataBits / 8) + 1 }
 
   // [External] Core AXI interface.
   val axiSysIdBits = 7
   val axiSysAddrBits = 32
-  val axiSysDataBits = vectorBits
+  def axiSysDataBits: Int = { lsuDataBits }
 
   // [Internal] L1ICache interface.
   val l1islots = 256
+  val l1iassoc = 4
   val axi0IdBits = 4  // (1x banks, 4 bits unused)
   val axi0AddrBits = 32
-  val axi0DataBits = fetchDataBits
+  def axi0DataBits: Int = { fetchDataBits }
 
   // [Internal] L1DCache interface.
   val l1dslots = 256  // (x2 banks)
   val axi1IdBits = 4  // (x2 banks, 3 bits unused)
   val axi1AddrBits = 32
-  val axi1DataBits = vectorBits
+  def axi1DataBits: Int = { lsuDataBits } /* axiSysDataBits */ /* vectorBits */
 
   // [Internal] TCM[Vector,Scalar] interface.
   val axi2IdBits = 6
   val axi2AddrBits = 32
-  val axi2DataBits = vectorBits
+  def axi2DataBits: Int = { lsuDataBits } // vectorBits
 }
 
 import scala.reflect.runtime.{universe => ru}
@@ -134,6 +151,9 @@
         builder = builder.append(s"#define KP_${x.name} ${value}\n")
       }
     }
+    // TODO(atv): See if we can improve the reflection above to execute
+    // the methods for our dynamic parameters.
+    builder = builder.append(s"#define KP_dbusSize ${p.dbusSize}\n")
     builder = builder.append("#endif\n")
     builder.result()
   }
diff --git a/hdl/chisel/src/kelvin/scalar/Csr.scala b/hdl/chisel/src/kelvin/scalar/Csr.scala
index 21b7d960..d6e2edb 100644
--- a/hdl/chisel/src/kelvin/scalar/Csr.scala
+++ b/hdl/chisel/src/kelvin/scalar/Csr.scala
@@ -131,7 +131,7 @@
   val mscratch  = RegInit(0.U(32.W))
   val mepc      = RegInit(0.U(32.W))
 
-  val mhartid   = RegInit(p.hartId)
+  val mhartid   = RegInit(p.hartId.U(32.W))
 
   val mcycle    = RegInit(0.U(64.W))
   val minstret  = RegInit(0.U(64.W))
diff --git a/hdl/chisel/src/kelvin/scalar/UncachedFetch.scala b/hdl/chisel/src/kelvin/scalar/UncachedFetch.scala
index 0424897..797aab5 100644
--- a/hdl/chisel/src/kelvin/scalar/UncachedFetch.scala
+++ b/hdl/chisel/src/kelvin/scalar/UncachedFetch.scala
@@ -21,7 +21,7 @@
 
 class PredecodeOutput(p: Parameters) extends Bundle {
     val addr = UInt(p.fetchAddrBits.W)
-    val inst = Vec(8, UInt(p.instructionBits.W))
+    val inst = Vec(p.fetchInstrSlots, UInt(p.instructionBits.W))
     val startIdx = UInt(3.W)
     val count = UInt(4.W)
     val nextPc = UInt(p.instructionBits.W)
@@ -29,7 +29,7 @@
 
 class FetchResponse(p: Parameters) extends Bundle {
     val addr = UInt(p.fetchAddrBits.W)
-    val inst = Vec(8, UInt(p.instructionBits.W))
+    val inst = Vec(p.fetchInstrSlots, UInt(p.instructionBits.W))
 }
 
 class Instruction(p: Parameters) extends Bundle {
@@ -56,7 +56,7 @@
   io.fetch.valid := ibusCmd.valid
   io.fetch.bits.addr := Mux(ibusCmd.valid, ibusCmd.bits, 0.U)
   val data = Mux(ibusCmd.valid, io.ibus.rdata, 0.U)
-  for (i <- 0 until 8) {
+  for (i <- 0 until p.fetchInstrSlots) {
     val offset = p.instructionBits * i
     io.fetch.bits.inst(i) := data(offset + p.instructionBits - 1, offset)
   }
@@ -67,7 +67,8 @@
   ctrlAddr := Mux(io.ctrl.valid || ctrlValid && !io.ibus.ready,
     ctrlAddr, io.ctrl.bits
   )
-  val lsb = log2Ceil(p.fetchAddrBits)
+  val lsb = log2Ceil(p.fetchDataBits / 8)
+  assert((p.fetchDataBits == 128 && lsb == 4) || (p.fetchDataBits == 256 && lsb == 5))
   io.ibus.valid := io.ctrl.valid
   io.ibus.addr := Cat(io.ctrl.bits(p.fetchAddrBits - 1, lsb), 0.U(lsb.W))
   io.ctrl.ready := io.ibus.ready
@@ -87,7 +88,7 @@
         val ibusFired = Input(Bool())
 
         val fetchAddr = Decoupled(UInt(p.fetchAddrBits.W))
-        val bufferRequest = DecoupledVectorIO(new FetchInstruction(p), 8)
+        val bufferRequest = DecoupledVectorIO(new FetchInstruction(p), p.fetchInstrSlots)
     })
 
     def PredictJump(addr: UInt, inst: UInt): ValidIO[UInt] = {
@@ -106,12 +107,13 @@
     }
 
     def Predecode(fetchResponse: FetchResponse): (PredecodeOutput, Vec[Bool]) = {
-      val insts = (0 until 8).map(i => fetchResponse.inst(i))
+      val insts = (0 until p.fetchInstrSlots).map(i => fetchResponse.inst(i))
       val addr = fetchResponse.addr
-      val lsb = log2Ceil(p.fetchAddrBits)
+      val lsb = log2Ceil(p.fetchDataBits / 8)
+      assert((p.fetchDataBits == 128 && lsb == 4) || (p.fetchDataBits == 256 && lsb == 5))
       val baseAddr = addr(p.fetchAddrBits - 1, lsb)
-      val startElem = addr(lsb - 1, lsb - 3)
-      val addrs = (0 until 8).map(i => Cat(baseAddr, i.U(3.W), 0.U(2.W)))
+      val startElem = addr(lsb - 1, lsb - log2Ceil(p.fetchInstrSlots))
+      val addrs = (0 until p.fetchInstrSlots).map(i => Cat(baseAddr, i.U((lsb - 2).W), 0.U(2.W)))
 
       val branchTargets = (addrs zip insts).map {
           case (addr, inst) => {
@@ -120,23 +122,23 @@
           }
       }
 
-      val jumped = Wire(Vec(8, Bool()))
-      for (i <- 0 until 8) {
+      val jumped = Wire(Vec(p.fetchInstrSlots, Bool()))
+      for (i <- 0 until p.fetchInstrSlots) {
         val validInst = i.U >= startElem
         jumped(i) := validInst && branchTargets(i).valid
       }
 
-      val lastInstIdx = MuxCase(8.U, (0 until 8).map(i => jumped(i) -> i.U))
+      val lastInstIdx = MuxCase(p.fetchInstrSlots.U, (0 until p.fetchInstrSlots).map(i => jumped(i) -> i.U))
       val nextFetchPc = MuxCase(Cat(baseAddr + 1.U, 0.U(lsb.W)),
-          (0 until 8).map(i => jumped(i) -> branchTargets(i).bits))
+          (0 until p.fetchInstrSlots).map(i => jumped(i) -> branchTargets(i).bits))
 
-      val startElemW = Wire(UInt(3.W))
+      val startElemW = Wire(UInt(log2Ceil(p.fetchInstrSlots).W))
       startElemW := startElem
       val result = Wire(new PredecodeOutput(p))
       result.addr := Cat(baseAddr, 0.U(lsb.W))
       result.inst := insts
       result.startIdx := startElemW
-      result.count := Mux(lastInstIdx === 8.U,
+      result.count := Mux(lastInstIdx === p.fetchInstrSlots.U,
                           lastInstIdx - startElem,
                           lastInstIdx + 1.U - startElem)
       result.nextPc := nextFetchPc
@@ -147,29 +149,29 @@
     val pc = Reg(Valid(UInt(p.fetchAddrBits.W)))
 
     val (predecode, jumped) = Predecode(io.fetchData.bits)
-    var predecodeValids = (0 until 8).map(i =>
+    var predecodeValids = (0 until p.fetchInstrSlots).map(i =>
         i.U >= predecode.startIdx && i.U < (predecode.startIdx +& predecode.count)
     )
-    for (i <- 0 until 8) {
+    for (i <- 0 until p.fetchInstrSlots) {
         val selectHot = PrioritySelect(predecodeValids)
         io.bufferRequest.bits(i).addr :=
           MuxCase(0.U(p.fetchAddrBits.W),
-                  (0 until 8).map(x => selectHot(x) -> (predecode.addr + (4 * x).U)))
+                  (0 until p.fetchInstrSlots).map(x => selectHot(x) -> (predecode.addr + (4 * x).U)))
         io.bufferRequest.bits(i).inst :=
           MuxCase(0.U(p.instructionBits.W),
-                  (0 until 8).map(x => selectHot(x) -> predecode.inst(x)))
+                  (0 until p.fetchInstrSlots).map(x => selectHot(x) -> predecode.inst(x)))
         io.bufferRequest.bits(i).brchFwd :=
           MuxCase(false.B,
-                  (0 until 8).map(x => selectHot(x) -> jumped(x)))
+                  (0 until p.fetchInstrSlots).map(x => selectHot(x) -> jumped(x)))
         predecodeValids = VecInit((predecodeValids zip selectHot).map({case (p, s) => p && !s}))
     }
 
-    // We can fill up to 8 elements in the instruction buffer from each ibus
+    // We can fill up to p.fetchInstrSlots elements in the instruction buffer from each ibus
     // request. Use number of elements ready as a back-pressure signal.
     val fetchValid = !io.branch.valid &&
                           !reset.asBool &&
                           pc.valid &&
-                          (io.bufferRequest.nReady >= 8.U)
+                          (io.bufferRequest.nReady >= p.fetchInstrSlots.U)
     val fetch = Reg(Valid(UInt(p.fetchAddrBits.W)))
     fetch := Mux(io.ibusFired,
                  MakeValid(false.B, 0.U(p.fetchAddrBits.W)),
@@ -225,7 +227,7 @@
 
   val window = 16
   val instructionBuffer = Module(new InstructionBuffer(
-      new FetchInstruction(p), 8, window, true))
+      new FetchInstruction(p), p.fetchInstrSlots, window, true))
   instructionBuffer.io.feedIn <> ctrl.io.bufferRequest
   io.inst.lanes <> instructionBuffer.io.out.take(4)
   instructionBuffer.io.flush.get := io.iflush.valid || branch.valid
diff --git a/hdl/chisel/src/matcha/Axi2Sram.scala b/hdl/chisel/src/matcha/Axi2Sram.scala
index 934d8a0..1840ae8 100644
--- a/hdl/chisel/src/matcha/Axi2Sram.scala
+++ b/hdl/chisel/src/matcha/Axi2Sram.scala
@@ -38,12 +38,12 @@
       None
     }
     // Scalar DBus
-    val in1 = Flipped(new AxiMasterIO(p.axiSysAddrBits, p.axiSysDataBits, p.axiSysIdBits))
+    val in1 = Flipped(new AxiMasterIO(p.axiSysAddrBits, p.axi2DataBits, p.axiSysIdBits))
     // L1DCache
-    val in2 = Flipped(new AxiMasterIO(p.axiSysAddrBits, p.axiSysDataBits, p.axiSysIdBits))
+    val in2 = Flipped(new AxiMasterIO(p.axiSysAddrBits, p.axi1DataBits, p.axiSysIdBits))
     // L1ICache
     val in3 = new Bundle {
-      val read = Flipped(new AxiMasterReadIO(p.axiSysAddrBits, p.axiSysDataBits, p.axiSysIdBits))
+      val read = Flipped(new AxiMasterReadIO(p.axiSysAddrBits, p.axi0DataBits, p.axiSysIdBits))
     }
     // SRAM port
     val out = new CrossbarIO(p.axiSysAddrBits, p.axiSysDataBits, p.axiSysIdBits)
@@ -51,11 +51,11 @@
 
   assert(p.axiSysIdBits == 7)
   assert(p.axiSysAddrBits == 32)
-  assert(p.axiSysDataBits == 256)
+  assert(p.axiSysDataBits == 256 || p.axiSysDataBits == 128)
   assert(p.vectorBits == 256)
-  assert(p.axi0DataBits == 256)
-  assert(p.axi1DataBits == 256)
-  assert(p.axi2DataBits == 256)
+  assert(p.axi0DataBits == 256 || p.axi0DataBits == 128)
+  assert(p.axi1DataBits == 256 || p.axi1DataBits == 128)
+  assert(p.axi2DataBits == 256 || p.axi2DataBits == 128)
 
   def Decode(i: Int, id: UInt): Bool = {
     assert(id.getWidth == 7)
@@ -221,7 +221,7 @@
   }
 
   for (x <- readInterfaces) {
-    assert(!(x.data.valid && !x.data.ready))
+    assert(!x.data.valid || x.data.ready)
   }
 
   assert(!(cctrl.io.in.valid && cctrl.io.in.ready && cctrl.io.in.bits.cwrite && !wdata.io.in.valid))
diff --git a/hdl/chisel/src/matcha/BUILD b/hdl/chisel/src/matcha/BUILD
index 0b79dda..30fe3ef 100644
--- a/hdl/chisel/src/matcha/BUILD
+++ b/hdl/chisel/src/matcha/BUILD
@@ -42,6 +42,9 @@
         "//hdl/verilog:sram_1rw_256x256",
         "//hdl/verilog:sram_1rw_256x288",
     ],
+    extra_outs = [
+        "VKelvin_parameters.h",
+    ],
 )
 
 chisel_cc_library(
@@ -59,6 +62,9 @@
         "--enableVector=False",
         "--moduleName=KelvinScalar",
     ],
+    extra_outs = [
+        "VKelvinScalar_parameters.h",
+    ],
 )
 
 chisel_cc_library(
@@ -74,8 +80,14 @@
     verilog_file_path = "KelvinMini.sv",
     gen_flags = [
         "--enableFetchL0=False",
+        "--fetchDataBits=128",
+        "--lsuDataBits=128",
+        "--enableVector=False",
         "--moduleName=KelvinMini",
     ],
+    extra_outs = [
+        "VKelvinMini_parameters.h",
+    ],
 )
 
 chisel_cc_library(
diff --git a/hdl/chisel/src/matcha/Kelvin.scala b/hdl/chisel/src/matcha/Kelvin.scala
index fcb9e81..23745ae 100644
--- a/hdl/chisel/src/matcha/Kelvin.scala
+++ b/hdl/chisel/src/matcha/Kelvin.scala
@@ -19,6 +19,8 @@
 
 import bus.KelvinMemIO
 import common._
+import java.nio.file.{Paths, Files, StandardOpenOption}
+import java.nio.charset.{StandardCharsets}
 import _root_.circt.stage.ChiselStage
 
 object Kelvin {
@@ -142,19 +144,50 @@
 
 object EmitKelvin extends App {
   val p = new kelvin.MatchaParameters
+  val core_p = new kelvin.Parameters
   var moduleName = "Kelvin"
   var chiselArgs = List[String]()
+  var targetDir: Option[String] = None
+  var nextIsTargetDir = false
   for (arg <- args) {
+    if (nextIsTargetDir) {
+      nextIsTargetDir = false
+      chiselArgs = chiselArgs :+ arg
+      targetDir = Some(arg)
+    }
     if (arg.startsWith("--enableFetchL0")) {
-      p.enableFetchL0 = arg.split("=")(1).toBoolean
+      val argval = arg.split("=")(1).toBoolean
+      p.enableFetchL0 = argval
+      core_p.enableFetchL0 = argval
     } else if (arg.startsWith("--moduleName")) {
       moduleName = arg.split("=")(1)
     } else if (arg.startsWith("--enableVector")) {
-      p.enableVector = arg.split("=")(1).toBoolean
+      val argval = arg.split("=")(1).toBoolean
+      p.enableVector = argval
+      core_p.enableVector = argval
+    } else if (arg.startsWith("--fetchDataBits")) {
+      val argval = arg.split("=")(1).toInt
+      p.fetchDataBits = argval
+      core_p.fetchDataBits = argval
+    } else if (arg.startsWith("--lsuDataBits")) {
+      val argval = arg.split("=")(1).toInt
+      p.lsuDataBits = argval
+      core_p.lsuDataBits = argval
+    } else if (arg.startsWith("--target-dir")) {
+      nextIsTargetDir = true
+      chiselArgs = chiselArgs :+ arg
     } else {
       chiselArgs = chiselArgs :+ arg
     }
   }
   ChiselStage.emitSystemVerilogFile(
     new Kelvin(p, moduleName), chiselArgs.toArray)
+  val header_str = kelvin.EmitParametersHeader(core_p)
+  targetDir match {
+    case Some(targetDir) => {
+      var ret = Files.write(Paths.get(targetDir + "/V" + moduleName + "_parameters.h"), header_str.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE)
+      ()
+    }
+    case None => ()
+  }
 }
diff --git a/hdl/chisel/src/matcha/MatchaParameters.scala b/hdl/chisel/src/matcha/MatchaParameters.scala
index 7b5e6cf..55034b7 100644
--- a/hdl/chisel/src/matcha/MatchaParameters.scala
+++ b/hdl/chisel/src/matcha/MatchaParameters.scala
@@ -18,7 +18,7 @@
 import chisel3.util._
 
 class MatchaParameters(m: Seq[MemoryRegion] = Seq(),
-        hartId: UInt = 2.U(32.W)) extends Parameters(m) {
+        hartId: Int = 2) extends Parameters(m, hartId) {
 
   // Debug
   // tl_main_pkg::ADDR_SPACE_DBG + dm::HaltAddress
diff --git a/tests/verilator_sim/BUILD b/tests/verilator_sim/BUILD
index b67e15f..c2390c1 100644
--- a/tests/verilator_sim/BUILD
+++ b/tests/verilator_sim/BUILD
@@ -110,6 +110,7 @@
     srcs = [
         "matcha/kelvin_if.h",
         "matcha/kelvin_tb.cc",
+        "@kelvin_hw//hdl/chisel/src/matcha:VKelvin_parameters.h",
     ],
     defines = [
         "VERILATOR_MODEL=VKelvin",
@@ -129,6 +130,7 @@
     srcs = [
         "matcha/kelvin_if.h",
         "matcha/kelvin_tb.cc",
+        "@kelvin_hw//hdl/chisel/src/matcha:VKelvinScalar_parameters.h",
     ],
     defines = [
         "VERILATOR_MODEL=VKelvinScalar",
@@ -148,6 +150,7 @@
     srcs = [
         "matcha/kelvin_if.h",
         "matcha/kelvin_tb.cc",
+        "@kelvin_hw//hdl/chisel/src/matcha:VKelvinMini_parameters.h",
     ],
     defines = [
         "VERILATOR_MODEL=VKelvinMini",
diff --git a/tests/verilator_sim/kelvin/core_if.h b/tests/verilator_sim/kelvin/core_if.h
index 1709f4b..ba7c5da 100644
--- a/tests/verilator_sim/kelvin/core_if.h
+++ b/tests/verilator_sim/kelvin/core_if.h
@@ -62,17 +62,17 @@
   sc_in<bool>         io_ibus_valid;
   sc_out<bool>        io_ibus_ready;
   sc_in<sc_bv<32> >   io_ibus_addr;
-  sc_out<sc_bv<256> > io_ibus_rdata;
+  sc_out<sc_bv<KP_fetchDataBits> > io_ibus_rdata;
 
   sc_in<bool> io_dbus_valid;
   sc_out<bool> io_dbus_ready;
   sc_in<bool> io_dbus_write;
   sc_in<sc_bv<32> > io_dbus_addr;
   sc_in<sc_bv<32> > io_dbus_adrx;
-  sc_in<sc_bv<kDbusBits> > io_dbus_size;
-  sc_in<sc_bv<kVector> > io_dbus_wdata;
-  sc_in<sc_bv<kVector / 8> > io_dbus_wmask;
-  sc_out<sc_bv<kVector> > io_dbus_rdata;
+  sc_in<sc_bv<KP_dbusSize> > io_dbus_size;
+  sc_in<sc_bv<KP_lsuDataBits> > io_dbus_wdata;
+  sc_in<sc_bv<KP_lsuDataBits / 8> > io_dbus_wmask;
+  sc_out<sc_bv<KP_lsuDataBits> > io_dbus_rdata;
 
 #if KP_enableVector
   sc_out<bool> io_axi0_write_addr_ready;
@@ -81,8 +81,8 @@
   sc_in<sc_bv<kUncId> > io_axi0_write_addr_bits_id;
   sc_out<bool> io_axi0_write_data_ready;
   sc_in<bool> io_axi0_write_data_valid;
-  sc_in<sc_bv<kUncBits> > io_axi0_write_data_bits_data;
-  sc_in<sc_bv<kUncStrb> > io_axi0_write_data_bits_strb;
+  sc_in<sc_bv<KP_lsuDataBits> > io_axi0_write_data_bits_data;
+  sc_in<sc_bv<KP_lsuDataBits/8> > io_axi0_write_data_bits_strb;
   sc_in<bool> io_axi0_write_resp_ready;
   sc_out<bool> io_axi0_write_resp_valid;
   sc_out<sc_bv<kUncId> > io_axi0_write_resp_bits_id;
@@ -95,7 +95,7 @@
   sc_out<bool> io_axi0_read_data_valid;
   sc_out<sc_bv<2> > io_axi0_read_data_bits_resp;
   sc_out<sc_bv<kUncId> > io_axi0_read_data_bits_id;
-  sc_out<sc_bv<kUncBits> > io_axi0_read_data_bits_data;
+  sc_out<sc_bv<KP_lsuDataBits> > io_axi0_read_data_bits_data;
 #endif  // KP_enableVector
   sc_out<bool> io_axi1_write_addr_ready;
   sc_in<bool> io_axi1_write_addr_valid;
@@ -103,8 +103,8 @@
   sc_in<sc_bv<kUncId> > io_axi1_write_addr_bits_id;
   sc_out<bool> io_axi1_write_data_ready;
   sc_in<bool> io_axi1_write_data_valid;
-  sc_in<sc_bv<kUncBits> > io_axi1_write_data_bits_data;
-  sc_in<sc_bv<kUncStrb> > io_axi1_write_data_bits_strb;
+  sc_in<sc_bv<KP_lsuDataBits> > io_axi1_write_data_bits_data;
+  sc_in<sc_bv<KP_lsuDataBits/8> > io_axi1_write_data_bits_strb;
   sc_in<bool> io_axi1_write_resp_ready;
   sc_out<bool> io_axi1_write_resp_valid;
   sc_out<sc_bv<kUncId> > io_axi1_write_resp_bits_id;
@@ -117,10 +117,10 @@
   sc_out<bool> io_axi1_read_data_valid;
   sc_out<sc_bv<2> > io_axi1_read_data_bits_resp;
   sc_out<sc_bv<kUncId> > io_axi1_read_data_bits_id;
-  sc_out<sc_bv<kUncBits> > io_axi1_read_data_bits_data;
+  sc_out<sc_bv<KP_lsuDataBits> > io_axi1_read_data_bits_data;
 
   Core_if(sc_module_name n, const char* bin) : Memory_if(n, bin) {
-    for (int i = 0; i < kUncBits / 32; ++i) {
+    for (int i = 0; i < KP_lsuDataBits / 32; ++i) {
       runused_.set_word(i, 0);
     }
   }
@@ -177,14 +177,14 @@
 
       // Data bus read.
       if (io_dbus_valid && io_dbus_ready && !io_dbus_write) {
-        sc_bv<kVector> rdata;
+        sc_bv<KP_lsuDataBits> rdata;
         uint32_t addr = io_dbus_addr.read().get_word(0);
-        uint32_t words[kVector / 32] = {0};
+        uint32_t words[KP_lsuDataBits / 32] = {0};
         memset(words, 0xcc, sizeof(words));
         int bytes = io_dbus_size.read().get_word(0);
         Read(addr, bytes, reinterpret_cast<uint8_t*>(words));
-        ReadSwizzle(addr, kVector / 8, reinterpret_cast<uint8_t*>(words));
-        for (int i = 0; i < kVector / 32; ++i) {
+        ReadSwizzle(addr, KP_lsuDataBits / 8, reinterpret_cast<uint8_t*>(words));
+        for (int i = 0; i < KP_lsuDataBits / 32; ++i) {
           rdata.set_word(i, words[i]);
         }
         io_dbus_rdata = rdata;
@@ -192,30 +192,30 @@
 
       // Data bus write.
       if (io_dbus_valid && io_dbus_ready && io_dbus_write) {
-        sc_bv<kVector> wdata = io_dbus_wdata;
+        sc_bv<KP_lsuDataBits> wdata = io_dbus_wdata;
         uint32_t addr = io_dbus_addr.read().get_word(0);
-        uint32_t words[kVector / 32];
+        uint32_t words[KP_lsuDataBits / 32];
         int bytes = io_dbus_size.read().get_word(0);
-        for (int i = 0; i < kVector / 32; ++i) {
+        for (int i = 0; i < KP_lsuDataBits / 32; ++i) {
           words[i] = wdata.get_word(i);
         }
-        WriteSwizzle(addr, kVector / 8, reinterpret_cast<uint8_t*>(words));
+        WriteSwizzle(addr, KP_lsuDataBits / 8, reinterpret_cast<uint8_t*>(words));
         Write(addr, bytes, reinterpret_cast<uint8_t*>(words));
       }
 
       rtcm_t tcm_read;
-      sc_bv<kUncBits> rdata;
+      sc_bv<KP_lsuDataBits> rdata;
 
 #if KP_enableVector
       // axi0 read.
       if (io_axi0_read_addr_valid && io_axi0_read_addr_ready) {
         uint32_t addr = io_axi0_read_addr_bits_addr.read().get_word(0);
-        uint32_t words[kUncBits / 32];
-        Read(addr, kUncBits / 8, reinterpret_cast<uint8_t*>(words));
+        uint32_t words[KP_lsuDataBits / 32];
+        Read(addr, KP_lsuDataBits / 8, reinterpret_cast<uint8_t*>(words));
 
         tcm_read.cycle = cycle_;
         tcm_read.id = io_axi0_read_addr_bits_id.read().get_word(0);
-        for (int i = 0; i < kUncBits / 32; ++i) {
+        for (int i = 0; i < KP_lsuDataBits / 32; ++i) {
           tcm_read.data.set_word(i, words[i]);
         }
         rtcm_[0].write(tcm_read);
@@ -236,15 +236,15 @@
       // axi0 write.
       if (io_axi0_write_addr_valid && io_axi0_write_addr_ready) {
         assert(io_axi0_write_data_valid && io_axi0_write_data_valid);
-        uint8_t wdata[kUncBits / 8];
+        uint8_t wdata[KP_lsuDataBits / 8];
         uint32_t addr = io_axi0_write_addr_bits_addr.read().get_word(0);
         uint32_t* p_wdata = reinterpret_cast<uint32_t*>(wdata);
 
-        for (int i = 0; i < kUncBits / 32; ++i) {
+        for (int i = 0; i < KP_lsuDataBits / 32; ++i) {
           p_wdata[i] = io_axi0_write_data_bits_data.read().get_word(i);
         }
 
-        for (int i = 0; i < kUncBits / 8; ++i) {
+        for (int i = 0; i < KP_lsuDataBits / 8; ++i) {
           if (io_axi0_write_data_bits_strb.read().get_bit(i) != 0) {
             Write(addr + i, 1, wdata + i);
           }
@@ -260,12 +260,12 @@
       // axi1 read.
       if (io_axi1_read_addr_valid && io_axi1_read_addr_ready) {
         uint32_t addr = io_axi1_read_addr_bits_addr.read().get_word(0);
-        uint32_t words[kUncBits / 32];
-        Read(addr, kUncBits / 8, reinterpret_cast<uint8_t*>(words));
+        uint32_t words[KP_lsuDataBits / 32];
+        Read(addr, KP_lsuDataBits / 8, reinterpret_cast<uint8_t*>(words));
 
         tcm_read.cycle = cycle_;
         tcm_read.id = io_axi1_read_addr_bits_id.read().get_word(0);
-        for (int i = 0; i < kUncBits / 32; ++i) {
+        for (int i = 0; i < KP_lsuDataBits / 32; ++i) {
           tcm_read.data.set_word(i, words[i]);
         }
         rtcm_[1].write(tcm_read);
@@ -286,15 +286,15 @@
       // axi1 write.
       if (io_axi1_write_addr_valid && io_axi1_write_addr_ready) {
         assert(io_axi1_write_data_valid && io_axi1_write_data_valid);
-        uint8_t wdata[kUncBits / 8];
+        uint8_t wdata[KP_lsuDataBits / 8];
         uint32_t addr = io_axi1_write_addr_bits_addr.read().get_word(0);
         uint32_t* p_wdata = reinterpret_cast<uint32_t*>(wdata);
 
-        for (int i = 0; i < kUncBits / 32; ++i) {
+        for (int i = 0; i < KP_lsuDataBits / 32; ++i) {
           p_wdata[i] = io_axi1_write_data_bits_data.read().get_word(i);
         }
 
-        for (int i = 0; i < kUncBits / 8; ++i) {
+        for (int i = 0; i < KP_lsuDataBits / 8; ++i) {
           if (io_axi1_write_data_bits_strb.read().get_bit(i) != 0) {
             Write(addr + i, 1, wdata + i);
           }
@@ -314,11 +314,11 @@
   struct rtcm_t {
     uint32_t cycle;
     uint32_t id : 7;
-    sc_bv<kUncBits> data;
+    sc_bv<KP_lsuDataBits> data;
   };
 
   fifo_t<rtcm_t> rtcm_[2];
-  sc_bv<kUncBits> runused_;
+  sc_bv<KP_lsuDataBits> runused_;
 };
 
 #endif  // TESTS_VERILATOR_SIM_KELVIN_CORE_IF_H_
diff --git a/tests/verilator_sim/kelvin/core_tb.cc b/tests/verilator_sim/kelvin/core_tb.cc
index 8d5b982..ed45a8c 100644
--- a/tests/verilator_sim/kelvin/core_tb.cc
+++ b/tests/verilator_sim/kelvin/core_tb.cc
@@ -90,13 +90,13 @@
   sc_signal<sc_bv<32> > io_csr_out_value_6;
   sc_signal<sc_bv<32> > io_csr_out_value_7;
   sc_signal<sc_bv<32> > io_ibus_addr;
-  sc_signal<sc_bv<256> > io_ibus_rdata;
+  sc_signal<sc_bv<KP_fetchDataBits> > io_ibus_rdata;
   sc_signal<sc_bv<32> > io_dbus_addr;
   sc_signal<sc_bv<32> > io_dbus_adrx;
-  sc_signal<sc_bv<kDbusBits> > io_dbus_size;
-  sc_signal<sc_bv<kVector> > io_dbus_wdata;
-  sc_signal<sc_bv<kVector / 8> > io_dbus_wmask;
-  sc_signal<sc_bv<kVector> > io_dbus_rdata;
+  sc_signal<sc_bv<KP_dbusSize> > io_dbus_size;
+  sc_signal<sc_bv<KP_lsuDataBits> > io_dbus_wdata;
+  sc_signal<sc_bv<KP_lsuDataBits / 8> > io_dbus_wmask;
+  sc_signal<sc_bv<KP_lsuDataBits> > io_dbus_rdata;
   sc_signal<sc_bv<5> > io_slog_addr;
   sc_signal<sc_bv<32> > io_slog_data;
   sc_signal<sc_bv<4> > io_debug_en;
@@ -108,8 +108,8 @@
   sc_signal<sc_bv<kUncId> > io_axi0_write_addr_bits_id;
   sc_signal<bool> io_axi0_write_data_ready;
   sc_signal<bool> io_axi0_write_data_valid;
-  sc_signal<sc_bv<kUncBits> > io_axi0_write_data_bits_data;
-  sc_signal<sc_bv<kUncStrb> > io_axi0_write_data_bits_strb;
+  sc_signal<sc_bv<KP_lsuDataBits> > io_axi0_write_data_bits_data;
+  sc_signal<sc_bv<KP_lsuDataBits/8> > io_axi0_write_data_bits_strb;
   sc_signal<bool> io_axi0_write_resp_ready;
   sc_signal<bool> io_axi0_write_resp_valid;
   sc_signal<sc_bv<kUncId> > io_axi0_write_resp_bits_id;
@@ -122,7 +122,7 @@
   sc_signal<bool> io_axi0_read_data_valid;
   sc_signal<sc_bv<2> > io_axi0_read_data_bits_resp;
   sc_signal<sc_bv<kUncId> > io_axi0_read_data_bits_id;
-  sc_signal<sc_bv<kUncBits> > io_axi0_read_data_bits_data;
+  sc_signal<sc_bv<KP_lsuDataBits> > io_axi0_read_data_bits_data;
 #endif  // KP_enableVector
   sc_signal<bool> io_axi1_write_addr_ready;
   sc_signal<bool> io_axi1_write_addr_valid;
@@ -130,8 +130,8 @@
   sc_signal<sc_bv<kUncId> > io_axi1_write_addr_bits_id;
   sc_signal<bool> io_axi1_write_data_ready;
   sc_signal<bool> io_axi1_write_data_valid;
-  sc_signal<sc_bv<kUncBits> > io_axi1_write_data_bits_data;
-  sc_signal<sc_bv<kUncStrb> > io_axi1_write_data_bits_strb;
+  sc_signal<sc_bv<KP_lsuDataBits> > io_axi1_write_data_bits_data;
+  sc_signal<sc_bv<KP_lsuDataBits/8> > io_axi1_write_data_bits_strb;
   sc_signal<bool> io_axi1_write_resp_ready;
   sc_signal<bool> io_axi1_write_resp_valid;
   sc_signal<sc_bv<kUncId> > io_axi1_write_resp_bits_id;
@@ -144,7 +144,7 @@
   sc_signal<bool> io_axi1_read_data_valid;
   sc_signal<sc_bv<2> > io_axi1_read_data_bits_resp;
   sc_signal<sc_bv<kUncId> > io_axi1_read_data_bits_id;
-  sc_signal<sc_bv<kUncBits> > io_axi1_read_data_bits_data;
+  sc_signal<sc_bv<KP_lsuDataBits> > io_axi1_read_data_bits_data;
 
 #define IO_DEBUG(x)                       \
   sc_signal<sc_bv<32> > io_debug_addr##x; \
diff --git a/tests/verilator_sim/matcha/kelvin_if.h b/tests/verilator_sim/matcha/kelvin_if.h
index f18ec48..0f435fb 100644
--- a/tests/verilator_sim/matcha/kelvin_if.h
+++ b/tests/verilator_sim/matcha/kelvin_if.h
@@ -18,12 +18,17 @@
 #include "tests/verilator_sim/kelvin/memory_if.h"
 #include "tests/verilator_sim/kelvin/kelvin_cfg.h"
 
+#define PARAMS_HEADER_PREFIX hdl/chisel/src/matcha/
+#define PARAMS_HEADER_SUFFIX _parameters.h
+#define PARAMS_HEADER STR(PARAMS_HEADER_PREFIX VERILATOR_MODEL PARAMS_HEADER_SUFFIX)
+#include PARAMS_HEADER
+
 //     [Bus]  addr
 // 1cc [SRAM] addr
 // 2cc [SRAM] rdata
 //     [Bus]  rdata
 constexpr int kWaitState = 2;
-constexpr int kBusBits = 256;
+constexpr int kBusBits = KP_lsuDataBits;
 
 struct Kelvin_if : Memory_if {
   sc_in<bool> io_bus_cvalid;
@@ -32,7 +37,7 @@
   sc_in<sc_bv<7> > io_bus_cid;
   sc_in<sc_bv<32> > io_bus_caddr;
   sc_in<sc_bv<kBusBits> > io_bus_wdata;
-  sc_in<sc_bv<32> > io_bus_wmask;
+  sc_in<sc_bv<kBusBits / 8> > io_bus_wmask;
 
   sc_out<bool> io_bus_rvalid;
   sc_out<sc_bv<7> > io_bus_rid;
diff --git a/tests/verilator_sim/matcha/kelvin_tb.cc b/tests/verilator_sim/matcha/kelvin_tb.cc
index 38de989..cd17021 100644
--- a/tests/verilator_sim/matcha/kelvin_tb.cc
+++ b/tests/verilator_sim/matcha/kelvin_tb.cc
@@ -21,6 +21,11 @@
 #define MODEL_HEADER STR(VERILATOR_MODEL MODEL_HEADER_SUFFIX)
 #include MODEL_HEADER
 
+#define PARAMS_HEADER_PREFIX hdl/chisel/src/matcha/
+#define PARAMS_HEADER_SUFFIX _parameters.h
+#define PARAMS_HEADER STR(PARAMS_HEADER_PREFIX VERILATOR_MODEL PARAMS_HEADER_SUFFIX)
+#include PARAMS_HEADER
+
 #include "absl/flags/flag.h"
 #include "absl/flags/parse.h"
 #include "absl/flags/usage.h"
@@ -65,11 +70,11 @@
   sc_signal<bool> cwrite;
   sc_signal<sc_bv<32> > caddr;
   sc_signal<sc_bv<7> > cid;
-  sc_signal<sc_bv<256> > wdata;
-  sc_signal<sc_bv<32> > wmask;
+  sc_signal<sc_bv<KP_lsuDataBits> > wdata;
+  sc_signal<sc_bv<KP_lsuDataBits / 8> > wmask;
   sc_signal<bool> rvalid;
   sc_signal<sc_bv<7> > rid;
-  sc_signal<sc_bv<256> > rdata;
+  sc_signal<sc_bv<KP_lsuDataBits> > rdata;
 
   ml_reset = 0;
   clk_freeze = 0;