diff options
author | Friedrich Beckmann <friedrich.beckmann@hs-augsburg.de> | 2022-07-25 17:55:39 +0200 |
---|---|---|
committer | Friedrich Beckmann <friedrich.beckmann@hs-augsburg.de> | 2022-07-25 17:55:39 +0200 |
commit | 3fff6023602822531efdae30bc8ebf862967f1ef (patch) | |
tree | 16028102b8d850f8ab3115d28a8539ca6bc5f51d /VexRiscv/src/main/scala/vexriscv/plugin/RegFilePlugin.scala |
Initial Commit
Diffstat (limited to 'VexRiscv/src/main/scala/vexriscv/plugin/RegFilePlugin.scala')
-rw-r--r-- | VexRiscv/src/main/scala/vexriscv/plugin/RegFilePlugin.scala | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/VexRiscv/src/main/scala/vexriscv/plugin/RegFilePlugin.scala b/VexRiscv/src/main/scala/vexriscv/plugin/RegFilePlugin.scala new file mode 100644 index 0000000..94a3f32 --- /dev/null +++ b/VexRiscv/src/main/scala/vexriscv/plugin/RegFilePlugin.scala @@ -0,0 +1,122 @@ +package vexriscv.plugin + +import vexriscv._ +import spinal.core._ +import spinal.lib._ + +import scala.collection.mutable + + +trait RegFileReadKind +object ASYNC extends RegFileReadKind +object SYNC extends RegFileReadKind + + +class RegFilePlugin(regFileReadyKind : RegFileReadKind, + zeroBoot : Boolean = false, + x0Init : Boolean = true, + writeRfInMemoryStage : Boolean = false, + readInExecute : Boolean = false, + syncUpdateOnStall : Boolean = true, + rv32e : Boolean = false, + withShadow : Boolean = false //shadow registers aren't transition hazard free + ) extends Plugin[VexRiscv] with RegFileService{ + import Riscv._ + + override def readStage(): Stage = if(readInExecute) pipeline.execute else pipeline.decode + + override def setup(pipeline: VexRiscv): Unit = { + import pipeline.config._ + val decoderService = pipeline.service(classOf[DecoderService]) + decoderService.addDefault(RS1_USE,False) + decoderService.addDefault(RS2_USE,False) + decoderService.addDefault(REGFILE_WRITE_VALID,False) + } + + override def build(pipeline: VexRiscv): Unit = { + import pipeline._ + import pipeline.config._ + + val readStage = if(readInExecute) execute else decode + val writeStage = if(writeRfInMemoryStage) memory else stages.last + + val numRegisters = if(rv32e) 16 else 32 + def clipRange(that : Range) = if(rv32e) that.tail else that + + val global = pipeline plug new Area{ + val regFileSize = if(withShadow) numRegisters * 2 else numRegisters + val regFile = Mem(Bits(32 bits),regFileSize) addAttribute(Verilator.public) + if(zeroBoot) regFile.init(List.fill(regFileSize)(B(0, 32 bits))) + + val shadow = ifGen(withShadow)(new Area{ + val write, read, clear = RegInit(False) + + read clearWhen(clear && !readStage.arbitration.isStuck) + write clearWhen(clear && !writeStage.arbitration.isStuck) + + val csrService = pipeline.service(classOf[CsrInterface]) + csrService.w(0x7C0,2 -> clear, 1 -> read, 0 -> write) + }) + } + + //Disable rd0 write in decoding stage + when(decode.input(INSTRUCTION)(rdRange) === 0) { + decode.input(REGFILE_WRITE_VALID) := False + } + if(rv32e) when(decode.input(INSTRUCTION)(rdRange.head)) { + decode.input(REGFILE_WRITE_VALID) := False + } + + //Read register file + readStage plug new Area{ + import readStage._ + + //read register file + val srcInstruction = regFileReadyKind match{ + case `ASYNC` => input(INSTRUCTION) + case `SYNC` if !readInExecute => input(INSTRUCTION_ANTICIPATED) + case `SYNC` if readInExecute => if(syncUpdateOnStall) Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION)) else decode.input(INSTRUCTION) + } + + def shadowPrefix(that : Bits) = if(withShadow) global.shadow.read ## that else that + val regFileReadAddress1 = U(shadowPrefix(srcInstruction(clipRange(Riscv.rs1Range)))) + val regFileReadAddress2 = U(shadowPrefix(srcInstruction(clipRange(Riscv.rs2Range)))) + + val (rs1Data,rs2Data) = regFileReadyKind match{ + case `ASYNC` => (global.regFile.readAsync(regFileReadAddress1),global.regFile.readAsync(regFileReadAddress2)) + case `SYNC` => + val enable = if(!syncUpdateOnStall) !readStage.arbitration.isStuck else null + (global.regFile.readSync(regFileReadAddress1, enable),global.regFile.readSync(regFileReadAddress2, enable)) + } + + insert(RS1) := rs1Data + insert(RS2) := rs2Data + } + + //Write register file + writeStage plug new Area { + import writeStage._ + + def shadowPrefix(that : Bits) = if(withShadow) global.shadow.write ## that else that + val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public).setName("lastStageRegFileWrite") + regFileWrite.valid := output(REGFILE_WRITE_VALID) && arbitration.isFiring + regFileWrite.address := U(shadowPrefix(output(INSTRUCTION)(clipRange(rdRange)))) + regFileWrite.data := output(REGFILE_WRITE_DATA) + + //Ensure no boot glitches modify X0 + if(!x0Init && zeroBoot) when(regFileWrite.address === 0){ + regFileWrite.valid := False + } + + //CPU will initialise constant register zero in the first cycle + if(x0Init) { + val boot = RegNext(False) init (True) + regFileWrite.valid setWhen (boot) + when(boot) { + regFileWrite.address := 0 + regFileWrite.data := 0 + } + } + } + } +}
\ No newline at end of file |