DataCache plugin now support all exceptions
This commit is contained in:
parent
5ba8ab7947
commit
ca1bc9cf69
|
@ -12,13 +12,15 @@ case class DataCacheConfig( cacheSize : Int,
|
||||||
addressWidth : Int,
|
addressWidth : Int,
|
||||||
cpuDataWidth : Int,
|
cpuDataWidth : Int,
|
||||||
memDataWidth : Int,
|
memDataWidth : Int,
|
||||||
catchAccessFault : Boolean,
|
catchAccessError : Boolean,
|
||||||
|
catchIllegal : Boolean,
|
||||||
|
catchUnaligned : Boolean,
|
||||||
catchMemoryTranslationMiss : Boolean,
|
catchMemoryTranslationMiss : Boolean,
|
||||||
|
clearTagsAfterReset : Boolean = true,
|
||||||
tagSizeShift : Int = 0){ //Used to force infering ram
|
tagSizeShift : Int = 0){ //Used to force infering ram
|
||||||
def burstSize = bytePerLine*8/memDataWidth
|
def burstSize = bytePerLine*8/memDataWidth
|
||||||
val burstLength = bytePerLine/(memDataWidth/8)
|
val burstLength = bytePerLine/(memDataWidth/8)
|
||||||
assert(catchAccessFault == false)
|
def catchSomething = catchUnaligned || catchMemoryTranslationMiss || catchIllegal || catchAccessError
|
||||||
def catchSomething = catchAccessFault || catchMemoryTranslationMiss
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +45,7 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
|
||||||
SRC_USE_SUB_LESS -> False,
|
SRC_USE_SUB_LESS -> False,
|
||||||
MEMORY_ENABLE -> True,
|
MEMORY_ENABLE -> True,
|
||||||
REG1_USE -> True
|
REG1_USE -> True
|
||||||
) ++ (if (catchAccessFault) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage
|
) ++ (if (catchUnaligned) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage
|
||||||
|
|
||||||
val loadActions = stdActions ++ List(
|
val loadActions = stdActions ++ List(
|
||||||
SRC2_CTRL -> Src2CtrlEnum.IMI,
|
SRC2_CTRL -> Src2CtrlEnum.IMI,
|
||||||
|
@ -99,7 +101,7 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
|
||||||
U(1) -> B"0011",
|
U(1) -> B"0011",
|
||||||
default -> B"1111"
|
default -> B"1111"
|
||||||
) << cache.io.cpu.execute.args.address(1 downto 0)).resized
|
) << cache.io.cpu.execute.args.address(1 downto 0)).resized
|
||||||
cache.io.cpu.execute.args.bypass := cache.io.cpu.execute.args.address(31 downto 28) === 0xF
|
cache.io.cpu.execute.args.forceUncachedAccess := False // cache.io.cpu.execute.args.address(31 downto 28) === 0xF
|
||||||
cache.io.cpu.execute.args.kind := DataCacheCpuCmdKind.MEMORY
|
cache.io.cpu.execute.args.kind := DataCacheCpuCmdKind.MEMORY
|
||||||
cache.io.cpu.execute.args.clean := False
|
cache.io.cpu.execute.args.clean := False
|
||||||
cache.io.cpu.execute.args.invalidate := False
|
cache.io.cpu.execute.args.invalidate := False
|
||||||
|
@ -128,9 +130,12 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
|
||||||
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||||
cache.io.cpu.writeBack.isStuck := arbitration.isStuck
|
cache.io.cpu.writeBack.isStuck := arbitration.isStuck
|
||||||
if(catchSomething) {
|
if(catchSomething) {
|
||||||
exceptionBus.valid := cache.io.cpu.writeBack.mmuMiss
|
exceptionBus.valid := cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.accessError
|
||||||
exceptionBus.badAddr := cache.io.cpu.writeBack.badAddr
|
exceptionBus.badAddr := cache.io.cpu.writeBack.badAddr
|
||||||
exceptionBus.code := 13
|
exceptionBus.code := 13
|
||||||
|
when(cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.accessError){
|
||||||
|
exceptionBus.code := (input(INSTRUCTION)(5) ? U(7) | U(5)).resized
|
||||||
|
}
|
||||||
}
|
}
|
||||||
arbitration.haltIt.setWhen(cache.io.cpu.writeBack.haltIt)
|
arbitration.haltIt.setWhen(cache.io.cpu.writeBack.haltIt)
|
||||||
|
|
||||||
|
@ -255,7 +260,7 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
|
||||||
val address = UInt(p.addressWidth bit)
|
val address = UInt(p.addressWidth bit)
|
||||||
val data = Bits(p.cpuDataWidth bit)
|
val data = Bits(p.cpuDataWidth bit)
|
||||||
val mask = Bits(p.cpuDataWidth/8 bit)
|
val mask = Bits(p.cpuDataWidth/8 bit)
|
||||||
val bypass = Bool
|
val forceUncachedAccess = Bool
|
||||||
val clean, invalidate, way = Bool
|
val clean, invalidate, way = Bool
|
||||||
// val all = Bool //Address should be zero when "all" is used
|
// val all = Bool //Address should be zero when "all" is used
|
||||||
}
|
}
|
||||||
|
@ -278,14 +283,13 @@ case class DataCacheCpuWriteBack(p : DataCacheConfig) extends Bundle with IMaste
|
||||||
val isStuck = Bool
|
val isStuck = Bool
|
||||||
val haltIt = Bool
|
val haltIt = Bool
|
||||||
val data = Bits(p.cpuDataWidth bit)
|
val data = Bits(p.cpuDataWidth bit)
|
||||||
val mmuMiss = Bool
|
val mmuMiss, illegalAccess, unalignedAccess , accessError = Bool
|
||||||
val badAddr = UInt(32 bits)
|
val badAddr = UInt(32 bits)
|
||||||
// val exceptionBus = if(p.catchSomething) Flow(ExceptionCause()) else null
|
// val exceptionBus = if(p.catchSomething) Flow(ExceptionCause()) else null
|
||||||
|
|
||||||
override def asMaster(): Unit = {
|
override def asMaster(): Unit = {
|
||||||
out(isValid,isStuck)
|
out(isValid,isStuck)
|
||||||
in(haltIt, data, mmuMiss, badAddr)
|
in(haltIt, data, mmuMiss,illegalAccess , unalignedAccess, accessError, badAddr)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,6 +315,7 @@ case class DataCacheMemCmd(p : DataCacheConfig) extends Bundle{
|
||||||
}
|
}
|
||||||
case class DataCacheMemRsp(p : DataCacheConfig) extends Bundle{
|
case class DataCacheMemRsp(p : DataCacheConfig) extends Bundle{
|
||||||
val data = Bits(p.memDataWidth bit)
|
val data = Bits(p.memDataWidth bit)
|
||||||
|
val error = Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave{
|
case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave{
|
||||||
|
@ -449,7 +454,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
||||||
tagsReadCmd.payload := io.cpu.execute.address(lineRange)
|
tagsReadCmd.payload := io.cpu.execute.address(lineRange)
|
||||||
|
|
||||||
dataReadCmd.valid := True
|
dataReadCmd.valid := True
|
||||||
dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low) //TODO FMAX mayybe critical path could be default
|
dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low) //TODO FMAX maybe critical path could be default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -544,7 +549,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
||||||
val request = RegNextWhen(io.cpu.execute.args, !io.cpu.memory.isStuck)
|
val request = RegNextWhen(io.cpu.execute.args, !io.cpu.memory.isStuck)
|
||||||
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid && request.kind === MEMORY //TODO filter request kind
|
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid && request.kind === MEMORY //TODO filter request kind
|
||||||
io.cpu.memory.mmuBus.cmd.virtualAddress := request.address
|
io.cpu.memory.mmuBus.cmd.virtualAddress := request.address
|
||||||
io.cpu.memory.mmuBus.cmd.bypass := request.way
|
io.cpu.memory.mmuBus.cmd.bypassTranslation := request.way
|
||||||
}
|
}
|
||||||
|
|
||||||
val stageB = new Area {
|
val stageB = new Area {
|
||||||
|
@ -568,10 +573,13 @@ class DataCache(p : DataCacheConfig) extends Component{
|
||||||
|
|
||||||
io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid
|
io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid
|
||||||
io.cpu.writeBack.mmuMiss := False
|
io.cpu.writeBack.mmuMiss := False
|
||||||
|
io.cpu.writeBack.illegalAccess := False
|
||||||
|
io.cpu.writeBack.unalignedAccess := False
|
||||||
|
io.cpu.writeBack.accessError := (if(catchAccessError) io.mem.rsp.valid && io.mem.rsp.error else False)
|
||||||
io.cpu.writeBack.badAddr := request.address
|
io.cpu.writeBack.badAddr := request.address
|
||||||
|
|
||||||
//Evict the cache after reset logics
|
//Evict the cache after reset logics
|
||||||
val bootEvicts = new Area {
|
val bootEvicts = if(clearTagsAfterReset) new Area {
|
||||||
val valid = RegInit(True)
|
val valid = RegInit(True)
|
||||||
mmuRsp.physicalAddress init (0)
|
mmuRsp.physicalAddress init (0)
|
||||||
when(valid) {
|
when(valid) {
|
||||||
|
@ -588,11 +596,11 @@ class DataCache(p : DataCacheConfig) extends Component{
|
||||||
}
|
}
|
||||||
|
|
||||||
when(io.cpu.writeBack.isValid) {
|
when(io.cpu.writeBack.isValid) {
|
||||||
switch(request.kind) {
|
|
||||||
is(LINE) {
|
|
||||||
if (catchMemoryTranslationMiss) {
|
if (catchMemoryTranslationMiss) {
|
||||||
io.cpu.writeBack.mmuMiss := mmuRsp.miss
|
io.cpu.writeBack.mmuMiss := mmuRsp.miss
|
||||||
}
|
}
|
||||||
|
switch(request.kind) {
|
||||||
|
is(LINE) {
|
||||||
when(delayedIsStuck && !mmuRsp.miss) {
|
when(delayedIsStuck && !mmuRsp.miss) {
|
||||||
when(delayedWaysHitValid || (request.way && way.tagReadRspTwo.used)) {
|
when(delayedWaysHitValid || (request.way && way.tagReadRspTwo.used)) {
|
||||||
io.cpu.writeBack.haltIt.clearWhen(!(victim.requestIn.valid && !victim.requestIn.ready))
|
io.cpu.writeBack.haltIt.clearWhen(!(victim.requestIn.valid && !victim.requestIn.ready))
|
||||||
|
@ -609,11 +617,12 @@ class DataCache(p : DataCacheConfig) extends Component{
|
||||||
tagsWriteCmd.data.dirty := !request.clean
|
tagsWriteCmd.data.dirty := !request.clean
|
||||||
}
|
}
|
||||||
is(MEMORY) {
|
is(MEMORY) {
|
||||||
if (catchMemoryTranslationMiss) {
|
val illegal = if(catchIllegal) (request.wr && !mmuRsp.allowWrite) || (!request.wr && !mmuRsp.allowRead) else False
|
||||||
io.cpu.writeBack.mmuMiss := mmuRsp.miss
|
val unaligned = if(catchUnaligned) ((request.mask === 0xF && mmuRsp.physicalAddress(1 downto 0) =/= 0) || ((request.mask === 0x3 || request.mask === 0xC) && mmuRsp.physicalAddress(0) =/= False)) else False
|
||||||
}
|
io.cpu.writeBack.illegalAccess := illegal
|
||||||
when(Bool(!catchMemoryTranslationMiss) || !mmuRsp.miss) {
|
io.cpu.writeBack.unalignedAccess := unaligned
|
||||||
when(request.bypass) {
|
when((Bool(!catchMemoryTranslationMiss) || !mmuRsp.miss) && !illegal && !unaligned) {
|
||||||
|
when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
|
||||||
val memCmdSent = RegInit(False)
|
val memCmdSent = RegInit(False)
|
||||||
when(!victim.request.valid) {
|
when(!victim.request.valid) {
|
||||||
//Avoid mixing memory request while victim is pending
|
//Avoid mixing memory request while victim is pending
|
||||||
|
@ -639,7 +648,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
||||||
dataWriteCmd.data := request.data
|
dataWriteCmd.data := request.data
|
||||||
dataWriteCmd.mask := request.mask
|
dataWriteCmd.mask := request.mask
|
||||||
|
|
||||||
tagsWriteCmd.valid := !loadingNotDone || request.wr
|
tagsWriteCmd.valid := (!loadingNotDone) || request.wr
|
||||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||||
tagsWriteCmd.data.used := True
|
tagsWriteCmd.data.used := True
|
||||||
tagsWriteCmd.data.dirty := request.wr
|
tagsWriteCmd.data.dirty := request.wr
|
||||||
|
@ -658,7 +667,7 @@ 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")
|
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.bypass ? io.mem.rsp.data | way.dataReadRspTwo //not multi ways
|
io.cpu.writeBack.data := request.forceUncachedAccess ? io.mem.rsp.data | way.dataReadRspTwo //not multi ways
|
||||||
}
|
}
|
||||||
|
|
||||||
//The whole life of a loading task, the corresponding manager request is present
|
//The whole life of a loading task, the corresponding manager request is present
|
||||||
|
|
|
@ -458,7 +458,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
||||||
|
|
||||||
io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid
|
io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid
|
||||||
io.cpu.fetch.mmuBus.cmd.virtualAddress := io.cpu.fetch.address
|
io.cpu.fetch.mmuBus.cmd.virtualAddress := io.cpu.fetch.address
|
||||||
io.cpu.fetch.mmuBus.cmd.bypass := False
|
io.cpu.fetch.mmuBus.cmd.bypassTranslation := False
|
||||||
val mmuRsp = RegNextWhen(io.cpu.fetch.mmuBus.rsp,!io.cpu.decode.isStuck)
|
val mmuRsp = RegNextWhen(io.cpu.fetch.mmuBus.rsp,!io.cpu.decode.isStuck)
|
||||||
|
|
||||||
val hit = tag.valid && tag.address === mmuRsp.physicalAddress(tagRange) && !(tag.loading && !lineLoader.loadedWords(mmuRsp.physicalAddress(wordRange)))
|
val hit = tag.valid && tag.address === mmuRsp.physicalAddress(tagRange) && !(tag.loading && !lineLoader.loadedWords(mmuRsp.physicalAddress(wordRange)))
|
||||||
|
|
|
@ -9,7 +9,9 @@ case class MemoryTranslatorPort(bus : MemoryTranslatorBus, stage : Stage, args :
|
||||||
|
|
||||||
case class MemoryTranslatorPortConfig(portTlbSize : Int)
|
case class MemoryTranslatorPortConfig(portTlbSize : Int)
|
||||||
|
|
||||||
class MemoryTranslatorPlugin(tlbSize : Int, mmuRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator {
|
class MemoryTranslatorPlugin(tlbSize : Int,
|
||||||
|
virtualRange : UInt => Bool,
|
||||||
|
ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator {
|
||||||
assert(isPow2(tlbSize))
|
assert(isPow2(tlbSize))
|
||||||
|
|
||||||
val portsInfo = ArrayBuffer[MemoryTranslatorPort]()
|
val portsInfo = ArrayBuffer[MemoryTranslatorPort]()
|
||||||
|
@ -66,7 +68,7 @@ class MemoryTranslatorPlugin(tlbSize : Int, mmuRange : UInt => Bool) extends Plu
|
||||||
val cacheHits = cache.map(line => line.valid && line.virtualAddress === port.bus.cmd.virtualAddress(31 downto 12))
|
val cacheHits = cache.map(line => line.valid && line.virtualAddress === port.bus.cmd.virtualAddress(31 downto 12))
|
||||||
val cacheHit = cacheHits.asBits.orR
|
val cacheHit = cacheHits.asBits.orR
|
||||||
val cacheLine = MuxOH(cacheHits, cache)
|
val cacheLine = MuxOH(cacheHits, cache)
|
||||||
val isInMmuRange = mmuRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypass
|
val isInMmuRange = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation
|
||||||
|
|
||||||
val sharedMiss = RegInit(False)
|
val sharedMiss = RegInit(False)
|
||||||
val sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits))
|
val sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits))
|
||||||
|
@ -112,6 +114,7 @@ class MemoryTranslatorPlugin(tlbSize : Int, mmuRange : UInt => Bool) extends Plu
|
||||||
port.bus.rsp.allowWrite := True
|
port.bus.rsp.allowWrite := True
|
||||||
port.bus.rsp.allowExecute := True
|
port.bus.rsp.allowExecute := True
|
||||||
}
|
}
|
||||||
|
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
|
||||||
port.bus.rsp.miss := sharedMiss
|
port.bus.rsp.miss := sharedMiss
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,11 @@ trait ExceptionService{
|
||||||
case class MemoryTranslatorCmd() extends Bundle{
|
case class MemoryTranslatorCmd() extends Bundle{
|
||||||
val isValid = Bool
|
val isValid = Bool
|
||||||
val virtualAddress = UInt(32 bits)
|
val virtualAddress = UInt(32 bits)
|
||||||
val bypass = Bool
|
val bypassTranslation = Bool
|
||||||
}
|
}
|
||||||
case class MemoryTranslatorRsp() extends Bundle{
|
case class MemoryTranslatorRsp() extends Bundle{
|
||||||
val physicalAddress = UInt(32 bits)
|
val physicalAddress = UInt(32 bits)
|
||||||
|
val isIoAccess = Bool
|
||||||
val allowRead, allowWrite, allowExecute = Bool
|
val allowRead, allowWrite, allowExecute = Bool
|
||||||
val miss = Bool
|
val miss = Bool
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,9 @@ object TopLevel {
|
||||||
addressWidth = 32,
|
addressWidth = 32,
|
||||||
cpuDataWidth = 32,
|
cpuDataWidth = 32,
|
||||||
memDataWidth = 32,
|
memDataWidth = 32,
|
||||||
catchAccessFault = false,
|
catchAccessError = true,
|
||||||
|
catchIllegal = true,
|
||||||
|
catchUnaligned = true,
|
||||||
catchMemoryTranslationMiss = false
|
catchMemoryTranslationMiss = false
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -269,7 +271,9 @@ object TopLevel {
|
||||||
addressWidth = 32,
|
addressWidth = 32,
|
||||||
cpuDataWidth = 32,
|
cpuDataWidth = 32,
|
||||||
memDataWidth = 32,
|
memDataWidth = 32,
|
||||||
catchAccessFault = false,
|
catchAccessError = true,
|
||||||
|
catchIllegal = true,
|
||||||
|
catchUnaligned = true,
|
||||||
catchMemoryTranslationMiss = true,
|
catchMemoryTranslationMiss = true,
|
||||||
tagSizeShift = 2
|
tagSizeShift = 2
|
||||||
),
|
),
|
||||||
|
@ -281,7 +285,8 @@ object TopLevel {
|
||||||
|
|
||||||
new MemoryTranslatorPlugin(
|
new MemoryTranslatorPlugin(
|
||||||
tlbSize = 32,
|
tlbSize = 32,
|
||||||
mmuRange = _(31 downto 28) === 0xC
|
virtualRange = _(31 downto 28) === 0xC,
|
||||||
|
ioRange = _(31 downto 28) === 0xF
|
||||||
),
|
),
|
||||||
new MachineCsr(csrConfigSmall),
|
new MachineCsr(csrConfigSmall),
|
||||||
new DecoderSimplePlugin(
|
new DecoderSimplePlugin(
|
||||||
|
|
|
@ -562,12 +562,14 @@ public:
|
||||||
virtual void postCycle(){
|
virtual void postCycle(){
|
||||||
if(pendingCount != 0 && !wr && (!ws->dStall || VL_RANDOM_I(7) < 100)){
|
if(pendingCount != 0 && !wr && (!ws->dStall || VL_RANDOM_I(7) < 100)){
|
||||||
ws->dBusAccess(address,0,2,0,&top->dBus_rsp_payload_data,&error_next);
|
ws->dBusAccess(address,0,2,0,&top->dBus_rsp_payload_data,&error_next);
|
||||||
|
top->dBus_rsp_payload_error = error_next;
|
||||||
top->dBus_rsp_valid = 1;
|
top->dBus_rsp_valid = 1;
|
||||||
address += 4;
|
address += 4;
|
||||||
pendingCount--;
|
pendingCount--;
|
||||||
} else{
|
} else{
|
||||||
top->dBus_rsp_valid = 0;
|
top->dBus_rsp_valid = 0;
|
||||||
top->dBus_rsp_payload_data = VL_RANDOM_I(32);
|
top->dBus_rsp_payload_data = VL_RANDOM_I(32);
|
||||||
|
top->dBus_rsp_payload_error = VL_RANDOM_I(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
top->dBus_cmd_ready = (ws->dStall ? VL_RANDOM_I(7) < 100 : 1) && (pendingCount == 0 || wr);
|
top->dBus_cmd_ready = (ws->dStall ? VL_RANDOM_I(7) < 100 : 1) && (pendingCount == 0 || wr);
|
||||||
|
|
Loading…
Reference in New Issue