Skip to content

Commit

Permalink
Add more configs and separate state and transition of core (#22)
Browse files Browse the repository at this point in the history
* feat: split state and trans of RiscvCore

* build: bump to sbt1.8.2

* fix: set width of exceptionNO

* refactor: remove test code

* refactor: replace deprecated function in Chisel3.6

* feat: support more config

* feat: add config for initValue of mtvec

* feat: support config initValue of mstatus

* fix: set default value of mstatus to h0000_1800
  • Loading branch information
liuyic00 authored Aug 17, 2024
1 parent ec1e447 commit 74c204b
Show file tree
Hide file tree
Showing 19 changed files with 260 additions and 218 deletions.
6 changes: 2 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ ThisBuild / scalaVersion := "2.12.17"

ThisBuild / crossScalaVersions := Seq("2.12.15", "2.13.8")

resolvers ++= Seq(
Resolver.sonatypeRepo("snapshots"),
Resolver.sonatypeRepo("releases")
)
resolvers ++= Resolver.sonatypeOssRepos("releases")
resolvers ++= Resolver.sonatypeOssRepos("snapshots")

lazy val publishSettings = Seq(
versionScheme := {
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.6.2
sbt.version=1.8.2
13 changes: 0 additions & 13 deletions src/main/scala/rvspeccore/checker/AssumeHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,3 @@ object RVPrivileged extends AssumeHelper with spec.instset.PrivilegedInsts {
// )
val partition: Seq[AssumeHelper] = List(trap_return)
}

object SV39Translate
extends AssumeHelper
with spec.instset.PrivilegedInsts
with spec.instset.IBaseInsts
with spec.instset.ZicsrExtensionInsts {
val regImm = AssumeHelper(
// List(LW, SW, SRET, MRET)
// List(LW, SW)
List(TEST_TLBLW)
)
val partition: Seq[AssumeHelper] = List(regImm)
}
91 changes: 50 additions & 41 deletions src/main/scala/rvspeccore/core/RVConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,61 @@ package rvspeccore.core
import chisel3._
import chisel3.util._

/** @param XLEN
* The width of an integer register in bits
* @param extensions
* Supported extensions
* @param fakeExtensions
* RiscvCore does not support these extensions, but they will appear in misa
*/
class RVConfig(val XLEN: Int, extensions: String, fakeExtensions: String) {
case class RVConfig(configs: (String, Any)*) {
val cfgs = configs.toMap
// - riscv-spec-20191213
// - We use the term XLEN to refer to the width of an integer register in
// : We use the term XLEN to refer to the width of an integer register in
// bits.
require(cfgs.contains("XLEN"), "XLEN is required in RVConfig")
val XLEN: Int = cfgs("XLEN").asInstanceOf[Int]
require(XLEN == 32 || XLEN == 64, "RiscvCore only support 32 or 64 bits now")

// ISA Extensions
val M: Boolean = extensions.indexOf("M") != -1
val C: Boolean = extensions.indexOf("C") != -1
// Priviledge Levels
val S: Boolean = extensions.indexOf("S") != -1
val U: Boolean = extensions.indexOf("U") != -1
object extensions {
protected val raw = cfgs.getOrElse("extensions", "").asInstanceOf[String]

// - RISC-V ISA, Unprivileged, 20240411
// - Preface
val I = true
val M = raw.contains("M")
val C = raw.contains("C")
val Zifencei = raw.contains("Zifencei")
val Zicsr = raw.contains("Zicsr")

// - RSIC-V ISA, Privileged, 20240411
// - 1. Introduction
// - 1.2. Privilege Levels
// - Table 1. RISC-V privilege levels.
val U = raw.contains("U")
val S = raw.contains("S")
// - Table 2. Supported combination of privilege modes.
assert(
(!U && !S) || (U && !S) || (U && S),
"Supported combination of privilege modes are M, MU, MSU, " +
s"not M${if (S) "S" else ""}${if (U) "U" else ""}"
)
}
val fakeExtensions: String = cfgs.getOrElse("fakeExtensions", "").asInstanceOf[String]

// CSRs Config
object csr {
// Misa
val MisaExtList: String =
cfgs.getOrElse("fakeExtensions", "").asInstanceOf[String] +
Seq(
if (extensions.I) 'I' else "",
if (extensions.M) 'M' else "",
if (extensions.C) 'C' else "",
if (extensions.S) 'S' else "",
if (extensions.U) 'U' else ""
).mkString("")
}

// Misa
val CSRMisaExtList = (fakeExtensions.toSeq ++
Seq(
Some('I'),
if (M) Some('M') else None,
if (C) Some('C') else None,
if (S) Some('S') else None,
if (U || S) Some('U') else None
).flatten).distinct
}
// Init Value
val initValue = cfgs.getOrElse("initValue", Map[String, String]()).asInstanceOf[Map[String, String]]

object RVConfig {

/** Create a RVConfig
* @param XLEN
* The width of an integer register in bits
* @param extensions
* Supported extensions
* @param fakeExtensions
* RiscvCore do not support this extensions, but will be appear in Misa
*/
def apply(
XLEN: Int,
extensions: String = "",
fakeExtensions: String = ""
): RVConfig =
new RVConfig(XLEN, extensions, fakeExtensions)
// Other Functions Config
object functions {
protected val raw = cfgs.getOrElse("functions", Seq[String]()).asInstanceOf[Seq[String]]
val privileged: Boolean = raw.contains("Privileged")
}
}
116 changes: 71 additions & 45 deletions src/main/scala/rvspeccore/core/RiscvCore.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,20 @@ import spec.instset.csr.CSR
import spec.instset.csr.EventSig
import spec.instset.csr.SatpStruct

abstract class BaseCore()(implicit config: RVConfig) extends Module {
// Define Basic parts
abstract class BaseCore()(implicit val config: RVConfig) extends Module {
implicit val XLEN: Int = config.XLEN
val io = IO(new Bundle {
// Processor IO
val inst = Input(UInt(32.W))
val valid = Input(Bool())
val mem = new MemIO
val tlb = new TLBIO
// Exposed processor status
val now = Output(State())
val next = Output(State())
val event = Output(new EventSig)
val iFetchpc = Output(UInt(XLEN.W))
})
// Initial State
val now = RegInit(State.wireInit())

// State
val now = Wire(State())
val next = Wire(State())
val mem = Wire(new MemIO)
val tlb = Wire(new TLBIO)
// Global Data
// IO ports
val iFetchpc = Wire(UInt(XLEN.W))
val mem = Wire(new MemIO)
val tlb = Wire(new TLBIO)
// Global signals
val inst = Wire(UInt(32.W))
val global_data = Wire(new GlobalData) // TODO: GlobalData only has setpc? event, iFetchpc?
val event = Wire(new EventSig)
val iFetchpc = Wire(UInt(XLEN.W))
}
class GlobalData extends Bundle {
val setpc = Bool()
Expand Down Expand Up @@ -82,11 +72,11 @@ class State()(implicit XLEN: Int, config: RVConfig) extends Bundle {

object State {
def apply()(implicit XLEN: Int, config: RVConfig): State = new State
def wireInit(pcStr: String = "h8000_0000")(implicit XLEN: Int, config: RVConfig): State = {
def wireInit()(implicit XLEN: Int, config: RVConfig): State = {
val state = Wire(new State)

state.reg := Seq.fill(32)(0.U(XLEN.W))
state.pc := pcStr.U(XLEN.W)
state.pc := config.initValue.getOrElse("pc", "h8000_0000").U(XLEN.W)
state.csr := CSR.wireInit()

state.internal := Internal.wireInit()
Expand All @@ -95,13 +85,30 @@ object State {
}
}

class RiscvCore()(implicit config: RVConfig) extends BaseCore with RVInstSet {
class RiscvTrans()(implicit config: RVConfig) extends BaseCore with RVInstSet {
val io = IO(new Bundle {
// Processor IO
val inst = Input(UInt(32.W))
val valid = Input(Bool())
val iFetchpc = Output(UInt(XLEN.W))
val mem = new MemIO
val tlb = new TLBIO
// Processor status
val now = Input(State())
val next = Output(State())
// Exposed signals
val event = Output(new EventSig)
})

// Initial the value
now := io.now
// these signals should keep the value in the next clock if there no changes below
next := now
inst := 0.U
global_data.setpc := false.B
event := 0.U.asTypeOf(new EventSig)
iFetchpc := now.pc

// dont read or write mem
// if there no LOAD/STORE below
mem := 0.U.asTypeOf(new MemIO)
Expand All @@ -122,28 +129,18 @@ class RiscvCore()(implicit config: RVConfig) extends BaseCore with RVInstSet {
iFetchpc := resultPC

// Decode and Excute
config.XLEN match {
case 32 => {
doRV32I
if (config.M) { doRV32M }
if (config.C) { doRV32C }
}
case 64 => {
doRV64I
if (config.M) { doRV64M }
if (config.C) { doRV64C }
}
}
// TODO: add config for privileged instruction
doRVPrivileged()
doRVZicsr
doRVZifencei
doRVI
if (config.extensions.C) doRVC
if (config.extensions.M) doRVM
if (config.functions.privileged) doRVPrivileged
if (config.extensions.Zicsr) doRVZicsr
if (config.extensions.Zifencei) doRVZifencei

// End excute
next.reg(0) := 0.U

when(!global_data.setpc) {
if (config.C) {
if (config.extensions.C) {
// + 4.U for 32 bits width inst
// + 2.U for 16 bits width inst in C extension
next.pc := now.pc + Mux(inst(1, 0) === "b11".U, 4.U, 2.U)
Expand All @@ -159,12 +156,41 @@ class RiscvCore()(implicit config: RVConfig) extends BaseCore with RVInstSet {
io.mem <> mem
io.tlb <> tlb

// update
now := next

// output
io.now := now
io.next := next
io.event := event
io.iFetchpc := iFetchpc
}

class RiscvCore()(implicit config: RVConfig) extends Module {
implicit val XLEN: Int = config.XLEN

val io = IO(new Bundle {
// Processor IO
val inst = Input(UInt(32.W))
val valid = Input(Bool())
val iFetchpc = Output(UInt(XLEN.W))
val mem = new MemIO
val tlb = new TLBIO
// Processor status
val now = Output(State())
val next = Output(State())
// Exposed signals
val event = Output(new EventSig)
})

val state = RegInit(State.wireInit())
val trans = Module(new RiscvTrans())

trans.io.inst := io.inst
trans.io.valid := io.valid
trans.io.mem <> io.mem
trans.io.tlb <> io.tlb

trans.io.now := state
state := trans.io.next

io.now := state
io.next := trans.io.next
io.event := trans.io.event
io.iFetchpc := trans.io.iFetchpc
}
7 changes: 7 additions & 0 deletions src/main/scala/rvspeccore/core/spec/instset/CExtension.scala
Original file line number Diff line number Diff line change
Expand Up @@ -303,4 +303,11 @@ trait CExtension extends BaseCore with CDecode with CExtensionInsts { this: IBas
next.reg(cat01(rdP)) := signExt(now.reg(cat01(rdP))(31, 0) - now.reg(cat01(rs2P))(31, 0), XLEN)
}
}

def doRVC: Unit = {
config.XLEN match {
case 32 => doRV32C
case 64 => doRV64C
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import rvspeccore.core.tool.BitTool._
* - 2.3 Immediate Encoding Variants
*/
trait CommonDecode extends BaseCore with csr.ExceptionSupport {
val inst = WireInit(0.U(32.W))

val opcode = WireInit(0.U(7.W))
val rd = WireInit(0.U(5.W))
val funct3 = WireInit(0.U(3.W))
Expand Down
15 changes: 9 additions & 6 deletions src/main/scala/rvspeccore/core/spec/instset/IBase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,7 @@ trait IBase extends BaseCore with CommonDecode with IBaseInsts with ExceptionSup

}
def addrAligned(size: UInt, addr: UInt): Bool = {
MuxLookup(
size,
false.B,
MuxLookup(size, false.B)(
Seq(
"b00".U -> true.B, // b
"b01".U -> (addr(0) === 0.U), // h
Expand All @@ -133,9 +131,7 @@ trait IBase extends BaseCore with CommonDecode with IBaseInsts with ExceptionSup
}

def getfetchSize(): UInt = {
MuxLookup(
now.csr.misa(CSR.getMisaExtInt('C')),
SizeOp.w,
MuxLookup(now.csr.misa(CSR.getMisaExtInt('C')), SizeOp.w)(
Seq(
"b0".U -> SizeOp.w,
"b1".U -> SizeOp.h
Expand Down Expand Up @@ -415,6 +411,13 @@ trait IBase extends BaseCore with CommonDecode with IBaseInsts with ExceptionSup

// - 5.4 HINT Instructions
}

def doRVI: Unit = {
config.XLEN match {
case 32 => doRV32I
case 64 => doRV64I
}
}
}

// scalafmt: { maxColumn = 120 } (back to defaults)
7 changes: 7 additions & 0 deletions src/main/scala/rvspeccore/core/spec/instset/MExtension.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ trait MExtension extends BaseCore with CommonDecode with MExtensionInsts {
when(REMW(inst)) { decodeR; next.reg(rd) := signExt(opREM(now.reg(rs1)(31, 0), now.reg(rs2)(31, 0), 32), XLEN) }
when(REMUW(inst)) { decodeR; next.reg(rd) := signExt(opREMU(now.reg(rs1)(31, 0), now.reg(rs2)(31, 0), 32), XLEN) }
}

def doRVM: Unit = {
XLEN match {
case 32 => doRV32M
case 64 => doRV64M
}
}
}

// scalafmt: { maxColumn = 120 } (back to defaults)
Loading

0 comments on commit 74c204b

Please sign in to comment.