mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-01-03 03:43:39 -05:00
PcPlugin change fastPcCalculation into relaxedPcCalculation
relaxedPcCalculation relax timings on the IBusSimple address => better FMax when the CPU is integrated into a SoC
This commit is contained in:
parent
3b66d986a8
commit
e8aa828744
12 changed files with 124 additions and 81 deletions
|
@ -262,7 +262,7 @@ val cpu = new VexRiscv(
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(
|
new PcManagerSimplePlugin(
|
||||||
resetVector = 0x00000000l,
|
resetVector = 0x00000000l,
|
||||||
fastPcCalculation = true
|
relaxedPcCalculation = true
|
||||||
),
|
),
|
||||||
new IBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
interfaceKeepData = false,
|
interfaceKeepData = false,
|
||||||
|
|
|
@ -31,62 +31,65 @@ object TestsWorkspace {
|
||||||
SpinalVerilog {
|
SpinalVerilog {
|
||||||
val configFull = VexRiscvConfig(
|
val configFull = VexRiscvConfig(
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(0x00000000l, false),
|
new PcManagerSimplePlugin(
|
||||||
// new IBusSimplePlugin(
|
resetVector = 0x00000000l,
|
||||||
// interfaceKeepData = false,
|
relaxedPcCalculation = true
|
||||||
// catchAccessFault = true
|
|
||||||
// ),
|
|
||||||
new IBusCachedPlugin(
|
|
||||||
config = InstructionCacheConfig(
|
|
||||||
cacheSize = 4096,
|
|
||||||
bytePerLine =32,
|
|
||||||
wayCount = 1,
|
|
||||||
wrappedMemAccess = true,
|
|
||||||
addressWidth = 32,
|
|
||||||
cpuDataWidth = 32,
|
|
||||||
memDataWidth = 32,
|
|
||||||
catchIllegalAccess = true,
|
|
||||||
catchAccessFault = true,
|
|
||||||
catchMemoryTranslationMiss = true,
|
|
||||||
asyncTagMemory = false,
|
|
||||||
twoStageLogic = true
|
|
||||||
),
|
|
||||||
askMemoryTranslation = true,
|
|
||||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
|
||||||
portTlbSize = 4
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
// new DBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
// catchAddressMisaligned = true,
|
interfaceKeepData = false,
|
||||||
// catchAccessFault = true,
|
catchAccessFault = true
|
||||||
// earlyInjection = false
|
|
||||||
// ),
|
|
||||||
new DBusCachedPlugin(
|
|
||||||
config = new DataCacheConfig(
|
|
||||||
cacheSize = 4096,
|
|
||||||
bytePerLine = 32,
|
|
||||||
wayCount = 1,
|
|
||||||
addressWidth = 32,
|
|
||||||
cpuDataWidth = 32,
|
|
||||||
memDataWidth = 32,
|
|
||||||
catchAccessError = true,
|
|
||||||
catchIllegal = true,
|
|
||||||
catchUnaligned = true,
|
|
||||||
catchMemoryTranslationMiss = true
|
|
||||||
),
|
|
||||||
// memoryTranslatorPortConfig = null
|
|
||||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
|
||||||
portTlbSize = 6
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
|
// new IBusCachedPlugin(
|
||||||
|
// config = InstructionCacheConfig(
|
||||||
|
// cacheSize = 4096,
|
||||||
|
// bytePerLine =32,
|
||||||
|
// wayCount = 1,
|
||||||
|
// wrappedMemAccess = true,
|
||||||
|
// addressWidth = 32,
|
||||||
|
// cpuDataWidth = 32,
|
||||||
|
// memDataWidth = 32,
|
||||||
|
// catchIllegalAccess = true,
|
||||||
|
// catchAccessFault = true,
|
||||||
|
// catchMemoryTranslationMiss = true,
|
||||||
|
// asyncTagMemory = false,
|
||||||
|
// twoStageLogic = true
|
||||||
|
// ),
|
||||||
|
// askMemoryTranslation = true,
|
||||||
|
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||||
|
// portTlbSize = 4
|
||||||
|
// )
|
||||||
|
// ),
|
||||||
|
new DBusSimplePlugin(
|
||||||
|
catchAddressMisaligned = true,
|
||||||
|
catchAccessFault = true,
|
||||||
|
earlyInjection = false
|
||||||
|
),
|
||||||
|
// new DBusCachedPlugin(
|
||||||
|
// config = new DataCacheConfig(
|
||||||
|
// cacheSize = 4096,
|
||||||
|
// bytePerLine = 32,
|
||||||
|
// wayCount = 1,
|
||||||
|
// addressWidth = 32,
|
||||||
|
// cpuDataWidth = 32,
|
||||||
|
// memDataWidth = 32,
|
||||||
|
// catchAccessError = true,
|
||||||
|
// catchIllegal = true,
|
||||||
|
// catchUnaligned = true,
|
||||||
|
// catchMemoryTranslationMiss = true
|
||||||
|
// ),
|
||||||
|
//// memoryTranslatorPortConfig = null
|
||||||
|
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||||
|
// portTlbSize = 6
|
||||||
|
// )
|
||||||
|
// ),
|
||||||
// new StaticMemoryTranslatorPlugin(
|
// new StaticMemoryTranslatorPlugin(
|
||||||
// ioRange = _(31 downto 28) === 0xF
|
// ioRange = _(31 downto 28) === 0xF
|
||||||
// ),
|
// ),
|
||||||
new MemoryTranslatorPlugin(
|
// new MemoryTranslatorPlugin(
|
||||||
tlbSize = 32,
|
// tlbSize = 32,
|
||||||
virtualRange = _(31 downto 28) === 0xC,
|
// virtualRange = _(31 downto 28) === 0xC,
|
||||||
ioRange = _(31 downto 28) === 0xF
|
// ioRange = _(31 downto 28) === 0xF
|
||||||
),
|
// ),
|
||||||
new DecoderSimplePlugin(
|
new DecoderSimplePlugin(
|
||||||
catchIllegalInstruction = true
|
catchIllegalInstruction = true
|
||||||
),
|
),
|
||||||
|
|
|
@ -14,7 +14,7 @@ object GenFull extends App{
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(
|
new PcManagerSimplePlugin(
|
||||||
resetVector = 0x00000000l,
|
resetVector = 0x00000000l,
|
||||||
fastPcCalculation = false
|
relaxedPcCalculation = false
|
||||||
),
|
),
|
||||||
new IBusCachedPlugin(
|
new IBusCachedPlugin(
|
||||||
config = InstructionCacheConfig(
|
config = InstructionCacheConfig(
|
||||||
|
|
|
@ -14,7 +14,7 @@ object GenFullNoMmu extends App{
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(
|
new PcManagerSimplePlugin(
|
||||||
resetVector = 0x00000000l,
|
resetVector = 0x00000000l,
|
||||||
fastPcCalculation = false
|
relaxedPcCalculation = false
|
||||||
),
|
),
|
||||||
new IBusCachedPlugin(
|
new IBusCachedPlugin(
|
||||||
config = InstructionCacheConfig(
|
config = InstructionCacheConfig(
|
||||||
|
|
|
@ -14,7 +14,7 @@ object GenFullNoMmuNoCache extends App{
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(
|
new PcManagerSimplePlugin(
|
||||||
resetVector = 0x00000000l,
|
resetVector = 0x00000000l,
|
||||||
fastPcCalculation = false
|
relaxedPcCalculation = false
|
||||||
),
|
),
|
||||||
new IBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
interfaceKeepData = false,
|
interfaceKeepData = false,
|
||||||
|
|
|
@ -13,7 +13,7 @@ object GenSmallAndProductive extends App{
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(
|
new PcManagerSimplePlugin(
|
||||||
resetVector = 0x00000000l,
|
resetVector = 0x00000000l,
|
||||||
fastPcCalculation = false
|
relaxedPcCalculation = false
|
||||||
),
|
),
|
||||||
new IBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
interfaceKeepData = false,
|
interfaceKeepData = false,
|
||||||
|
|
|
@ -13,7 +13,7 @@ object GenSmallest extends App{
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(
|
new PcManagerSimplePlugin(
|
||||||
resetVector = 0x00000000l,
|
resetVector = 0x00000000l,
|
||||||
fastPcCalculation = false
|
relaxedPcCalculation = false
|
||||||
),
|
),
|
||||||
new IBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
interfaceKeepData = false,
|
interfaceKeepData = false,
|
||||||
|
|
|
@ -13,7 +13,7 @@ object GenSmallestNoCsr extends App{
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(
|
new PcManagerSimplePlugin(
|
||||||
resetVector = 0x00000000l,
|
resetVector = 0x00000000l,
|
||||||
fastPcCalculation = false
|
relaxedPcCalculation = false
|
||||||
),
|
),
|
||||||
new IBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
interfaceKeepData = false,
|
interfaceKeepData = false,
|
||||||
|
|
|
@ -16,7 +16,8 @@ import vexriscv.{plugin, VexRiscvConfig, VexRiscv}
|
||||||
* Created by PIC32F_USER on 28/07/2017.
|
* Created by PIC32F_USER on 28/07/2017.
|
||||||
*
|
*
|
||||||
* Murax is a very light SoC which could work without any external component.
|
* Murax is a very light SoC which could work without any external component.
|
||||||
* Tested on ICE40-hx8k device, 60 Mhz, 2150 LC
|
* - ICE40-hx8k + icestorm => 53 Mhz, 2142 LC
|
||||||
|
* - 0.37 DMIPS/Mhz
|
||||||
* - 8 kB of on-chip ram
|
* - 8 kB of on-chip ram
|
||||||
* - JTAG debugger (eclipse/GDB/openocd ready)
|
* - JTAG debugger (eclipse/GDB/openocd ready)
|
||||||
* - Interrupt support
|
* - Interrupt support
|
||||||
|
@ -36,11 +37,11 @@ case class MuraxConfig(coreFrequency : HertzNumber,
|
||||||
|
|
||||||
object MuraxConfig{
|
object MuraxConfig{
|
||||||
def default = MuraxConfig(
|
def default = MuraxConfig(
|
||||||
coreFrequency = 12 MHz,
|
coreFrequency = 12 MHz,
|
||||||
onChipRamSize = 8 kB,
|
onChipRamSize = 8 kB,
|
||||||
pipelineDBus = false,
|
pipelineDBus = true,
|
||||||
pipelineMainBus = true,
|
pipelineMainBus = false,
|
||||||
pipelineApbBridge = false
|
pipelineApbBridge = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +131,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(
|
new PcManagerSimplePlugin(
|
||||||
resetVector = 0x00000000l,
|
resetVector = 0x00000000l,
|
||||||
fastPcCalculation = false
|
relaxedPcCalculation = true
|
||||||
),
|
),
|
||||||
new IBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
interfaceKeepData = false,
|
interfaceKeepData = false,
|
||||||
|
@ -138,7 +139,8 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
),
|
),
|
||||||
new DBusSimplePlugin(
|
new DBusSimplePlugin(
|
||||||
catchAddressMisaligned = false,
|
catchAddressMisaligned = false,
|
||||||
catchAccessFault = false
|
catchAccessFault = false,
|
||||||
|
earlyInjection = false
|
||||||
),
|
),
|
||||||
new CsrPlugin(CsrPluginConfig.smallest),
|
new CsrPlugin(CsrPluginConfig.smallest),
|
||||||
new DecoderSimplePlugin(
|
new DecoderSimplePlugin(
|
||||||
|
@ -186,7 +188,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
dBus = plugin.dBus
|
dBus = plugin.dBus
|
||||||
else {
|
else {
|
||||||
dBus = cloneOf(plugin.dBus)
|
dBus = cloneOf(plugin.dBus)
|
||||||
dBus.cmd <-< plugin.dBus.cmd
|
dBus.cmd << plugin.dBus.cmd.halfPipe()
|
||||||
dBus.rsp <> plugin.dBus.rsp
|
dBus.rsp <> plugin.dBus.rsp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean)
|
||||||
val pendingCmd = RegInit(False) clearWhen (iBus.rsp.ready) setWhen (iBus.cmd.fire)
|
val pendingCmd = RegInit(False) clearWhen (iBus.rsp.ready) setWhen (iBus.cmd.fire)
|
||||||
|
|
||||||
//Emit iBus.cmd request
|
//Emit iBus.cmd request
|
||||||
iBus.cmd.valid := prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers && !(pendingCmd && !iBus.rsp.ready) //prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers
|
iBus.cmd.valid := prefetch.arbitration.isValid && !prefetch.arbitration.removeIt && !prefetch.arbitration.isStuckByOthers && !(pendingCmd && !iBus.rsp.ready) //prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers
|
||||||
iBus.cmd.pc := prefetch.output(PC)
|
iBus.cmd.pc := prefetch.output(PC)
|
||||||
prefetch.arbitration.haltIt setWhen (!iBus.cmd.ready || (pendingCmd && !iBus.rsp.ready))
|
prefetch.arbitration.haltIt setWhen (!iBus.cmd.ready || (pendingCmd && !iBus.rsp.ready))
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import spinal.lib._
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
class PcManagerSimplePlugin(resetVector : BigInt,
|
class PcManagerSimplePlugin(resetVector : BigInt,
|
||||||
fastPcCalculation : Boolean = false) extends Plugin[VexRiscv] with JumpService{
|
relaxedPcCalculation : Boolean = false) extends Plugin[VexRiscv] with JumpService{
|
||||||
//FetchService interface
|
//FetchService interface
|
||||||
case class JumpInfo(interface : Flow[UInt], stage: Stage)
|
case class JumpInfo(interface : Flow[UInt], stage: Stage)
|
||||||
val jumpInfos = ArrayBuffer[JumpInfo]()
|
val jumpInfos = ArrayBuffer[JumpInfo]()
|
||||||
|
@ -19,11 +19,56 @@ class PcManagerSimplePlugin(resetVector : BigInt,
|
||||||
var prefetchExceptionPort : Flow[ExceptionCause] = null
|
var prefetchExceptionPort : Flow[ExceptionCause] = null
|
||||||
|
|
||||||
override def setup(pipeline: VexRiscv): Unit = {
|
override def setup(pipeline: VexRiscv): Unit = {
|
||||||
pipeline.unremovableStages += pipeline.prefetch
|
if(!relaxedPcCalculation) pipeline.unremovableStages += pipeline.prefetch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override def build(pipeline: VexRiscv): Unit = {
|
override def build(pipeline: VexRiscv): Unit = {
|
||||||
|
if(relaxedPcCalculation)
|
||||||
|
relaxedImpl(pipeline)
|
||||||
|
else
|
||||||
|
cycleEffectiveImpl(pipeline)
|
||||||
|
}
|
||||||
|
|
||||||
|
//reduce combinatorial path, and expose the PC to the pipeline as a register
|
||||||
|
def relaxedImpl(pipeline: VexRiscv): Unit = {
|
||||||
|
import pipeline.config._
|
||||||
|
import pipeline.prefetch
|
||||||
|
|
||||||
|
prefetch plug new Area {
|
||||||
|
import prefetch._
|
||||||
|
//Stage always valid
|
||||||
|
arbitration.isValid := True
|
||||||
|
|
||||||
|
//PC calculation without Jump
|
||||||
|
val pcReg = Reg(UInt(32 bits)) init(resetVector) addAttribute(Verilator.public)
|
||||||
|
when(arbitration.isFiring){
|
||||||
|
pcReg := pcReg + 4
|
||||||
|
}
|
||||||
|
|
||||||
|
//JumpService hardware implementation
|
||||||
|
val jump = if(jumpInfos.length != 0) new Area {
|
||||||
|
val sortedByStage = jumpInfos.sortWith((a, b) => pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage))
|
||||||
|
val valids = sortedByStage.map(_.interface.valid)
|
||||||
|
val pcs = sortedByStage.map(_.interface.payload)
|
||||||
|
|
||||||
|
val pcLoad = Flow(UInt(32 bits))
|
||||||
|
pcLoad.valid := jumpInfos.map(_.interface.valid).orR
|
||||||
|
pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs)
|
||||||
|
|
||||||
|
//application of the selected jump request
|
||||||
|
when(pcLoad.valid) {
|
||||||
|
pcReg := pcLoad.payload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
insert(PC_CALC_WITHOUT_JUMP) := pcReg
|
||||||
|
insert(PC) := pcReg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Jump take effect instantly (save one cycle), but expose the PC to the pipeline as a 'long' combinatorial path
|
||||||
|
def cycleEffectiveImpl(pipeline: VexRiscv): Unit = {
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
import pipeline.prefetch
|
import pipeline.prefetch
|
||||||
|
|
||||||
|
@ -35,19 +80,12 @@ class PcManagerSimplePlugin(resetVector : BigInt,
|
||||||
//PC calculation without Jump
|
//PC calculation without Jump
|
||||||
val pcReg = Reg(UInt(32 bits)) init(resetVector) addAttribute(Verilator.public)
|
val pcReg = Reg(UInt(32 bits)) init(resetVector) addAttribute(Verilator.public)
|
||||||
val inc = RegInit(False)
|
val inc = RegInit(False)
|
||||||
val pcBeforeJumps = if(fastPcCalculation){
|
val pcBeforeJumps = pcReg + (inc ## B"00").asUInt
|
||||||
val pcPlus4 = pcReg + U(4)
|
|
||||||
pcPlus4.addAttribute("keep")
|
|
||||||
Mux(inc,pcPlus4,pcReg)
|
|
||||||
}else{
|
|
||||||
pcReg + Mux[UInt](inc,4,0)
|
|
||||||
}
|
|
||||||
|
|
||||||
insert(PC_CALC_WITHOUT_JUMP) := pcBeforeJumps
|
insert(PC_CALC_WITHOUT_JUMP) := pcBeforeJumps
|
||||||
val pc = UInt(32 bits)
|
val pc = UInt(32 bits)
|
||||||
pc := input(PC_CALC_WITHOUT_JUMP)
|
pc := input(PC_CALC_WITHOUT_JUMP)
|
||||||
|
|
||||||
val samplePcNext = False //TODO FMAX
|
val samplePcNext = False
|
||||||
|
|
||||||
//JumpService hardware implementation
|
//JumpService hardware implementation
|
||||||
val jump = if(jumpInfos.length != 0) new Area {
|
val jump = if(jumpInfos.length != 0) new Area {
|
||||||
|
|
|
@ -19,8 +19,8 @@ public:
|
||||||
timeProcesses.push_back(jtag);
|
timeProcesses.push_back(jtag);
|
||||||
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
speedFactor = 10e-3;
|
//speedFactor = 10e-3;
|
||||||
cout << "Simulation caped to " << speedFactor << " of real time"<< endl;
|
//cout << "Simulation caped to " << speedFactor << " of real time"<< endl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue