parent
cc48fc7403
commit
75d4d049d7
|
@ -6,6 +6,7 @@ import spinal.lib._
|
|||
import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4ReadOnly}
|
||||
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
||||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||
import vexriscv.demo.{SimpleBus, SimpleBusConfig}
|
||||
|
||||
|
||||
case class InstructionCacheConfig( cacheSize : Int,
|
||||
|
@ -45,6 +46,11 @@ case class InstructionCacheConfig( cacheSize : Int,
|
|||
constantBurstBehavior = true
|
||||
)
|
||||
|
||||
def getSimpleBusConfig() = SimpleBusConfig(
|
||||
addressWidth = 32,
|
||||
dataWidth = 32
|
||||
)
|
||||
|
||||
def getWishboneConfig() = WishboneConfig(
|
||||
addressWidth = 30,
|
||||
dataWidth = 32,
|
||||
|
@ -178,6 +184,24 @@ case class InstructionCacheMemBus(p : InstructionCacheConfig) extends Bundle wit
|
|||
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 = {
|
||||
val wishboneConfig = p.getWishboneConfig()
|
||||
val bus = Wishbone(wishboneConfig)
|
||||
|
|
|
@ -200,7 +200,8 @@ trait CsrInterface{
|
|||
}
|
||||
|
||||
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 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)
|
||||
|
|
|
@ -6,6 +6,7 @@ import spinal.lib._
|
|||
import spinal.lib.bus.amba4.axi._
|
||||
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
||||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||
import vexriscv.demo.SimpleBus
|
||||
import vexriscv.ip.DataCacheMemCmd
|
||||
|
||||
|
||||
|
@ -131,11 +132,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
|||
mm.read := cmdStage.valid && !cmdStage.wr
|
||||
mm.write := cmdStage.valid && cmdStage.wr
|
||||
mm.address := (cmdStage.address >> 2) @@ U"00"
|
||||
mm.writeData := cmdStage.size.mux (
|
||||
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.writeData := cmdStage.data(31 downto 0)
|
||||
mm.byteEnable := (cmdStage.size.mux (
|
||||
U(0) -> B"0001",
|
||||
U(1) -> B"0011",
|
||||
|
@ -179,6 +176,25 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
|||
rsp.error := False //TODO
|
||||
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
|
||||
}
|
||||
}
|
||||
when(!(arbitration.isValid && input(MEMORY_ENABLE))){
|
||||
when(!(arbitration.isValid && input(MEMORY_ENABLE) && (if(cmdStage == rspStage) !arbitration.isStuckByOthers else True))){
|
||||
memoryExceptionPort.valid := False
|
||||
}
|
||||
|
||||
memoryExceptionPort.badAddr := input(REGFILE_WRITE_DATA).asUInt //Drived by IntAluPlugin
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import spinal.lib._
|
|||
import spinal.lib.bus.amba4.axi._
|
||||
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
assert(injectorStage == false)
|
||||
assert(iBusRsp.stages.dropWhile(_ != stage).length <= 2)
|
||||
}else
|
||||
}else {
|
||||
cmd.valid := stage.input.valid && stage.output.ready && pendingCmd =/= pendingMax
|
||||
}
|
||||
cmd.pc := stage.input.payload(31 downto 2) @@ "00"
|
||||
} else new Area{
|
||||
//This implementation keep the cmd on the bus until it's executed, even if the pipeline is flushed
|
||||
|
|
|
@ -11,17 +11,17 @@ 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) 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._
|
||||
|
||||
// assert(!writeRfInMemoryStage)
|
||||
|
||||
|
||||
override def readStage(): Stage = if(readInExecute) pipeline.execute else pipeline.decode
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
|
@ -36,9 +36,23 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
|
|||
import pipeline._
|
||||
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 regFile = Mem(Bits(32 bits),32) addAttribute(Verilator.public)
|
||||
if(zeroBoot) regFile.init(List.fill(32)(B(0, 32 bits)))
|
||||
val regFileSize = if(withShadow) 64 else 32
|
||||
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
|
||||
|
@ -47,7 +61,6 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
|
|||
}
|
||||
|
||||
//Read register file
|
||||
val readStage = if(readInExecute) execute else decode
|
||||
readStage plug new Area{
|
||||
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)
|
||||
}
|
||||
|
||||
val regFileReadAddress1 = srcInstruction(Riscv.rs1Range).asUInt
|
||||
val regFileReadAddress2 = srcInstruction(Riscv.rs2Range).asUInt
|
||||
def shadowPrefix(that : Bits) = if(withShadow) global.shadow.read ## that else that
|
||||
val regFileReadAddress1 = U(shadowPrefix(srcInstruction(Riscv.rs1Range)))
|
||||
val regFileReadAddress2 = U(shadowPrefix(srcInstruction(Riscv.rs2Range)))
|
||||
|
||||
val (rs1Data,rs2Data) = regFileReadyKind match{
|
||||
case `ASYNC` => (global.regFile.readAsync(regFileReadAddress1),global.regFile.readAsync(regFileReadAddress2))
|
||||
|
@ -73,13 +87,13 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
|
|||
}
|
||||
|
||||
//Write register file
|
||||
val writeStage = if(writeRfInMemoryStage) memory else stages.last
|
||||
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)
|
||||
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)
|
||||
|
||||
//CPU will initialise constant register zero in the first cycle
|
||||
|
|
Loading…
Reference in New Issue