/*
+ * Copyright (c) 2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2013 Mark D. Hill and David A. Wood
* All rights reserved.
*
// Base states
// The cache entry has not been allocated.
- I, AccessPermission:Invalid;
+ I, AccessPermission:Invalid, desc="Invalid";
// The cache entry is in shared mode. The processor can read this entry
// but it cannot write to it.
- S, AccessPermission:Read_Only;
+ S, AccessPermission:Read_Only, desc="Shared";
// The cache entry is in exclusive mode. The processor can read this
// entry. It can write to this entry without informing the directory.
// On writing, the entry moves to M state.
- E, AccessPermission:Read_Only;
+ E, AccessPermission:Read_Only, desc="Exclusive";
// The processor has read and write permissions on this entry.
- M, AccessPermission:Read_Write;
+ M, AccessPermission:Read_Write, desc="Modified";
// Transient States
// The cache controller has requested an instruction. It will be stored
// in the shared state so that the processor can read it.
- Inst_IS, AccessPermission:Busy;
+ Inst_IS, AccessPermission:Busy, desc="Issued GETS, have not seen response yet";
// The cache controller has requested that this entry be fetched in
// shared state so that the processor can read it.
- IS, AccessPermission:Busy;
+ IS, AccessPermission:Busy, desc="Issued GETS, have not seen response yet";
// The cache controller has requested that this entry be fetched in
// modify state so that the processor can read/write it.
- IM, AccessPermission:Busy;
+ IM, AccessPermission:Busy, desc="Issued GETX, have not seen response yet";
// The cache controller had read permission over the entry. But now the
// processor needs to write to it. So, the controller has requested for
// write permission.
- SM, AccessPermission:Read_Only;
+ SM, AccessPermission:Read_Only, desc="Issued GETX, have not seen response yet";
}
// EVENTS
enumeration(Event, desc="Cache events") {
- // L0 events
+ // Events from core
Load, desc="Load request from the home processor";
Ifetch, desc="I-fetch request from the home processor";
Store, desc="Store request from the home processor";
// internal generated request
L0_Replacement, desc="L0 Replacement", format="!r";
- // other requests
+ // requests forwarded from other processors
Fwd_GETX, desc="GETX from other processor";
Fwd_GETS, desc="GETS from other processor";
Fwd_GET_INSTR, desc="GET_INSTR from other processor";
+ // data arrives from L1 cache
Data, desc="Data for processor";
Data_Exclusive, desc="Data for processor";
Data_Stale, desc="Data for processor, but not for storage";
Ack, desc="Ack for processor";
- Ack_all, desc="Last ack for processor";
WB_Ack, desc="Ack for replacement";
}
}
}
- action(f_sendDataToL1, "f", desc="send data to the L2 cache") {
+ action(f_sendDataToL1, "f", desc="Send data to the L1 cache") {
enqueue(requestNetwork_out, CoherenceMsg, response_latency) {
assert(is_valid(cache_entry));
out_msg.addr := address;
cache_entry.Dirty := false;
}
- action(fi_sendInvAck, "fi", desc="send data to the L2 cache") {
+ action(fi_sendInvAck, "fi", desc="Send data to the L1 cache") {
peek(messgeBuffer_in, CoherenceMsg) {
enqueue(requestNetwork_out, CoherenceMsg, response_latency) {
out_msg.addr := address;
}
}
- action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") {
+ action(forward_eviction_to_cpu, "\cc", desc="Send eviction information to the processor") {
if (send_evictions) {
DPRINTF(RubySlicc, "Sending invalidation for %#x to the CPU\n", address);
sequencer.evictionCallback(address);
}
}
- action(g_issuePUTX, "g", desc="send data to the L2 cache") {
+ action(g_issuePUTX, "g", desc="Relinquish line to the L1 cache") {
enqueue(requestNetwork_out, CoherenceMsg, response_latency) {
assert(is_valid(cache_entry));
out_msg.addr := address;
}
}
- action(h_load_hit, "hd", desc="If not prefetch, notify sequencer the load completed.") {
+ action(h_load_hit, "hd", desc="Notify sequencer the load completed (cache hit)") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
Dcache.setMRU(cache_entry);
sequencer.readCallback(address, cache_entry.DataBlk);
}
- action(h_ifetch_hit, "hi", desc="If not prefetch, notify sequencer the ifetch completed.") {
+ action(h_ifetch_hit, "hi", desc="Notify sequencer the ifetch completed (cache hit)") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
Icache.setMRU(cache_entry);
sequencer.readCallback(address, cache_entry.DataBlk);
}
- action(hx_load_hit, "hxd", desc="notify sequencer the load completed.") {
+ // The action name uses a counterintuitive _hit prefix when it is only
+ // called due to a cache miss. It is technically now a hit after having
+ // serviced the miss.
+ action(hx_load_hit, "hxd", desc="Notify sequencer the load completed (cache miss)") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
Dcache.setMRU(cache_entry);
sequencer.readCallback(address, cache_entry.DataBlk, true);
}
- action(hx_ifetch_hit, "hxi", desc="notify sequencer the ifetch completed.") {
+ // The action name uses a counterintuitive _hit prefix when it is only
+ // called due to a cache miss. It is technically now a hit after having
+ // serviced the miss.
+ action(hx_ifetch_hit, "hxi", desc="Notify sequencer the ifetch completed (cache miss)") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
Icache.setMRU(cache_entry);
sequencer.readCallback(address, cache_entry.DataBlk, true);
}
- action(hh_store_hit, "\h", desc="If not prefetch, notify sequencer that store completed.") {
+ action(hh_store_hit, "\h", desc="Notify sequencer that store completed (cache hit)") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
Dcache.setMRU(cache_entry);
cache_entry.Dirty := true;
}
- action(hhx_store_hit, "\hx", desc="If not prefetch, notify sequencer that store completed.") {
+ // The action name uses a counterintuitive _hit prefix when it is only
+ // called due to a cache miss. It is technically now a hit after having
+ // serviced the miss.
+ action(hhx_store_hit, "\hx", desc="Notify sequencer that store completed (cache miss)") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
Dcache.setMRU(cache_entry);
tbe.DataBlk := cache_entry.DataBlk;
}
- action(k_popMandatoryQueue, "k", desc="Pop mandatory queue.") {
+ action(k_popMandatoryQueue, "k", desc="Pop mandatory queue") {
mandatoryQueue_in.dequeue(clockEdge());
}
unset_cache_entry();
}
- action(oo_allocateDCacheBlock, "\o", desc="Set L1 D-cache tag equal to tag of block B.") {
+ action(oo_allocateDCacheBlock, "\o", desc="Set L1 D-cache tag equal to tag of block B") {
if (is_invalid(cache_entry)) {
set_cache_entry(Dcache.allocate(address, new Entry));
}
}
- action(pp_allocateICacheBlock, "\p", desc="Set L1 I-cache tag equal to tag of block B.") {
+ action(pp_allocateICacheBlock, "\p", desc="Set L1 I-cache tag equal to tag of block B") {
if (is_invalid(cache_entry)) {
set_cache_entry(Icache.allocate(address, new Entry));
}
}
- action(z_stallAndWaitMandatoryQueue, "\z", desc="recycle cpu request queue") {
+ action(z_stallAndWaitMandatoryQueue, "\z", desc="Stall cpu request queue") {
stall_and_wait(mandatoryQueue_in, address);
}
- action(kd_wakeUpDependents, "kd", desc="wake-up dependents") {
+ action(kd_wakeUpDependents, "kd", desc="Wake-up dependents") {
wakeUpAllBuffers(address);
}
++Icache.demand_misses;
}
- action(uu_profileInstHit, "\uih", desc="Profile the demand miss") {
+ action(uu_profileInstHit, "\uih", desc="Profile the demand hit") {
++Icache.demand_hits;
}
++Dcache.demand_misses;
}
- action(uu_profileDataHit, "\udh", desc="Profile the demand miss") {
+ action(uu_profileDataHit, "\udh", desc="Profile the demand hit") {
++Dcache.demand_hits;
}
/*
+ * Copyright (c) 2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 1999-2013 Mark D. Hill and David A. Wood
* All rights reserved.
*
// STATES
state_declaration(State, desc="Cache states", default="L1Cache_State_I") {
// Base states
- I, AccessPermission:Invalid, desc="a L1 cache entry Idle";
- S, AccessPermission:Read_Only, desc="a L1 cache entry Shared";
- SS, AccessPermission:Read_Only, desc="a L1 cache entry Shared";
- E, AccessPermission:Read_Only, desc="a L1 cache entry Exclusive";
- EE, AccessPermission:Read_Write, desc="a L1 cache entry Exclusive";
- M, AccessPermission:Maybe_Stale, desc="a L1 cache entry Modified", format="!b";
- MM, AccessPermission:Read_Write, desc="a L1 cache entry Modified", format="!b";
+ I, AccessPermission:Invalid, desc="L1 cache entry Idle";
+ S, AccessPermission:Read_Only, desc="Line is present in shared state in L1 and L0";
+ SS, AccessPermission:Read_Only, desc="Line is present in shared state in L1 but not L0";
+ E, AccessPermission:Read_Only, desc="Line is present in exclusive state in L1 and L0";
+ EE, AccessPermission:Read_Write, desc="Line is present in exclusive state in L1 but not L0";
+ M, AccessPermission:Maybe_Stale, desc="Line is present in modified state in L1 and present in L0", format="!b";
+ MM, AccessPermission:Read_Write, desc="Line is present in modified state in L1 but not present in L0", format="!b";
// Transient States
IS, AccessPermission:Busy, desc="L1 idle, issued GETS, have not seen response yet";
// For all of the following states, invalidate
// message has been sent to L0 cache. The response
// from the L0 cache has not been seen yet.
- S_IL0, AccessPermission:Busy;
- E_IL0, AccessPermission:Busy;
- M_IL0, AccessPermission:Busy;
- MM_IL0, AccessPermission:Read_Write;
- SM_IL0, AccessPermission:Busy;
+ S_IL0, AccessPermission:Busy, desc="Shared in L1, invalidation sent to L0, have not seen response yet";
+ E_IL0, AccessPermission:Busy, desc="Exclusive in L1, invalidation sent to L0, have not seen response yet";
+ M_IL0, AccessPermission:Busy, desc="Modified in L1, invalidation sent to L0, have not seen response yet";
+ MM_IL0, AccessPermission:Read_Write, desc="Invalidation sent to L0, have not seen response yet";
+ SM_IL0, AccessPermission:Busy, desc="Invalidation sent to L0, have not seen response yet";
}
// EVENTS
// Responses from the L0 Cache
// L0 cache received the invalidation message
// and has sent the data.
- L0_DataAck;
+ L0_DataAck, desc="L0 received INV message";
Inv, desc="Invalidate request from L2 bank";
- // internal generated request
- // Invalidate the line in L0 due to own requirements
- L0_Invalidate_Own;
- // Invalidate the line in L0 due to some other cache's requirements
- L0_Invalidate_Else;
- // Invalidate the line in the cache due to some one else / space needs.
- L1_Replacement;
+ // internally generated requests:
+ L0_Invalidate_Own, desc="Invalidate line in L0, due to this cache's (L1) requirements";
+ L0_Invalidate_Else, desc="Invalidate line in L0, due to another cache's requirements";
+ L1_Replacement, desc="Invalidate line in this cache (L1), due to another cache's requirements";
// other requests
Fwd_GETX, desc="GETX from other processor";