Add shadow regfile

various cleaning
This commit is contained in:
Dolu1990 2018-11-16 17:06:11 +01:00
parent cc48fc7403
commit 75d4d049d7
7 changed files with 96 additions and 26 deletions

View File

@ -6,6 +6,7 @@ import spinal.lib._
import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4ReadOnly} import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4ReadOnly}
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig} import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig} import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
import vexriscv.demo.{SimpleBus, SimpleBusConfig}
case class InstructionCacheConfig( cacheSize : Int, case class InstructionCacheConfig( cacheSize : Int,
@ -45,6 +46,11 @@ case class InstructionCacheConfig( cacheSize : Int,
constantBurstBehavior = true constantBurstBehavior = true
) )
def getSimpleBusConfig() = SimpleBusConfig(
addressWidth = 32,
dataWidth = 32
)
def getWishboneConfig() = WishboneConfig( def getWishboneConfig() = WishboneConfig(
addressWidth = 30, addressWidth = 30,
dataWidth = 32, dataWidth = 32,
@ -178,6 +184,24 @@ case class InstructionCacheMemBus(p : InstructionCacheConfig) extends Bundle wit
mm mm
} }
def toSimpleBus(): SimpleBus = {
val simpleBusConfig = p.getSimpleBusConfig()
val bus = SimpleBus(simpleBusConfig)
val counter = Counter(p.burstSize, bus.cmd.fire)
bus.cmd.valid := cmd.valid
bus.cmd.address := cmd.address(31 downto widthOf(counter.value) + 2) @@ counter @@ U"00"
bus.cmd.wr := False
bus.cmd.mask.assignDontCare()
bus.cmd.data.assignDontCare()
cmd.ready := counter.willOverflow
rsp.valid := bus.rsp.valid
rsp.data := bus.rsp.payload.data
rsp.error := False
bus
}
def toWishbone(): Wishbone = { def toWishbone(): Wishbone = {
val wishboneConfig = p.getWishboneConfig() val wishboneConfig = p.getWishboneConfig()
val bus = Wishbone(wishboneConfig) val bus = Wishbone(wishboneConfig)

View File

@ -200,7 +200,8 @@ trait CsrInterface{
} }
def rw(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) rw(csrAddress,that._1, that._2) def rw(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) rw(csrAddress,that._1, that._2)
def r [T <: Data](csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) r(csrAddress,that._1, that._2) def w(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) w(csrAddress,that._1, that._2)
def r(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) r(csrAddress,that._1, that._2)
def rw[T <: Data](csrAddress : Int, that : T): Unit = rw(csrAddress,0,that) def rw[T <: Data](csrAddress : Int, that : T): Unit = rw(csrAddress,0,that)
def w[T <: Data](csrAddress : Int, that : T): Unit = w(csrAddress,0,that) def w[T <: Data](csrAddress : Int, that : T): Unit = w(csrAddress,0,that)
def r [T <: Data](csrAddress : Int, that : T): Unit = r(csrAddress,0,that) def r [T <: Data](csrAddress : Int, that : T): Unit = r(csrAddress,0,that)

View File

@ -6,6 +6,7 @@ import spinal.lib._
import spinal.lib.bus.amba4.axi._ import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig} import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig} import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
import vexriscv.demo.SimpleBus
import vexriscv.ip.DataCacheMemCmd import vexriscv.ip.DataCacheMemCmd
@ -131,11 +132,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
mm.read := cmdStage.valid && !cmdStage.wr mm.read := cmdStage.valid && !cmdStage.wr
mm.write := cmdStage.valid && cmdStage.wr mm.write := cmdStage.valid && cmdStage.wr
mm.address := (cmdStage.address >> 2) @@ U"00" mm.address := (cmdStage.address >> 2) @@ U"00"
mm.writeData := cmdStage.size.mux ( mm.writeData := cmdStage.data(31 downto 0)
U(0) -> cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0),
U(1) -> cmdStage.data(15 downto 0) ## cmdStage.data(15 downto 0),
default -> cmdStage.data(31 downto 0)
)
mm.byteEnable := (cmdStage.size.mux ( mm.byteEnable := (cmdStage.size.mux (
U(0) -> B"0001", U(0) -> B"0001",
U(1) -> B"0011", U(1) -> B"0011",
@ -179,6 +176,25 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
rsp.error := False //TODO rsp.error := False //TODO
bus bus
} }
def toSimpleBus() : SimpleBus = {
val bus = SimpleBus(32,32)
bus.cmd.valid := cmd.valid
bus.cmd.wr := cmd.wr
bus.cmd.address := cmd.address.resized
bus.cmd.data := cmd.data
bus.cmd.mask := cmd.size.mux(
0 -> B"0001",
1 -> B"0011",
default -> B"1111"
) |<< cmd.address(1 downto 0)
cmd.ready := bus.cmd.ready
rsp.ready := bus.rsp.valid
rsp.data := bus.rsp.data
bus
}
} }
@ -311,9 +327,10 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
memoryExceptionPort.valid := True memoryExceptionPort.valid := True
} }
} }
when(!(arbitration.isValid && input(MEMORY_ENABLE))){ when(!(arbitration.isValid && input(MEMORY_ENABLE) && (if(cmdStage == rspStage) !arbitration.isStuckByOthers else True))){
memoryExceptionPort.valid := False memoryExceptionPort.valid := False
} }
memoryExceptionPort.badAddr := input(REGFILE_WRITE_DATA).asUInt //Drived by IntAluPlugin memoryExceptionPort.badAddr := input(REGFILE_WRITE_DATA).asUInt //Drived by IntAluPlugin
} }

View File

@ -6,6 +6,7 @@ import spinal.lib._
import spinal.lib.bus.amba4.axi._ import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig} import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig} import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
import vexriscv.demo.SimpleBus
@ -135,6 +136,18 @@ case class IBusSimpleBus(interfaceKeepData : Boolean = false) extends Bundle wit
bus bus
} }
def toSimpleBus(): SimpleBus = {
val bus = SimpleBus(32,32)
bus.cmd.arbitrationFrom(cmd)
bus.cmd.address := cmd.pc.resized
bus.cmd.wr := False
bus.cmd.mask.assignDontCare()
bus.cmd.data.assignDontCare()
rsp.valid := bus.rsp.valid
rsp.inst := bus.rsp.payload.data
rsp.error := False
bus
}
} }
@ -202,8 +215,9 @@ class IBusSimplePlugin(resetVector : BigInt,
cmd.valid := stage.input.valid && pendingCmd =/= pendingMax && !stages.map(_.arbitration.isValid).orR cmd.valid := stage.input.valid && pendingCmd =/= pendingMax && !stages.map(_.arbitration.isValid).orR
assert(injectorStage == false) assert(injectorStage == false)
assert(iBusRsp.stages.dropWhile(_ != stage).length <= 2) assert(iBusRsp.stages.dropWhile(_ != stage).length <= 2)
}else }else {
cmd.valid := stage.input.valid && stage.output.ready && pendingCmd =/= pendingMax cmd.valid := stage.input.valid && stage.output.ready && pendingCmd =/= pendingMax
}
cmd.pc := stage.input.payload(31 downto 2) @@ "00" cmd.pc := stage.input.payload(31 downto 2) @@ "00"
} else new Area{ } else new Area{
//This implementation keep the cmd on the bus until it's executed, even if the pipeline is flushed //This implementation keep the cmd on the bus until it's executed, even if the pipeline is flushed

View File

@ -11,17 +11,17 @@ trait RegFileReadKind
object ASYNC extends RegFileReadKind object ASYNC extends RegFileReadKind
object SYNC extends RegFileReadKind object SYNC extends RegFileReadKind
class RegFilePlugin(regFileReadyKind : RegFileReadKind, class RegFilePlugin(regFileReadyKind : RegFileReadKind,
zeroBoot : Boolean = false, zeroBoot : Boolean = false,
x0Init : Boolean = true, x0Init : Boolean = true,
writeRfInMemoryStage : Boolean = false, writeRfInMemoryStage : Boolean = false,
readInExecute : Boolean = false, readInExecute : Boolean = false,
syncUpdateOnStall : Boolean = true) extends Plugin[VexRiscv] with RegFileService{ syncUpdateOnStall : Boolean = true,
withShadow : Boolean = false //shadow registers aren't transition hazard free
) extends Plugin[VexRiscv] with RegFileService{
import Riscv._ import Riscv._
// assert(!writeRfInMemoryStage)
override def readStage(): Stage = if(readInExecute) pipeline.execute else pipeline.decode override def readStage(): Stage = if(readInExecute) pipeline.execute else pipeline.decode
override def setup(pipeline: VexRiscv): Unit = { override def setup(pipeline: VexRiscv): Unit = {
@ -36,9 +36,23 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
import pipeline._ import pipeline._
import pipeline.config._ import pipeline.config._
val readStage = if(readInExecute) execute else decode
val writeStage = if(writeRfInMemoryStage) memory else stages.last
val global = pipeline plug new Area{ val global = pipeline plug new Area{
val regFile = Mem(Bits(32 bits),32) addAttribute(Verilator.public) val regFileSize = if(withShadow) 64 else 32
if(zeroBoot) regFile.init(List.fill(32)(B(0, 32 bits))) 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 //Disable rd0 write in decoding stage
@ -47,7 +61,6 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
} }
//Read register file //Read register file
val readStage = if(readInExecute) execute else decode
readStage plug new Area{ readStage plug new Area{
import readStage._ import readStage._
@ -58,8 +71,9 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
case `SYNC` if readInExecute => if(syncUpdateOnStall) Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION)) else decode.input(INSTRUCTION) case `SYNC` if readInExecute => if(syncUpdateOnStall) Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION)) else decode.input(INSTRUCTION)
} }
val regFileReadAddress1 = srcInstruction(Riscv.rs1Range).asUInt def shadowPrefix(that : Bits) = if(withShadow) global.shadow.read ## that else that
val regFileReadAddress2 = srcInstruction(Riscv.rs2Range).asUInt val regFileReadAddress1 = U(shadowPrefix(srcInstruction(Riscv.rs1Range)))
val regFileReadAddress2 = U(shadowPrefix(srcInstruction(Riscv.rs2Range)))
val (rs1Data,rs2Data) = regFileReadyKind match{ val (rs1Data,rs2Data) = regFileReadyKind match{
case `ASYNC` => (global.regFile.readAsync(regFileReadAddress1),global.regFile.readAsync(regFileReadAddress2)) case `ASYNC` => (global.regFile.readAsync(regFileReadAddress1),global.regFile.readAsync(regFileReadAddress2))
@ -73,13 +87,13 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
} }
//Write register file //Write register file
val writeStage = if(writeRfInMemoryStage) memory else stages.last
writeStage plug new Area { writeStage plug new Area {
import writeStage._ import writeStage._
def shadowPrefix(that : Bits) = if(withShadow) global.shadow.write ## that else that
val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public) val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public)
regFileWrite.valid := output(REGFILE_WRITE_VALID) && arbitration.isFiring regFileWrite.valid := output(REGFILE_WRITE_VALID) && arbitration.isFiring
regFileWrite.address := output(INSTRUCTION)(rdRange).asUInt regFileWrite.address := U(shadowPrefix(output(INSTRUCTION)(rdRange)))
regFileWrite.data := output(REGFILE_WRITE_DATA) regFileWrite.data := output(REGFILE_WRITE_DATA)
//CPU will initialise constant register zero in the first cycle //CPU will initialise constant register zero in the first cycle