* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-machine(L1Cache, "MI Example L1 Cache")
-: Sequencer * sequencer;
- CacheMemory * cacheMemory;
- Cycles cache_response_latency := 12;
- Cycles issue_latency := 2;
- bool send_evictions;
+machine(MachineType:L1Cache, "MI Example L1 Cache")
+ : Sequencer * sequencer;
+ CacheMemory * cacheMemory;
+ Cycles cache_response_latency := 12;
+ Cycles issue_latency := 2;
+ bool send_evictions;
+
+ // NETWORK BUFFERS
+ MessageBuffer * requestFromCache, network="To", virtual_network="2",
+ vnet_type="request";
+ MessageBuffer * responseFromCache, network="To", virtual_network="4",
+ vnet_type="response";
+
+ MessageBuffer * forwardToCache, network="From", virtual_network="3",
+ vnet_type="forward";
+ MessageBuffer * responseToCache, network="From", virtual_network="4",
+ vnet_type="response";
+
+ MessageBuffer * mandatoryQueue;
{
-
- // NETWORK BUFFERS
- MessageBuffer requestFromCache, network="To", virtual_network="2", ordered="true", vnet_type="request";
- MessageBuffer responseFromCache, network="To", virtual_network="4", ordered="true", vnet_type="response";
-
- MessageBuffer forwardToCache, network="From", virtual_network="3", ordered="true", vnet_type="forward";
- MessageBuffer responseToCache, network="From", virtual_network="4", ordered="true", vnet_type="response";
-
// STATES
state_declaration(State, desc="Cache states") {
I, AccessPermission:Invalid, desc="Not Present/Invalid";
}
// STRUCTURE DEFINITIONS
-
- MessageBuffer mandatoryQueue, ordered="false";
-
// CacheEntry
structure(Entry, desc="...", interface="AbstractCacheEntry") {
State CacheState, desc="cache state";
}
structure(TBETable, external="yes") {
- TBE lookup(Address);
- void allocate(Address);
- void deallocate(Address);
- bool isPresent(Address);
+ TBE lookup(Addr);
+ void allocate(Addr);
+ void deallocate(Addr);
+ bool isPresent(Addr);
}
TBETable TBEs, template="<L1Cache_TBE>", constructor="m_number_of_TBEs";
// PROTOTYPES
+ Tick clockEdge();
+ Cycles ticksToCycles(Tick t);
void set_cache_entry(AbstractCacheEntry a);
void unset_cache_entry();
void set_tbe(TBE b);
void unset_tbe();
void profileMsgDelay(int virtualNetworkType, Cycles b);
- Entry getCacheEntry(Address address), return_by_pointer="yes" {
+ Entry getCacheEntry(Addr address), return_by_pointer="yes" {
return static_cast(Entry, "pointer", cacheMemory.lookup(address));
}
}
}
- State getState(TBE tbe, Entry cache_entry, Address addr) {
+ State getState(TBE tbe, Entry cache_entry, Addr addr) {
if (is_valid(tbe)) {
return tbe.TBEState;
}
}
- void setState(TBE tbe, Entry cache_entry, Address addr, State state) {
+ void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
if (is_valid(tbe)) {
tbe.TBEState := state;
}
}
- AccessPermission getAccessPermission(Address addr) {
+ AccessPermission getAccessPermission(Addr addr) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return L1Cache_State_to_permission(tbe.TBEState);
return AccessPermission:NotPresent;
}
- void setAccessPermission(Entry cache_entry, Address addr, State state) {
+ void setAccessPermission(Entry cache_entry, Addr addr, State state) {
if (is_valid(cache_entry)) {
cache_entry.changePermission(L1Cache_State_to_permission(state));
}
}
- DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ void functionalRead(Addr addr, Packet *pkt) {
+ TBE tbe := TBEs[addr];
+ if(is_valid(tbe)) {
+ testAndRead(addr, tbe.DataBlk, pkt);
+ } else {
+ testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
+ }
+ }
+
+ int functionalWrite(Addr addr, Packet *pkt) {
+ int num_functional_writes := 0;
+
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
- return tbe.DataBlk;
+ num_functional_writes := num_functional_writes +
+ testAndWrite(addr, tbe.DataBlk, pkt);
+ return num_functional_writes;
}
- return getCacheEntry(addr).DataBlk;
+ num_functional_writes := num_functional_writes +
+ testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
+ return num_functional_writes;
}
// NETWORK PORTS
out_port(responseNetwork_out, ResponseMsg, responseFromCache);
in_port(forwardRequestNetwork_in, RequestMsg, forwardToCache) {
- if (forwardRequestNetwork_in.isReady()) {
- peek(forwardRequestNetwork_in, RequestMsg, block_on="Addr") {
+ if (forwardRequestNetwork_in.isReady(clockEdge())) {
+ peek(forwardRequestNetwork_in, RequestMsg, block_on="addr") {
- Entry cache_entry := getCacheEntry(in_msg.Addr);
- TBE tbe := TBEs[in_msg.Addr];
+ Entry cache_entry := getCacheEntry(in_msg.addr);
+ TBE tbe := TBEs[in_msg.addr];
if (in_msg.Type == CoherenceRequestType:GETX) {
- trigger(Event:Fwd_GETX, in_msg.Addr, cache_entry, tbe);
+ trigger(Event:Fwd_GETX, in_msg.addr, cache_entry, tbe);
}
else if (in_msg.Type == CoherenceRequestType:WB_ACK) {
- trigger(Event:Writeback_Ack, in_msg.Addr, cache_entry, tbe);
+ trigger(Event:Writeback_Ack, in_msg.addr, cache_entry, tbe);
}
else if (in_msg.Type == CoherenceRequestType:WB_NACK) {
- trigger(Event:Writeback_Nack, in_msg.Addr, cache_entry, tbe);
+ trigger(Event:Writeback_Nack, in_msg.addr, cache_entry, tbe);
}
else if (in_msg.Type == CoherenceRequestType:INV) {
- trigger(Event:Inv, in_msg.Addr, cache_entry, tbe);
+ trigger(Event:Inv, in_msg.addr, cache_entry, tbe);
}
else {
error("Unexpected message");
}
in_port(responseNetwork_in, ResponseMsg, responseToCache) {
- if (responseNetwork_in.isReady()) {
- peek(responseNetwork_in, ResponseMsg, block_on="Addr") {
+ if (responseNetwork_in.isReady(clockEdge())) {
+ peek(responseNetwork_in, ResponseMsg, block_on="addr") {
- Entry cache_entry := getCacheEntry(in_msg.Addr);
- TBE tbe := TBEs[in_msg.Addr];
+ Entry cache_entry := getCacheEntry(in_msg.addr);
+ TBE tbe := TBEs[in_msg.addr];
if (in_msg.Type == CoherenceResponseType:DATA) {
- trigger(Event:Data, in_msg.Addr, cache_entry, tbe);
+ trigger(Event:Data, in_msg.addr, cache_entry, tbe);
}
else {
error("Unexpected message");
// Mandatory Queue
in_port(mandatoryQueue_in, RubyRequest, mandatoryQueue, desc="...") {
- if (mandatoryQueue_in.isReady()) {
+ if (mandatoryQueue_in.isReady(clockEdge())) {
peek(mandatoryQueue_in, RubyRequest, block_on="LineAddress") {
Entry cache_entry := getCacheEntry(in_msg.LineAddress);
action(a_issueRequest, "a", desc="Issue a request") {
enqueue(requestNetwork_out, RequestMsg, issue_latency) {
- out_msg.Addr := address;
+ out_msg.addr := address;
out_msg.Type := CoherenceRequestType:GETX;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_Address_to_Directory(address));
action(b_issuePUT, "b", desc="Issue a PUT request") {
enqueue(requestNetwork_out, RequestMsg, issue_latency) {
assert(is_valid(cache_entry));
- out_msg.Addr := address;
+ out_msg.addr := address;
out_msg.Type := CoherenceRequestType:PUTX;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_Address_to_Directory(address));
peek(forwardRequestNetwork_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, cache_response_latency) {
assert(is_valid(cache_entry));
- out_msg.Addr := address;
+ out_msg.addr := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
out_msg.Destination.add(in_msg.Requestor);
peek(forwardRequestNetwork_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, cache_response_latency) {
assert(is_valid(tbe));
- out_msg.Addr := address;
+ out_msg.addr := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
out_msg.Destination.add(in_msg.Requestor);
}
action(m_popMandatoryQueue, "m", desc="Pop the mandatory request queue") {
- mandatoryQueue_in.dequeue();
+ mandatoryQueue_in.dequeue(clockEdge());
}
action(n_popResponseQueue, "n", desc="Pop the response queue") {
- profileMsgDelay(1, responseNetwork_in.dequeue());
+ Tick delay := responseNetwork_in.dequeue(clockEdge());
+ profileMsgDelay(1, ticksToCycles(delay));
}
action(o_popForwardedRequestQueue, "o", desc="Pop the forwarded request queue") {
- profileMsgDelay(2, forwardRequestNetwork_in.dequeue());
+ Tick delay := forwardRequestNetwork_in.dequeue(clockEdge());
+ profileMsgDelay(2, ticksToCycles(delay));
}
action(p_profileMiss, "pi", desc="Profile cache miss") {
action(r_load_hit, "r", desc="Notify sequencer the load completed.") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
+ cacheMemory.setMRU(cache_entry);
sequencer.readCallback(address, cache_entry.DataBlk, false);
}
peek(responseNetwork_in, ResponseMsg) {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
+ cacheMemory.setMRU(cache_entry);
sequencer.readCallback(address, cache_entry.DataBlk, true,
machineIDToMachineType(in_msg.Sender));
}
action(s_store_hit, "s", desc="Notify sequencer that store completed.") {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
+ cacheMemory.setMRU(cache_entry);
sequencer.writeCallback(address, cache_entry.DataBlk, false);
}
peek(responseNetwork_in, ResponseMsg) {
assert(is_valid(cache_entry));
DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
+ cacheMemory.setMRU(cache_entry);
sequencer.writeCallback(address, cache_entry.DataBlk, true,
machineIDToMachineType(in_msg.Sender));
}
action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") {
if (send_evictions) {
- DPRINTF(RubySlicc, "Sending invalidation for %s to the CPU\n", address);
+ DPRINTF(RubySlicc, "Sending invalidation for %#x to the CPU\n", address);
sequencer.evictionCallback(address);
}
}