Add Atomic LR SC support to the DBusCachedPlugin via reservation entries buffer

This commit is contained in:
Dolu1990 2018-01-04 13:16:40 +01:00
parent 4ed19f2cc5
commit 468dd3841e
6 changed files with 86 additions and 4 deletions

View file

@ -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"

View file

@ -75,7 +75,8 @@ object TestsWorkspace {
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true
catchMemoryTranslationMiss = true,
atomicEntriesCount = 2
),
// memoryTranslatorPortConfig = null
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(

View file

@ -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

View file

@ -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._

View file

@ -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

View file

@ -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,