MachineCsr pass simple interrupt and exception tests
This commit is contained in:
parent
ed0660237f
commit
72d65841d2
|
@ -26,7 +26,7 @@ case class MachineCsrConfig(
|
||||||
marchid : BigInt,
|
marchid : BigInt,
|
||||||
mimpid : BigInt,
|
mimpid : BigInt,
|
||||||
mhartid : BigInt,
|
mhartid : BigInt,
|
||||||
misaExtensions : Int,
|
misaExtensionsInit : Int,
|
||||||
misaAccess : CsrAccess,
|
misaAccess : CsrAccess,
|
||||||
mtvecAccess : CsrAccess,
|
mtvecAccess : CsrAccess,
|
||||||
mtvecInit : BigInt,
|
mtvecInit : BigInt,
|
||||||
|
@ -151,18 +151,22 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
|
||||||
//Define CSR mapping utilities
|
//Define CSR mapping utilities
|
||||||
val csrMapping = new CsrMapping()
|
val csrMapping = new CsrMapping()
|
||||||
implicit class CsrAccessPimper(csrAccess : CsrAccess){
|
implicit class CsrAccessPimper(csrAccess : CsrAccess){
|
||||||
def apply(csrAddress : Int, thats : (Int, Data)*) : Unit = csrAccess match{
|
def apply(csrAddress : Int, thats : (Int, Data)*) : Unit = {
|
||||||
case `WRITE_ONLY` | `READ_WRITE` => for(that <- thats) csrMapping.w(csrAddress,that._1, that._2)
|
if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrMapping.w(csrAddress,that._1, that._2)
|
||||||
case `READ_ONLY` | `READ_WRITE` => for(that <- thats) csrMapping.r(csrAddress,that._1, that._2)
|
if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrMapping.r(csrAddress,that._1, that._2)
|
||||||
}
|
}
|
||||||
def apply(csrAddress : Int, that : Data) : Unit = csrAccess match{
|
def apply(csrAddress : Int, that : Data) : Unit = {
|
||||||
case `WRITE_ONLY` | `READ_WRITE` => csrMapping.w(csrAddress, 0, that)
|
if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) csrMapping.w(csrAddress, 0, that)
|
||||||
case `READ_ONLY` | `READ_WRITE` => csrMapping.r(csrAddress, 0, that)
|
if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) csrMapping.r(csrAddress, 0, that)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Define CSR registers
|
//Define CSR registers
|
||||||
|
val misa = new Area{
|
||||||
|
val base = Reg(UInt(2 bits)) init(U"01")
|
||||||
|
val extensions = Reg(Bits(26 bits)) init(misaExtensionsInit)
|
||||||
|
}
|
||||||
val mtvec = RegInit(U(mtvecInit,xlen bits))
|
val mtvec = RegInit(U(mtvecInit,xlen bits))
|
||||||
val mepc = Reg(UInt(xlen bits))
|
val mepc = Reg(UInt(xlen bits))
|
||||||
val mstatus = new Area{
|
val mstatus = new Area{
|
||||||
|
@ -182,7 +186,7 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
|
||||||
val exceptionCode = Reg(UInt(exceptionCodeWidth bits))
|
val exceptionCode = Reg(UInt(exceptionCodeWidth bits))
|
||||||
}
|
}
|
||||||
val mbadaddr = Reg(UInt(xlen bits))
|
val mbadaddr = Reg(UInt(xlen bits))
|
||||||
val mcycle = Reg(UInt(64 bits)) randBoot()
|
val mcycle = Reg(UInt(64 bits)) randBoot()
|
||||||
val minstret = Reg(UInt(64 bits)) randBoot()
|
val minstret = Reg(UInt(64 bits)) randBoot()
|
||||||
|
|
||||||
|
|
||||||
|
@ -193,14 +197,14 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
|
||||||
if(mimpid != null) READ_ONLY(CSR.MIMPID , U(mimpid ))
|
if(mimpid != null) READ_ONLY(CSR.MIMPID , U(mimpid ))
|
||||||
if(mhartid != null) READ_ONLY(CSR.MHARTID , U(mhartid ))
|
if(mhartid != null) READ_ONLY(CSR.MHARTID , U(mhartid ))
|
||||||
|
|
||||||
misaAccess(CSR.MISA, xlen-2 -> U"01" , 0 -> U(misaExtensions))
|
misaAccess(CSR.MISA, xlen-2 -> misa.base , 0 -> misa.extensions)
|
||||||
READ_ONLY(CSR.MIP, 11 -> mip.MEIP, 7 -> mip.MTIP)
|
READ_ONLY(CSR.MIP, 11 -> mip.MEIP, 7 -> mip.MTIP)
|
||||||
READ_WRITE(CSR.MIP, 3 -> mip.MSIP)
|
READ_WRITE(CSR.MIP, 3 -> mip.MSIP)
|
||||||
READ_WRITE(CSR.MIE, 11 -> mie.MEIE, 7 -> mie.MTIE, 3 -> mie.MSIE)
|
READ_WRITE(CSR.MIE, 11 -> mie.MEIE, 7 -> mie.MTIE, 3 -> mie.MSIE)
|
||||||
|
|
||||||
mtvecAccess(CSR.MTVEC, mtvec)
|
mtvecAccess(CSR.MTVEC, mtvec)
|
||||||
mepcAccess(CSR.MEPC, mepc)
|
mepcAccess(CSR.MEPC, mepc)
|
||||||
READ_ONLY(CSR.MSTATUS, 7 -> mstatus.MPIE, 3 -> mstatus.MIE)
|
READ_WRITE(CSR.MSTATUS, 7 -> mstatus.MPIE, 3 -> mstatus.MIE)
|
||||||
if(mscratchGen) READ_WRITE(CSR.MSCRATCH, mscratch)
|
if(mscratchGen) READ_WRITE(CSR.MSCRATCH, mscratch)
|
||||||
mcauseAccess(CSR.MCAUSE, xlen-1 -> mcause.interrupt, 0 -> mcause.exceptionCode)
|
mcauseAccess(CSR.MCAUSE, xlen-1 -> mcause.interrupt, 0 -> mcause.exceptionCode)
|
||||||
mbadaddrAccess(CSR.MBADADDR, mbadaddr)
|
mbadaddrAccess(CSR.MBADADDR, mbadaddr)
|
||||||
|
@ -222,7 +226,7 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
|
||||||
//Used to make the pipeline empty softly (for interrupts)
|
//Used to make the pipeline empty softly (for interrupts)
|
||||||
val pipelineLiberator = new Area{
|
val pipelineLiberator = new Area{
|
||||||
val enable = False
|
val enable = False
|
||||||
decode.arbitration.haltIt setWhen(enable)
|
prefetch.arbitration.haltIt setWhen(enable)
|
||||||
val done = ! List(fetch, decode, execute, memory, writeBack).map(_.arbitration.isValid).orR
|
val done = ! List(fetch, decode, execute, memory, writeBack).map(_.arbitration.isValid).orR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,6 +299,7 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
|
||||||
when(memory.arbitration.isFiring && memory.input(ENV_CTRL) === EnvCtrlEnum.MRET){
|
when(memory.arbitration.isFiring && memory.input(ENV_CTRL) === EnvCtrlEnum.MRET){
|
||||||
jumpInterface.valid := True
|
jumpInterface.valid := True
|
||||||
jumpInterface.payload := mepc
|
jumpInterface.payload := mepc
|
||||||
|
execute.arbitration.flushIt := True
|
||||||
mstatus.MIE := mstatus.MPIE
|
mstatus.MIE := mstatus.MPIE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,41 +310,39 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
|
||||||
|
|
||||||
val imm = IMM(input(INSTRUCTION))
|
val imm = IMM(input(INSTRUCTION))
|
||||||
|
|
||||||
val writeEnable = !((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|
val writeEnable = arbitration.isValid && !arbitration.isStuckByOthers && input(IS_CSR) &&
|
||||||
|| (input(INSTRUCTION)(14 downto 13) === "10" && imm.z === 0))
|
(!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|
||||||
val readEnable = input(INSTRUCTION)(rdRange) =/= 0
|
|| (input(INSTRUCTION)(14 downto 13) === "10" && imm.z === 0)))
|
||||||
|
|
||||||
|
|
||||||
val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1)
|
val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1)
|
||||||
val readData = B(0, 32 bits)
|
val readData = B(0, 32 bits)
|
||||||
val writeData = input(INSTRUCTION)(12).mux(
|
val writeData = input(INSTRUCTION)(13).mux(
|
||||||
False -> writeSrc,
|
False -> writeSrc,
|
||||||
True -> Mux(input(INSTRUCTION)(13), readData & ~writeSrc, readData | writeSrc)
|
True -> Mux(input(INSTRUCTION)(12), readData & ~writeSrc, readData | writeSrc)
|
||||||
)
|
)
|
||||||
|
|
||||||
when(arbitration.isValid && input(IS_CSR)) {
|
when(arbitration.isValid && input(IS_CSR)) {
|
||||||
when(writeEnable) {
|
output(REGFILE_WRITE_DATA) := readData
|
||||||
output(REGFILE_WRITE_DATA) := writeData
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Translation of the csrMapping into real logic
|
//Translation of the csrMapping into real logic
|
||||||
val csrAddress = input(INSTRUCTION)(csrRange)
|
val csrAddress = input(INSTRUCTION)(csrRange)
|
||||||
when(arbitration.isValid && input(IS_CSR)) {
|
|
||||||
for ((address, jobs) <- csrMapping.mapping) {
|
|
||||||
when(csrAddress === address) {
|
|
||||||
when(writeEnable) {
|
|
||||||
for (element <- jobs) element match {
|
|
||||||
case element: CsrWrite => element.that.assignFromBits(writeData(element.bitOffset, element.that.getBitsWidth bits))
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for ((address, jobs) <- csrMapping.mapping) {
|
||||||
|
when(csrAddress === address) {
|
||||||
|
when(writeEnable) {
|
||||||
for (element <- jobs) element match {
|
for (element <- jobs) element match {
|
||||||
case element: CsrRead => readData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits
|
case element: CsrWrite => element.that.assignFromBits(writeData(element.bitOffset, element.that.getBitsWidth bits))
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (element <- jobs) element match {
|
||||||
|
case element: CsrRead => readData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class Stage() extends Area{
|
||||||
val input,inputDefault = key()
|
val input,inputDefault = key()
|
||||||
inputsDefault(key.asInstanceOf[Stageable[Data]]) = inputDefault
|
inputsDefault(key.asInstanceOf[Stageable[Data]]) = inputDefault
|
||||||
input := inputDefault
|
input := inputDefault
|
||||||
input.setPartialName(this,"input_" + key.getName())
|
input.setPartialName(this, key.getName())
|
||||||
}).asInstanceOf[T]
|
}).asInstanceOf[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,11 +36,11 @@ class Stage() extends Area{
|
||||||
val output,outputDefault = key()
|
val output,outputDefault = key()
|
||||||
outputsDefault(key.asInstanceOf[Stageable[Data]]) = outputDefault
|
outputsDefault(key.asInstanceOf[Stageable[Data]]) = outputDefault
|
||||||
output := outputDefault
|
output := outputDefault
|
||||||
output.setPartialName(this,"output_" + key.getName())
|
output //.setPartialName(this,"output_" + key.getName())
|
||||||
}).asInstanceOf[T]
|
}).asInstanceOf[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
def insert[T <: Data](key : Stageable[T]) : T = inserts.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],outsideCondScope(key())).asInstanceOf[T].setPartialName(this,key.getName())
|
def insert[T <: Data](key : Stageable[T]) : T = inserts.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],outsideCondScope(key())).asInstanceOf[T] //.setPartialName(this,key.getName())
|
||||||
// def apply[T <: Data](key : Stageable[T]) : T = ???
|
// def apply[T <: Data](key : Stageable[T]) : T = ???
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,10 @@ object TopLevel {
|
||||||
marchid = 22,
|
marchid = 22,
|
||||||
mimpid = 33,
|
mimpid = 33,
|
||||||
mhartid = 44,
|
mhartid = 44,
|
||||||
misaExtensions = 66,
|
misaExtensionsInit = 66,
|
||||||
misaAccess = READ_WRITE,
|
misaAccess = READ_WRITE,
|
||||||
mtvecAccess = READ_WRITE,
|
mtvecAccess = READ_WRITE,
|
||||||
mtvecInit = 0x80000004l,
|
mtvecInit = 0x00000020l,
|
||||||
mepcAccess = READ_WRITE,
|
mepcAccess = READ_WRITE,
|
||||||
mscratchGen = true,
|
mscratchGen = true,
|
||||||
mcauseAccess = READ_WRITE,
|
mcauseAccess = READ_WRITE,
|
||||||
|
|
|
@ -351,6 +351,32 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TestX28 : public Workspace{
|
||||||
|
public:
|
||||||
|
uint32_t refIndex = 0;
|
||||||
|
uint32_t *ref;
|
||||||
|
uint32_t refSize;
|
||||||
|
|
||||||
|
TestX28(string name, uint32_t *ref, uint32_t refSize) : Workspace(name) {
|
||||||
|
this->ref = ref;
|
||||||
|
this->refSize = refSize;
|
||||||
|
loadHex("../../resources/hex/" + name + ".hex");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void checks(){
|
||||||
|
if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address == 28){
|
||||||
|
assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data, ref[refIndex]);
|
||||||
|
//printf("%d\n",i);
|
||||||
|
|
||||||
|
refIndex++;
|
||||||
|
if(refIndex == refSize){
|
||||||
|
pass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class RiscvTest : public Workspace{
|
class RiscvTest : public Workspace{
|
||||||
public:
|
public:
|
||||||
RiscvTest(string name) : Workspace(name) {
|
RiscvTest(string name) : Workspace(name) {
|
||||||
|
@ -362,7 +388,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void checks(){
|
virtual void checks(){
|
||||||
if(top->VexRiscv->writeBack_arbitration_isValid == 1 && top->VexRiscv->writeBack_input_INSTRUCTION == 0x00000073){
|
if(top->VexRiscv->writeBack_arbitration_isValid == 1 && top->VexRiscv->writeBack_INSTRUCTION == 0x00000073){
|
||||||
uint32_t code = top->VexRiscv->RegFilePlugin_regFile[28];
|
uint32_t code = top->VexRiscv->RegFilePlugin_regFile[28];
|
||||||
if((code & 1) == 0){
|
if((code & 1) == 0){
|
||||||
cout << "Wrong error code"<< endl;
|
cout << "Wrong error code"<< endl;
|
||||||
|
@ -521,6 +547,11 @@ int main(int argc, char **argv, char **env) {
|
||||||
// Dhrystone("dhrystoneO3ML",false,false).run(8e6);
|
// Dhrystone("dhrystoneO3ML",false,false).run(8e6);
|
||||||
// Dhrystone("dhrystoneO3MLL",false,false).run(80e6);
|
// Dhrystone("dhrystoneO3MLL",false,false).run(80e6);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CSR
|
||||||
|
uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3};
|
||||||
|
TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).run(2e3);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t duration = timer_end(startedAt);
|
uint64_t duration = timer_end(startedAt);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
TRACE=no
|
TRACE=yes
|
||||||
DHRYSTONE=yes
|
CSR=yes
|
||||||
REDO=5
|
DHRYSTONE=no
|
||||||
|
REDO=1
|
||||||
|
|
||||||
ADDCFLAGS += -CFLAGS -DREDO=${REDO}
|
ADDCFLAGS += -CFLAGS -DREDO=${REDO}
|
||||||
ifeq ($(DHRYSTONE),yes)
|
ifeq ($(DHRYSTONE),yes)
|
||||||
|
@ -12,6 +13,10 @@ ifeq ($(TRACE),yes)
|
||||||
ADDCFLAGS += -CFLAGS -DTRACE
|
ADDCFLAGS += -CFLAGS -DTRACE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CSR),yes)
|
||||||
|
ADDCFLAGS += -CFLAGS -DCSR
|
||||||
|
endif
|
||||||
|
|
||||||
run: compile
|
run: compile
|
||||||
./obj_dir/VVexRiscv
|
./obj_dir/VVexRiscv
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue