npc,feat: add csr
Some checks failed
Build abstract machine with nix / build-abstract-machine (push) Failing after 1m1s
Run CTests within npc / npc-test (push) Failing after 56s

This commit is contained in:
xinyangli 2024-08-11 20:25:42 +08:00
parent ba18436c6c
commit a5790308f0
Signed by: xin
SSH key fingerprint: SHA256:qZ/tzd8lYRtUFSrfBDBMcUqV4GHKxqeqRA3huItgvbk
4 changed files with 181 additions and 0 deletions

View file

@ -0,0 +1,108 @@
package flow.components
import chisel3._
import chisel3.util.log2Ceil
import scala.reflect.runtime.universe._
import cats.instances.MapInstances
import dataclass.data
import chisel3.util.experimental.decode.{decoder, TruthTable}
import shapeless.HNil
import flow.Params
import chisel3.util.BitPat
import chisel3.util.Fill
class CSRControlInterface extends Bundle {
object csrRead extends ChiselEnum {
val csrReadDisabled, csrReadEnabled = Value
}
object csrWrite extends ChiselEnum {
val csrWriteDisabled, csrWriteEnabled = Value
}
val readEnable = Input(csrRead())
val writeEnable = Input(csrWrite())
def ctrlBindPorts = {
readEnable :: writeEnable :: HNil
}
}
class CSRCore(implicit val p: Params) extends Module {
val control = IO(new CSRControlInterface)
val in = IO(new Bundle {
val csrAddr = Input(UInt(p.csrAddrWidth))
val writeData = Input(UInt(p.XLEN))
})
val out = IO(new Bundle {
val readData = Output(UInt(p.XLEN))
val readValid = Output(Bool())
})
implicit class fromChiselEnumToBool[T <: EnumType](x: T) {
def B: Bool = {
x.asUInt =/= 0.U
}
}
val nameToAddr = Map(
"mstatus" -> 0x300,
"mtvec" -> 0x305,
"mie" -> 0x304,
"mepc" -> 0x341,
"mcause" -> 0x342,
"mtval" -> 0x343,
"mip" -> 0x344
)
val csrSize = nameToAddr.size
val addrToIndex = nameToAddr.zipWithIndex
.map(x => {
val (name: String, csrAddr: Int) = x._1
val index = x._2
csrAddr -> index
})
.toMap
val indexToAddr = addrToIndex.map(_.swap)
val csrIndexWidth = log2Ceil(csrSize).W
private val align = (x: UInt, w: Width) => BitPat(x.litValue.U(w))
val csrIndex = decoder(
in.csrAddr,
TruthTable(
addrToIndex.map(x =>
// Addr Index
(align(x._1.U, p.csrAddrWidth), align(x._2.U, csrIndexWidth))
),
align(addrToIndex.head._2.U, csrIndexWidth)
)
)
val csrIndexValid = !(
csrIndex === BitPat(0.U) &&
in.csrAddr =/= align(indexToAddr(0).U, p.csrAddrWidth)
)
val regs = RegInit(VecInit(Seq.fill(csrSize)(0.U(p.XLEN))))
val regReadValue = regs(csrIndex)
val delayWriteData = RegNext(in.writeData, 0.U(p.XLEN))
val delayWriteEnable = RegNext(control.writeEnable)
when(control.writeEnable.B) {
regs(csrIndex) := delayWriteData
}
when(control.readEnable.B) {
out.readData := regReadValue
out.readValid := true.B && csrIndexValid
} otherwise {
out.readData := 0.U(p.XLEN)
out.readValid := false.B && csrIndexValid
}
}

View file

@ -14,3 +14,9 @@ import io.circe.generic.JsonCodec
enableDifftest: Boolean = true,
traceConfig: TraceConfig = TraceConfig()
)
import chisel3._
case class Params(
XLEN: Width,
csrAddrWidth: Width = 12.W
)

View file

@ -0,0 +1,59 @@
package flow.tests
import chisel3._
import chiseltest._
import org.scalatest.freespec.AnyFreeSpec
import chiseltest.simulator.WriteVcdAnnotation
import flow.components.CSRCore
import flow.tests.defaultParams
class CSRSpec extends AnyFreeSpec with ChiselScalatestTester {
implicit val p: flow.Params = defaultParams()
"should compile" in {
test(new CSRCore) { c =>
c.clock.step(1)
}
}
"Write" - {
"delayed" in {
test(new CSRCore) { c =>
val tv = BigInt("deadbeef", 16)
c.in.csrAddr.poke(c.nameToAddr("mstatus"))
c.in.writeData.poke(tv)
c.control.writeEnable.poke(c.control.csrWrite.csrWriteEnabled)
c.clock.step(1)
c.control.readEnable.poke(c.control.csrRead.csrReadEnabled)
c.out.readData.expect(0)
c.out.readValid.expect(1)
c.clock.step(1)
c.out.readValid.expect(1)
c.out.readData.expect(tv)
}
}
}
"Read" - {
"controlled by readEnable" in {
test(new CSRCore) { c =>
val tv = BigInt("deadbeef", 16)
c.in.csrAddr.poke(c.nameToAddr("mstatus"))
c.in.writeData.poke(tv)
c.control.readEnable.poke(c.control.csrRead.csrReadEnabled)
c.control.writeEnable.poke(c.control.csrWrite.csrWriteEnabled)
c.clock.step(1)
c.control.readEnable.poke(c.control.csrRead.csrReadDisabled)
c.out.readData.expect(0)
c.out.readValid.expect(0)
c.clock.step(1)
c.out.readData.expect(0)
c.out.readValid.expect(0)
}
}
}
}

View file

@ -0,0 +1,8 @@
package flow.tests
import chisel3._
import flow.Params
object defaultParams {
def apply(): Params = new Params(XLEN = 32.W)
}