MachineCsr pass simple interrupt and exception tests

This commit is contained in:
Charles Papon 2017-03-23 23:12:44 +01:00
parent ed0660237f
commit 72d65841d2
6 changed files with 3263 additions and 38 deletions

View File

@ -26,7 +26,7 @@ case class MachineCsrConfig(
marchid : BigInt,
mimpid : BigInt,
mhartid : BigInt,
misaExtensions : Int,
misaExtensionsInit : Int,
misaAccess : CsrAccess,
mtvecAccess : CsrAccess,
mtvecInit : BigInt,
@ -151,18 +151,22 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
//Define CSR mapping utilities
val csrMapping = new CsrMapping()
implicit class CsrAccessPimper(csrAccess : CsrAccess){
def apply(csrAddress : Int, thats : (Int, Data)*) : Unit = csrAccess match{
case `WRITE_ONLY` | `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)
def apply(csrAddress : Int, thats : (Int, Data)*) : Unit = {
if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrMapping.w(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{
case `WRITE_ONLY` | `READ_WRITE` => csrMapping.w(csrAddress, 0, that)
case `READ_ONLY` | `READ_WRITE` => csrMapping.r(csrAddress, 0, that)
def apply(csrAddress : Int, that : Data) : Unit = {
if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) csrMapping.w(csrAddress, 0, that)
if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) csrMapping.r(csrAddress, 0, that)
}
}
//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 mepc = Reg(UInt(xlen bits))
val mstatus = new Area{
@ -182,7 +186,7 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
val exceptionCode = Reg(UInt(exceptionCodeWidth 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()
@ -193,14 +197,14 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
if(mimpid != null) READ_ONLY(CSR.MIMPID , U(mimpid ))
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_WRITE(CSR.MIP, 3 -> mip.MSIP)
READ_WRITE(CSR.MIE, 11 -> mie.MEIE, 7 -> mie.MTIE, 3 -> mie.MSIE)
mtvecAccess(CSR.MTVEC, mtvec)
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)
mcauseAccess(CSR.MCAUSE, xlen-1 -> mcause.interrupt, 0 -> mcause.exceptionCode)
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)
val pipelineLiberator = new Area{
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
}
@ -295,6 +299,7 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
when(memory.arbitration.isFiring && memory.input(ENV_CTRL) === EnvCtrlEnum.MRET){
jumpInterface.valid := True
jumpInterface.payload := mepc
execute.arbitration.flushIt := True
mstatus.MIE := mstatus.MPIE
}
@ -305,41 +310,39 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
val imm = IMM(input(INSTRUCTION))
val writeEnable = !((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|| (input(INSTRUCTION)(14 downto 13) === "10" && imm.z === 0))
val readEnable = input(INSTRUCTION)(rdRange) =/= 0
val writeEnable = arbitration.isValid && !arbitration.isStuckByOthers && input(IS_CSR) &&
(!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|| (input(INSTRUCTION)(14 downto 13) === "10" && imm.z === 0)))
val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1)
val readData = B(0, 32 bits)
val writeData = input(INSTRUCTION)(12).mux(
val writeData = input(INSTRUCTION)(13).mux(
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(writeEnable) {
output(REGFILE_WRITE_DATA) := writeData
}
output(REGFILE_WRITE_DATA) := readData
}
//Translation of the csrMapping into real logic
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 {
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 _ =>
}
}
for (element <- jobs) element match {
case element: CsrRead => readData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits
case _ =>
}
}
}
}

View File

@ -27,7 +27,7 @@ class Stage() extends Area{
val input,inputDefault = key()
inputsDefault(key.asInstanceOf[Stageable[Data]]) = inputDefault
input := inputDefault
input.setPartialName(this,"input_" + key.getName())
input.setPartialName(this, key.getName())
}).asInstanceOf[T]
}
@ -36,11 +36,11 @@ class Stage() extends Area{
val output,outputDefault = key()
outputsDefault(key.asInstanceOf[Stageable[Data]]) = outputDefault
output := outputDefault
output.setPartialName(this,"output_" + key.getName())
output //.setPartialName(this,"output_" + key.getName())
}).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 = ???

View File

@ -37,10 +37,10 @@ object TopLevel {
marchid = 22,
mimpid = 33,
mhartid = 44,
misaExtensions = 66,
misaExtensionsInit = 66,
misaAccess = READ_WRITE,
mtvecAccess = READ_WRITE,
mtvecInit = 0x80000004l,
mtvecInit = 0x00000020l,
mepcAccess = READ_WRITE,
mscratchGen = true,
mcauseAccess = READ_WRITE,

View File

@ -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{
public:
RiscvTest(string name) : Workspace(name) {
@ -362,7 +388,7 @@ public:
}
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];
if((code & 1) == 0){
cout << "Wrong error code"<< endl;
@ -521,6 +547,11 @@ int main(int argc, char **argv, char **env) {
// Dhrystone("dhrystoneO3ML",false,false).run(8e6);
// Dhrystone("dhrystoneO3MLL",false,false).run(80e6);
#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);

View File

@ -1,6 +1,7 @@
TRACE=no
DHRYSTONE=yes
REDO=5
TRACE=yes
CSR=yes
DHRYSTONE=no
REDO=1
ADDCFLAGS += -CFLAGS -DREDO=${REDO}
ifeq ($(DHRYSTONE),yes)
@ -12,6 +13,10 @@ ifeq ($(TRACE),yes)
ADDCFLAGS += -CFLAGS -DTRACE
endif
ifeq ($(CSR),yes)
ADDCFLAGS += -CFLAGS -DCSR
endif
run: compile
./obj_dir/VVexRiscv

File diff suppressed because it is too large Load Diff