parent
51058f851e
commit
787682d4f6
|
@ -6,7 +6,7 @@ import spinal.core._
|
||||||
import spinal.lib._
|
import spinal.lib._
|
||||||
|
|
||||||
trait BranchPrediction
|
trait BranchPrediction
|
||||||
object DISABLE extends BranchPrediction
|
object NONE extends BranchPrediction
|
||||||
object STATIC extends BranchPrediction
|
object STATIC extends BranchPrediction
|
||||||
object DYNAMIC extends BranchPrediction
|
object DYNAMIC extends BranchPrediction
|
||||||
|
|
||||||
|
@ -58,13 +58,13 @@ class BranchPlugin(earlyBranch : Boolean,prediction : BranchPrediction,historyRa
|
||||||
BGEU -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True))
|
BGEU -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True))
|
||||||
))
|
))
|
||||||
|
|
||||||
val pcManagerService = pipeline.service(classOf[PcManagerService])
|
val pcManagerService = pipeline.service(classOf[JumpService])
|
||||||
jumpInterface = pcManagerService.createJumpInterface(pipeline.execute)
|
jumpInterface = pcManagerService.createJumpInterface(pipeline.execute)
|
||||||
if(prediction != DISABLE) predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.decode)
|
if(prediction != NONE) predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.decode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def build(pipeline: VexRiscv): Unit = prediction match {
|
override def build(pipeline: VexRiscv): Unit = prediction match {
|
||||||
case `DISABLE` => buildWithoutPrediction(pipeline)
|
case NONE => buildWithoutPrediction(pipeline)
|
||||||
case `STATIC` => buildWithPrediction(pipeline)
|
case `STATIC` => buildWithPrediction(pipeline)
|
||||||
case `DYNAMIC` => buildWithPrediction(pipeline)
|
case `DYNAMIC` => buildWithPrediction(pipeline)
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,7 @@ class BranchPlugin(earlyBranch : Boolean,prediction : BranchPrediction,historyRa
|
||||||
import pipeline._
|
import pipeline._
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
|
|
||||||
|
//Do branch calculations (conditions + target PC)
|
||||||
execute plug new Area {
|
execute plug new Area {
|
||||||
import execute._
|
import execute._
|
||||||
|
|
||||||
|
@ -101,6 +102,7 @@ class BranchPlugin(earlyBranch : Boolean,prediction : BranchPrediction,historyRa
|
||||||
insert(BRANCH_CALC) := branch_src1 + branch_src2
|
insert(BRANCH_CALC) := branch_src1 + branch_src2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Apply branchs (JAL,JALR, Bxx)
|
||||||
val branchStage = if(earlyBranch) execute else memory
|
val branchStage = if(earlyBranch) execute else memory
|
||||||
branchStage plug new Area {
|
branchStage plug new Area {
|
||||||
import branchStage._
|
import branchStage._
|
||||||
|
@ -140,7 +142,8 @@ class BranchPlugin(earlyBranch : Boolean,prediction : BranchPrediction,historyRa
|
||||||
fetch.insert(HISTORY_LINE) := writePortReg.data
|
fetch.insert(HISTORY_LINE) := writePortReg.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Branch JAL, predict Bxx and branch it
|
||||||
decode plug new Area{
|
decode plug new Area{
|
||||||
import decode._
|
import decode._
|
||||||
val imm = IMM(input(INSTRUCTION))
|
val imm = IMM(input(INSTRUCTION))
|
||||||
|
@ -158,6 +161,7 @@ class BranchPlugin(earlyBranch : Boolean,prediction : BranchPrediction,historyRa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Do real branch calculation
|
||||||
execute plug new Area {
|
execute plug new Area {
|
||||||
import execute._
|
import execute._
|
||||||
|
|
||||||
|
@ -194,9 +198,9 @@ class BranchPlugin(earlyBranch : Boolean,prediction : BranchPrediction,historyRa
|
||||||
insert(BRANCH_CALC) := branch_src1 + branch_src2
|
insert(BRANCH_CALC) := branch_src1 + branch_src2
|
||||||
}
|
}
|
||||||
|
|
||||||
val branchStage = if(earlyBranch) execute else memory
|
|
||||||
|
|
||||||
// Apply branch corrections
|
// branch JALR or JAL/Bxx prediction miss corrections
|
||||||
|
val branchStage = if(earlyBranch) execute else memory
|
||||||
branchStage plug new Area {
|
branchStage plug new Area {
|
||||||
import branchStage._
|
import branchStage._
|
||||||
jumpInterface.valid := input(BRANCH_DO) && arbitration.isFiring
|
jumpInterface.valid := input(BRANCH_DO) && arbitration.isFiring
|
||||||
|
|
|
@ -75,6 +75,7 @@ class DBusSimplePlugin extends Plugin[VexRiscv]{
|
||||||
import pipeline._
|
import pipeline._
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
|
|
||||||
|
//Emit dCmd request
|
||||||
execute plug new Area{
|
execute plug new Area{
|
||||||
import execute._
|
import execute._
|
||||||
|
|
||||||
|
@ -95,6 +96,7 @@ class DBusSimplePlugin extends Plugin[VexRiscv]{
|
||||||
insert(MEMORY_ADDRESS_LOW) := dCmd.address(1 downto 0)
|
insert(MEMORY_ADDRESS_LOW) := dCmd.address(1 downto 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Collect dRsp read responses
|
||||||
memory plug new Area {
|
memory plug new Area {
|
||||||
import memory._
|
import memory._
|
||||||
|
|
||||||
|
@ -103,6 +105,7 @@ class DBusSimplePlugin extends Plugin[VexRiscv]{
|
||||||
assert(!(input(MEMORY_ENABLE) && (!input(INSTRUCTION)(5)) && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend")
|
assert(!(input(MEMORY_ENABLE) && (!input(INSTRUCTION)(5)) && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Reformat read responses, REGFILE_WRITE_DATA overriding
|
||||||
writeBack plug new Area {
|
writeBack plug new Area {
|
||||||
import writeBack._
|
import writeBack._
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ class DivPlugin extends Plugin[VexRiscv]{
|
||||||
|
|
||||||
val divider = new MixedDivider(32, 32, true) //cmd >-> rsp
|
val divider = new MixedDivider(32, 32, true) //cmd >-> rsp
|
||||||
|
|
||||||
|
//Send request to the divider component
|
||||||
execute plug new Area {
|
execute plug new Area {
|
||||||
import execute._
|
import execute._
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@ class DivPlugin extends Plugin[VexRiscv]{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Collect response from the divider component, REGFILE_WRITE_DATA overriding
|
||||||
memory plug new Area{
|
memory plug new Area{
|
||||||
import memory._
|
import memory._
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,14 @@ class IBusSimplePlugin(interfaceKeepData : Boolean) extends Plugin[VexRiscv]{
|
||||||
import pipeline._
|
import pipeline._
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
|
|
||||||
|
//Emit iCmd request
|
||||||
require(interfaceKeepData)
|
require(interfaceKeepData)
|
||||||
iCmd = master(Stream(IBusSimpleCmd())).setName("iCmd")
|
iCmd = master(Stream(IBusSimpleCmd())).setName("iCmd")
|
||||||
iCmd.valid := prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers
|
iCmd.valid := prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers
|
||||||
iCmd.pc := prefetch.output(PC)
|
iCmd.pc := prefetch.output(PC)
|
||||||
prefetch.arbitration.haltIt setWhen(!iCmd.ready)
|
prefetch.arbitration.haltIt setWhen(!iCmd.ready)
|
||||||
|
|
||||||
|
//Insert iRsp into INSTRUCTION
|
||||||
iRsp = in(IBusSimpleRsp()).setName("iRsp")
|
iRsp = in(IBusSimpleRsp()).setName("iRsp")
|
||||||
fetch.insert(INSTRUCTION) := iRsp.inst
|
fetch.insert(INSTRUCTION) := iRsp.inst
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ class MulPlugin extends Plugin[VexRiscv]{
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
|
|
||||||
|
|
||||||
|
//Do partial multiplication, four times 16 bits * 16 bits
|
||||||
execute plug new Area {
|
execute plug new Area {
|
||||||
import execute._
|
import execute._
|
||||||
val aSigned,bSigned = Bool
|
val aSigned,bSigned = Bool
|
||||||
|
@ -78,12 +78,13 @@ class MulPlugin extends Plugin[VexRiscv]{
|
||||||
insert(MUL_HH) := aHigh * bHigh
|
insert(MUL_HH) := aHigh * bHigh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//First aggregation of partial multiplication
|
||||||
memory plug new Area {
|
memory plug new Area {
|
||||||
import memory._
|
import memory._
|
||||||
insert(MUL_LOW) := S(0, MUL_HL.dataType.getWidth + 16 + 2 bit) + (False ## input(MUL_LL)).asSInt + (input(MUL_LH) << 16) + (input(MUL_HL) << 16)
|
insert(MUL_LOW) := S(0, MUL_HL.dataType.getWidth + 16 + 2 bit) + (False ## input(MUL_LL)).asSInt + (input(MUL_LH) << 16) + (input(MUL_HL) << 16)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Final aggregation of partial multiplications, REGFILE_WRITE_DATA overriding
|
||||||
writeBack plug new Area {
|
writeBack plug new Area {
|
||||||
import writeBack._
|
import writeBack._
|
||||||
val result = input(MUL_LOW) + (input(MUL_HH) << 32)
|
val result = input(MUL_LOW) + (input(MUL_HH) << 32)
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package SpinalRiscv.Plugin
|
package SpinalRiscv.Plugin
|
||||||
|
|
||||||
import SpinalRiscv.{PcManagerService, Stage, VexRiscv}
|
import SpinalRiscv.{JumpService, Stage, VexRiscv}
|
||||||
import spinal.core._
|
import spinal.core._
|
||||||
import spinal.lib._
|
import spinal.lib._
|
||||||
|
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
class PcManagerSimplePlugin(resetVector : BigInt,fastPcCalculation : Boolean) extends Plugin[VexRiscv] with PcManagerService{
|
class PcManagerSimplePlugin(resetVector : BigInt,fastPcCalculation : Boolean) extends Plugin[VexRiscv] with JumpService{
|
||||||
|
|
||||||
|
|
||||||
//FetchService interface
|
//FetchService interface
|
||||||
|
@ -29,19 +29,19 @@ class PcManagerSimplePlugin(resetVector : BigInt,fastPcCalculation : Boolean) ex
|
||||||
arbitration.isValid := True
|
arbitration.isValid := True
|
||||||
|
|
||||||
//PC calculation without Jump
|
//PC calculation without Jump
|
||||||
val pc = Reg(UInt(pcWidth bits)) init(resetVector) addAttribute("verilator public")
|
val pcReg = Reg(UInt(pcWidth bits)) init(resetVector) addAttribute("verilator public")
|
||||||
val inc = RegInit(False)
|
val inc = RegInit(False)
|
||||||
val pcNext = if(fastPcCalculation){
|
val pc = if(fastPcCalculation){
|
||||||
val pcPlus4 = pc + U(4)
|
val pcPlus4 = pcReg + U(4)
|
||||||
pcPlus4.addAttribute("keep")
|
pcPlus4.addAttribute("keep")
|
||||||
Mux(inc,pcPlus4,pc)
|
Mux(inc,pcPlus4,pcReg)
|
||||||
}else{
|
}else{
|
||||||
pc + Mux(inc,U(4),U(0))
|
pcReg + Mux[UInt](inc,4,0)
|
||||||
}
|
}
|
||||||
|
|
||||||
val samplePcNext = False
|
val samplePcNext = False
|
||||||
|
|
||||||
//FetchService hardware implementation
|
//JumpService hardware implementation
|
||||||
val jump = if(jumpInfos.length != 0) new Area {
|
val jump = if(jumpInfos.length != 0) new Area {
|
||||||
val sortedByStage = jumpInfos.sortWith((a, b) => pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage))
|
val sortedByStage = jumpInfos.sortWith((a, b) => pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage))
|
||||||
val valids = sortedByStage.map(_.interface.valid)
|
val valids = sortedByStage.map(_.interface.valid)
|
||||||
|
@ -51,11 +51,11 @@ class PcManagerSimplePlugin(resetVector : BigInt,fastPcCalculation : Boolean) ex
|
||||||
pcLoad.valid := jumpInfos.foldLeft(False)(_ || _.interface.valid)
|
pcLoad.valid := jumpInfos.foldLeft(False)(_ || _.interface.valid)
|
||||||
pcLoad.payload := MuxOH(valids, pcs)
|
pcLoad.payload := MuxOH(valids, pcs)
|
||||||
|
|
||||||
//Register managments
|
//application of the selected jump request
|
||||||
when(pcLoad.valid) {
|
when(pcLoad.valid) {
|
||||||
inc := False
|
inc := False
|
||||||
samplePcNext := True
|
samplePcNext := True
|
||||||
pcNext := pcLoad.payload
|
pc := pcLoad.payload
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,10 +64,9 @@ class PcManagerSimplePlugin(resetVector : BigInt,fastPcCalculation : Boolean) ex
|
||||||
samplePcNext := True
|
samplePcNext := True
|
||||||
}
|
}
|
||||||
|
|
||||||
when(samplePcNext) { pc := pcNext }
|
when(samplePcNext) { pcReg := pc }
|
||||||
|
|
||||||
//Pipeline insertions
|
insert(PC) := pc
|
||||||
insert(PC) := pcNext
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,6 +27,7 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind) extends Plugin[VexRiscv]
|
||||||
val regFile = Mem(Bits(32 bits),32) addAttribute("verilator public")
|
val regFile = Mem(Bits(32 bits),32) addAttribute("verilator public")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Read register file
|
||||||
decode plug new Area{
|
decode plug new Area{
|
||||||
import decode._
|
import decode._
|
||||||
|
|
||||||
|
@ -35,9 +36,6 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind) extends Plugin[VexRiscv]
|
||||||
decode.input(REGFILE_WRITE_VALID) := False
|
decode.input(REGFILE_WRITE_VALID) := False
|
||||||
}
|
}
|
||||||
|
|
||||||
val rs1 = input(INSTRUCTION)(Riscv.rs1Range).asUInt
|
|
||||||
val rs2 = input(INSTRUCTION)(Riscv.rs2Range).asUInt
|
|
||||||
|
|
||||||
//read register file
|
//read register file
|
||||||
val srcInstruction = regFileReadyKind match{
|
val srcInstruction = regFileReadyKind match{
|
||||||
case `ASYNC` => input(INSTRUCTION)
|
case `ASYNC` => input(INSTRUCTION)
|
||||||
|
@ -56,6 +54,7 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind) extends Plugin[VexRiscv]
|
||||||
insert(REG2) := rs2Data
|
insert(REG2) := rs2Data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Write register file
|
||||||
writeBack plug new Area {
|
writeBack plug new Area {
|
||||||
import writeBack._
|
import writeBack._
|
||||||
|
|
||||||
|
@ -64,7 +63,7 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind) extends Plugin[VexRiscv]
|
||||||
regFileWrite.address := input(INSTRUCTION)(rdRange).asUInt
|
regFileWrite.address := input(INSTRUCTION)(rdRange).asUInt
|
||||||
regFileWrite.data := input(REGFILE_WRITE_DATA)
|
regFileWrite.data := input(REGFILE_WRITE_DATA)
|
||||||
|
|
||||||
//CPU will write constant register zero in the first cycle
|
//CPU will initialise constant register zero in the first cycle
|
||||||
regFileWrite.valid setWhen(RegNext(False) init(True))
|
regFileWrite.valid setWhen(RegNext(False) init(True))
|
||||||
inputInit[Bits](REGFILE_WRITE_DATA, 0)
|
inputInit[Bits](REGFILE_WRITE_DATA, 0)
|
||||||
inputInit[Bits](INSTRUCTION, 0)
|
inputInit[Bits](INSTRUCTION, 0)
|
||||||
|
|
|
@ -3,7 +3,7 @@ package SpinalRiscv
|
||||||
import spinal.core._
|
import spinal.core._
|
||||||
import spinal.lib._
|
import spinal.lib._
|
||||||
|
|
||||||
trait PcManagerService{
|
trait JumpService{
|
||||||
def createJumpInterface(stage : Stage) : Flow[UInt]
|
def createJumpInterface(stage : Stage) : Flow[UInt]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,25 +64,4 @@ class Stage() extends Area{
|
||||||
|
|
||||||
def inputInit[T <: BaseType](stageable : Stageable[T],initValue : T) =
|
def inputInit[T <: BaseType](stageable : Stageable[T],initValue : T) =
|
||||||
Component.current.addPrePopTask(() => inputsDefault(stageable.asInstanceOf[Stageable[Data]]).asInstanceOf[T].getDrivingReg.init(initValue))
|
Component.current.addPrePopTask(() => inputsDefault(stageable.asInstanceOf[Stageable[Data]]).asInstanceOf[T].getDrivingReg.init(initValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//object StageMain{
|
|
||||||
//
|
|
||||||
// object OpEnum extends SpinalEnum{
|
|
||||||
// val AND,OR = newElement()
|
|
||||||
// }
|
|
||||||
// object OP extends Stageable(OpEnum())
|
|
||||||
// object SRC1 extends Stageable(Bits(32 bits))
|
|
||||||
// object SRC2 extends Stageable(Bits(32 bits))
|
|
||||||
// object RESULT extends Stageable(Bits(32 bits))
|
|
||||||
// def main(args: Array[String]) {
|
|
||||||
// val E = List.fill(2)(new Stage(9))
|
|
||||||
// val E0 = E(0)
|
|
||||||
// import E0._
|
|
||||||
// output(RESULT) := E(0).input(OP).mux(
|
|
||||||
// OpEnum.AND -> (E(0).input(SRC1) & E(0).input(SRC2)),
|
|
||||||
// OpEnum.OR -> (E(0).input(SRC1) | E(0).input(SRC2))
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
//}
|
|
|
@ -358,7 +358,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void postReset() {
|
virtual void postReset() {
|
||||||
top->VexRiscv->prefetch_PcManagerSimplePlugin_pc = 0x800000bcu;
|
top->VexRiscv->prefetch_PcManagerSimplePlugin_pcReg = 0x800000bcu;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void checks(){
|
virtual void checks(){
|
||||||
|
|
Loading…
Reference in New Issue