mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-01-03 03:43:39 -05:00
Add Atomic LR SC support to the DBusCachedPlugin via reservation entries buffer
This commit is contained in:
parent
4ed19f2cc5
commit
468dd3841e
6 changed files with 86 additions and 4 deletions
|
@ -59,6 +59,9 @@ object Riscv{
|
|||
def SH = M"-----------------001-----0100011"
|
||||
def SW = M"-----------------010-----0100011"
|
||||
|
||||
def LR = M"00010--00000-----010-----0101111"
|
||||
def SC = M"00011------------010-----0101111"
|
||||
|
||||
def BEQ = M"-----------------000-----1100011"
|
||||
def BNE = M"-----------------001-----1100011"
|
||||
def BLT = M"-----------------100-----1100011"
|
||||
|
|
|
@ -75,7 +75,8 @@ object TestsWorkspace {
|
|||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchMemoryTranslationMiss = true,
|
||||
atomicEntriesCount = 2
|
||||
),
|
||||
// memoryTranslatorPortConfig = null
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -19,10 +19,12 @@ case class DataCacheConfig( cacheSize : Int,
|
|||
catchMemoryTranslationMiss : Boolean,
|
||||
clearTagsAfterReset : Boolean = true,
|
||||
waysHitRetime : Boolean = true,
|
||||
tagSizeShift : Int = 0){ //Used to force infering ram
|
||||
tagSizeShift : Int = 0, //Used to force infering ram
|
||||
atomicEntriesCount : Int = 0){
|
||||
def burstSize = bytePerLine*8/memDataWidth
|
||||
val burstLength = bytePerLine/(memDataWidth/8)
|
||||
def catchSomething = catchUnaligned || catchMemoryTranslationMiss || catchIllegal || catchAccessError
|
||||
def genAtomic = atomicEntriesCount != 0
|
||||
|
||||
def getAxi4SharedConfig() = Axi4Config(
|
||||
addressWidth = addressWidth,
|
||||
|
@ -147,6 +149,7 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
|
|||
val size = UInt(2 bits)
|
||||
val forceUncachedAccess = Bool
|
||||
val clean, invalidate, way = Bool
|
||||
val isAtomic = ifGen(p.genAtomic){Bool}
|
||||
// val all = Bool //Address should be zero when "all" is used
|
||||
}
|
||||
|
||||
|
@ -173,11 +176,13 @@ case class DataCacheCpuWriteBack(p : DataCacheConfig) extends Bundle with IMaste
|
|||
val data = Bits(p.cpuDataWidth bit)
|
||||
val mmuMiss, illegalAccess, unalignedAccess , accessError = Bool
|
||||
val badAddr = UInt(32 bits)
|
||||
val clearAtomicEntries = ifGen(p.genAtomic) {Bool}
|
||||
// val exceptionBus = if(p.catchSomething) Flow(ExceptionCause()) else null
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid,isStuck,isUser)
|
||||
in(haltIt, data, mmuMiss,illegalAccess , unalignedAccess, accessError, badAddr)
|
||||
outWithNull(clearAtomicEntries)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -564,6 +569,38 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
val atomic = if(genAtomic) new Area{
|
||||
case class AtomicEntry() extends Bundle{
|
||||
val valid = Bool()
|
||||
val size = UInt(2 bits)
|
||||
val address = UInt(addressWidth bits)
|
||||
|
||||
def init: this.type ={
|
||||
valid init(False)
|
||||
this
|
||||
}
|
||||
}
|
||||
val entries = Vec(Reg(AtomicEntry()).init, atomicEntriesCount)
|
||||
val entriesAllocCounter = Counter(atomicEntriesCount)
|
||||
val entriesHit = entries.map(e => e.valid && e.size === request.size && e.address === request.address).orR
|
||||
when(io.cpu.writeBack.isValid && request.isAtomic && !request.wr){
|
||||
entries(entriesAllocCounter).valid := True
|
||||
entries(entriesAllocCounter).size := request.size
|
||||
entries(entriesAllocCounter).address := request.address
|
||||
when(!io.cpu.writeBack.isStuck){
|
||||
entriesAllocCounter.increment()
|
||||
}
|
||||
}
|
||||
when(io.cpu.writeBack.clearAtomicEntries){
|
||||
entries.foreach(_.valid := False)
|
||||
}
|
||||
|
||||
when(request.isAtomic && ! entriesHit){
|
||||
writeMask := 0
|
||||
}
|
||||
} else null
|
||||
|
||||
when(io.cpu.writeBack.isValid) {
|
||||
if (catchMemoryTranslationMiss) {
|
||||
io.cpu.writeBack.mmuMiss := mmuRsp.miss
|
||||
|
@ -638,6 +675,11 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
|
||||
assert(!(io.cpu.writeBack.isValid && !io.cpu.writeBack.haltIt && io.cpu.writeBack.isStuck), "writeBack stuck by another plugin is not allowed")
|
||||
io.cpu.writeBack.data := (request.forceUncachedAccess || mmuRsp.isIoAccess) ? io.mem.rsp.data | way.dataReadRspTwo //not multi ways
|
||||
if(genAtomic){
|
||||
when(request.isAtomic && request.wr){
|
||||
io.cpu.writeBack.data := (!atomic.entriesHit).asBits.resized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//The whole life of a loading task, the corresponding manager request is present
|
||||
|
|
|
@ -138,9 +138,13 @@ case class CsrMapping(){
|
|||
}
|
||||
|
||||
|
||||
trait IContextSwitching{
|
||||
def isContextSwitching : Bool
|
||||
}
|
||||
|
||||
|
||||
class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor{
|
||||
|
||||
class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching{
|
||||
import config._
|
||||
import CsrAccess._
|
||||
|
||||
|
@ -161,6 +165,8 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|
|||
var externalInterrupt : Bool = null
|
||||
var privilege : Bits = null
|
||||
var selfException : Flow[ExceptionCause] = null
|
||||
var contextSwitching : Bool = null
|
||||
override def isContextSwitching = contextSwitching
|
||||
|
||||
object EnvCtrlEnum extends SpinalEnum(binarySequential){
|
||||
val NONE, EBREAK, MRET= newElement()
|
||||
|
@ -223,6 +229,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|
|||
|
||||
timerInterrupt = in Bool() setName("timerInterrupt")
|
||||
externalInterrupt = in Bool() setName("externalInterrupt")
|
||||
contextSwitching = Bool().setName("contextSwitching")
|
||||
|
||||
privilege = RegInit(B"11")
|
||||
|
||||
|
@ -439,6 +446,8 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|
|||
}
|
||||
}
|
||||
|
||||
contextSwitching := jumpInterface.valid
|
||||
|
||||
//CSR read/write instructions management
|
||||
execute plug new Area {
|
||||
import execute._
|
||||
|
|
|
@ -7,7 +7,6 @@ import spinal.lib._
|
|||
|
||||
|
||||
|
||||
|
||||
class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv]{
|
||||
import config._
|
||||
var dBus : DataCacheMemBus = null
|
||||
|
@ -17,6 +16,7 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
|
|||
|
||||
object MEMORY_ENABLE extends Stageable(Bool)
|
||||
object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
|
||||
object MEMORY_ATOMIC extends Stageable(Bool)
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import Riscv._
|
||||
|
@ -49,6 +49,30 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
|
|||
List(SB, SH, SW).map(_ -> storeActions)
|
||||
)
|
||||
|
||||
if(genAtomic){
|
||||
List(LB, LH, LW, LBU, LHU, LWU, SB, SH, SW).foreach(e =>
|
||||
decoderService.add(e, Seq(MEMORY_ATOMIC -> False))
|
||||
)
|
||||
decoderService.add(
|
||||
key = LR,
|
||||
values = loadActions.filter(_._1 != SRC2_CTRL) ++ Seq(
|
||||
RS2_USE -> True,
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
MEMORY_ATOMIC -> True
|
||||
)
|
||||
)
|
||||
decoderService.add(
|
||||
key = SC,
|
||||
values = storeActions.filter(_._1 != SRC2_CTRL) ++ Seq(
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> False,
|
||||
MEMORY_ATOMIC -> True
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
def MANAGEMENT = M"-------00000-----101-----0001111"
|
||||
decoderService.add(MANAGEMENT, stdActions ++ List(
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
|
@ -114,6 +138,7 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
|
|||
cache.io.cpu.execute.args.clean := input(INSTRUCTION)(28)
|
||||
cache.io.cpu.execute.args.invalidate := input(INSTRUCTION)(29)
|
||||
cache.io.cpu.execute.args.way := input(INSTRUCTION)(30)
|
||||
if(genAtomic) cache.io.cpu.execute.args.isAtomic := input(MEMORY_ATOMIC)
|
||||
|
||||
insert(MEMORY_ADDRESS_LOW) := cache.io.cpu.execute.args.address(1 downto 0)
|
||||
}
|
||||
|
@ -133,6 +158,7 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
|
|||
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||
cache.io.cpu.writeBack.isStuck := arbitration.isStuck
|
||||
cache.io.cpu.writeBack.isUser := (if(privilegeService != null) privilegeService.isUser(writeBack) else False)
|
||||
if(genAtomic) cache.io.cpu.writeBack.clearAtomicEntries := service(classOf[IContextSwitching]).isContextSwitching
|
||||
|
||||
if(catchSomething) {
|
||||
exceptionBus.valid := cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess
|
||||
|
|
|
@ -25,6 +25,7 @@ object MuraxSim {
|
|||
|
||||
val clockDomain = ClockDomain(dut.io.mainClk, dut.io.asyncReset)
|
||||
clockDomain.forkStimulus(mainClkPeriod)
|
||||
// clockDomain.forkSimSpeedPrinter()
|
||||
|
||||
val tcpJtag = JtagTcp(
|
||||
jtag = dut.io.jtag,
|
||||
|
|
Loading…
Reference in a new issue