Ruby: Add support for functional accesses
[gem5.git] / src / mem / protocol / MOESI_CMP_token-L1cache.sm
index 226f213744197be2639fef9b23efb4add1e3aa72..66789b594a6cb3d17efe24ea7c564a66fd4d1add 100644 (file)
@@ -49,43 +49,43 @@ machine(L1Cache, "Token protocol")
   // From this node's L1 cache TO the network
 
   // a local L1 -> this L2 bank
-  MessageBuffer responseFromL1Cache, network="To", virtual_network="4", ordered="false";
-  MessageBuffer persistentFromL1Cache, network="To", virtual_network="3", ordered="true";
+  MessageBuffer responseFromL1Cache, network="To", virtual_network="4", ordered="false", vnet_type="response";
+  MessageBuffer persistentFromL1Cache, network="To", virtual_network="3", ordered="true", vnet_type="persistent";
   // a local L1 -> this L2 bank, currently ordered with directory forwarded requests
-  MessageBuffer requestFromL1Cache, network="To", virtual_network="1", ordered="false";
+  MessageBuffer requestFromL1Cache, network="To", virtual_network="1", ordered="false", vnet_type="request";
 
 
   // To this node's L1 cache FROM the network
   // a L2 bank -> this L1
-  MessageBuffer responseToL1Cache, network="From", virtual_network="4", ordered="false";
-  MessageBuffer persistentToL1Cache, network="From", virtual_network="3", ordered="true";
+  MessageBuffer responseToL1Cache, network="From", virtual_network="4", ordered="false", vnet_type="response";
+  MessageBuffer persistentToL1Cache, network="From", virtual_network="3", ordered="true", vnet_type="persistent";
   // a L2 bank -> this L1
-  MessageBuffer requestToL1Cache, network="From", virtual_network="1", ordered="false";
+  MessageBuffer requestToL1Cache, network="From", virtual_network="1", ordered="false", vnet_type="request";
 
   // STATES
-  enumeration(State, desc="Cache states", default="L1Cache_State_I") {
+  state_declaration(State, desc="Cache states", default="L1Cache_State_I") {
     // Base states
-    NP,   "NP",   desc="Not Present";
-    I,    "I",    desc="Idle";
-    S,    "S",    desc="Shared";
-    O,    "O",    desc="Owned";
-    M,    "M",    desc="Modified (dirty)";
-    MM,   "MM",   desc="Modified (dirty and locally modified)";
-    M_W,  "M^W",  desc="Modified (dirty), waiting";
-    MM_W, "MM^W", desc="Modified (dirty and locally modified), waiting";
+    NP, AccessPermission:Invalid, "NP", desc="Not Present";
+    I, AccessPermission:Invalid, "I", desc="Idle";
+    S, AccessPermission:Read_Only, "S", desc="Shared";
+    O, AccessPermission:Read_Only, "O", desc="Owned";
+    M, AccessPermission:Read_Only, "M", desc="Modified (dirty)";
+    MM, AccessPermission:Read_Write, "MM", desc="Modified (dirty and locally modified)";
+    M_W, AccessPermission:Read_Only, "M^W", desc="Modified (dirty), waiting";
+    MM_W, AccessPermission:Read_Write, "MM^W", desc="Modified (dirty and locally modified), waiting";
 
     // Transient States
-    IM, "IM", desc="Issued GetX";
-    SM, "SM", desc="Issued GetX, we still have an old copy of the line";
-    OM, "OM", desc="Issued GetX, received data";
-    IS, "IS", desc="Issued GetS";
+    IM, AccessPermission:Busy, "IM", desc="Issued GetX";
+    SM, AccessPermission:Read_Only, "SM", desc="Issued GetX, we still have an old copy of the line";
+    OM, AccessPermission:Read_Only, "OM", desc="Issued GetX, received data";
+    IS, AccessPermission:Busy, "IS", desc="Issued GetS";
 
     // Locked states
-    I_L,  "I^L",   desc="Invalid, Locked";
-    S_L,  "S^L",   desc="Shared, Locked";
-    IM_L, "IM^L",  desc="Invalid, Locked, trying to go to Modified";
-    SM_L, "SM^L",  desc="Shared, Locked, trying to go to Modified";
-    IS_L, "IS^L",  desc="Invalid, Locked, trying to go to Shared";
+    I_L, AccessPermission:Busy, "I^L", desc="Invalid, Locked";
+    S_L, AccessPermission:Busy, "S^L", desc="Shared, Locked";
+    IM_L, AccessPermission:Busy, "IM^L", desc="Invalid, Locked, trying to go to Modified";
+    SM_L, AccessPermission:Busy, "SM^L", desc="Shared, Locked, trying to go to Modified";
+    IS_L, AccessPermission:Busy, "IS^L", desc="Invalid, Locked, trying to go to Shared";
   }
 
   // EVENTS
@@ -149,18 +149,18 @@ machine(L1Cache, "Token protocol")
 
     AccessType AccessType,                desc="Type of request (used for profiling)";
     Time IssueTime,                       desc="Time the request was issued";
-    AccessModeType AccessMode,    desc="user/supervisor access type";
+    RubyAccessMode AccessMode,    desc="user/supervisor access type";
     PrefetchBit Prefetch,         desc="Is this a prefetch request";
   }
 
-  external_type(TBETable) {
+  structure(TBETable, external="yes") {
     TBE lookup(Address);
     void allocate(Address);
     void deallocate(Address);
     bool isPresent(Address);
   }
 
-  external_type(PersistentTable) {
+  structure(PersistentTable, external="yes") {
     void persistentRequestLock(Address, MachineID, AccessType);
     void persistentRequestUnlock(Address, MachineID);
     bool okToIssueStarving(Address, MachineID);
@@ -176,6 +176,8 @@ machine(L1Cache, "Token protocol")
   void unset_cache_entry();
   void set_tbe(TBE b);
   void unset_tbe();
+  void wakeUpAllBuffers();
+  void wakeUpBuffers(Address a);
 
   TBETable L1_TBEs, template_hack="<L1Cache_TBE>";
 
@@ -225,6 +227,10 @@ machine(L1Cache, "Token protocol")
     return L1Icache_entry;
   }
 
+  DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+    return getCacheEntry(addr).DataBlk;
+  }
+
   Entry getL1DCacheEntry(Address addr), return_by_pointer="yes" {
     Entry L1Dcache_entry := static_cast(Entry, "pointer", L1DcacheMemory.lookup(addr));
     return L1Dcache_entry;
@@ -336,51 +342,54 @@ machine(L1Cache, "Token protocol")
       }
 
       cache_entry.CacheState := state;
+    }
+  }
 
-      // Set permission
-      if (state == State:MM ||
-          state == State:MM_W) {
-        cache_entry.changePermission(AccessPermission:Read_Write);
-      } else if ((state == State:S) ||
-                 (state == State:O) ||
-                 (state == State:M) ||
-                 (state == State:M_W) ||
-                 (state == State:SM) ||
-                 (state == State:S_L) ||
-                 (state == State:SM_L) ||
-                 (state == State:OM)) {
-        cache_entry.changePermission(AccessPermission:Read_Only);
-      } else {
-        cache_entry.changePermission(AccessPermission:Invalid);
-      }
+  AccessPermission getAccessPermission(Address addr) {
+    TBE tbe := L1_TBEs[addr];
+    if(is_valid(tbe)) {
+      return L1Cache_State_to_permission(tbe.TBEState);
+    }
+
+    Entry cache_entry := getCacheEntry(addr);
+    if(is_valid(cache_entry)) {
+      return L1Cache_State_to_permission(cache_entry.CacheState);
+    }
+
+    return AccessPermission:NotPresent;
+  }
+
+  void setAccessPermission(Entry cache_entry, Address addr, State state) {
+    if (is_valid(cache_entry)) {
+      cache_entry.changePermission(L1Cache_State_to_permission(state));
     }
   }
 
-  Event mandatory_request_type_to_event(CacheRequestType type) {
-    if (type == CacheRequestType:LD) {
+  Event mandatory_request_type_to_event(RubyRequestType type) {
+    if (type == RubyRequestType:LD) {
       return Event:Load;
-    } else if (type == CacheRequestType:IFETCH) {
+    } else if (type == RubyRequestType:IFETCH) {
       return Event:Ifetch;
-    } else if (type == CacheRequestType:ST) {
+    } else if (type == RubyRequestType:ST) {
       return Event:Store;
-    } else if (type == CacheRequestType:ATOMIC) {
+    } else if (type == RubyRequestType:ATOMIC) {
       if (no_mig_atomic) {
         return Event:Atomic;
       } else {
         return Event:Store;
       }
     } else {
-      error("Invalid CacheRequestType");
+      error("Invalid RubyRequestType");
     }
   }
 
-  AccessType cache_request_type_to_access_type(CacheRequestType type) {
-    if ((type == CacheRequestType:LD) || (type == CacheRequestType:IFETCH)) {
+  AccessType cache_request_type_to_access_type(RubyRequestType type) {
+    if ((type == RubyRequestType:LD) || (type == RubyRequestType:IFETCH)) {
       return AccessType:Read;
-    } else if ((type == CacheRequestType:ST) || (type == CacheRequestType:ATOMIC)) {
+    } else if ((type == RubyRequestType:ST) || (type == RubyRequestType:ATOMIC)) {
       return AccessType:Write;
     } else {
-      error("Invalid CacheRequestType");
+      error("Invalid RubyRequestType");
     }
   }
 
@@ -637,14 +646,14 @@ machine(L1Cache, "Token protocol")
   }
 
   // Mandatory Queue
-  in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...", rank=0) {
+  in_port(mandatoryQueue_in, RubyRequest, mandatoryQueue, desc="...", rank=0) {
     if (mandatoryQueue_in.isReady()) {
-      peek(mandatoryQueue_in, CacheMsg, block_on="LineAddress") {
+      peek(mandatoryQueue_in, RubyRequest, block_on="LineAddress") {
         // Check for data access to blocks in I-cache and ifetchs to blocks in D-cache
 
         TBE tbe := L1_TBEs[in_msg.LineAddress];
 
-        if (in_msg.Type == CacheRequestType:IFETCH) {
+        if (in_msg.Type == RubyRequestType:IFETCH) {
           // ** INSTRUCTION ACCESS ***
 
           Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress);
@@ -1325,10 +1334,10 @@ machine(L1Cache, "Token protocol")
     L1_TBEs.allocate(address);
     set_tbe(L1_TBEs[address]);
     tbe.IssueCount := 0;
-    peek(mandatoryQueue_in, CacheMsg) {
+    peek(mandatoryQueue_in, RubyRequest) {
       tbe.PC := in_msg.ProgramCounter;
       tbe.AccessType := cache_request_type_to_access_type(in_msg.Type);
-      if (in_msg.Type == CacheRequestType:ATOMIC) {
+      if (in_msg.Type == RubyRequestType:ATOMIC) {
         tbe.IsAtomic := true;
       }
       tbe.Prefetch := in_msg.Prefetch;
@@ -1338,7 +1347,7 @@ machine(L1Cache, "Token protocol")
   }
 
   action(ta_traceStalledAddress, "ta", desc="Trace Stalled Address") {
-    peek(mandatoryQueue_in, CacheMsg) {
+    peek(mandatoryQueue_in, RubyRequest) {
       APPEND_TRANSITION_COMMENT(in_msg.LineAddress);
     }
   }
@@ -1514,7 +1523,7 @@ machine(L1Cache, "Token protocol")
   }
 
   action(uu_profileMiss, "\u", desc="Profile the demand miss") {
-    peek(mandatoryQueue_in, CacheMsg) {
+    peek(mandatoryQueue_in, RubyRequest) {
       if (L1DcacheMemory.isTagPresent(address)) {
         L1DcacheMemory.profileMiss(in_msg);
       } else {
@@ -1531,18 +1540,18 @@ machine(L1Cache, "Token protocol")
   }
 
   action(zz_stallAndWaitMandatoryQueue, "\z", desc="Send the head of the mandatory queue to the back of the queue.") {
-    peek(mandatoryQueue_in, CacheMsg) {
+    peek(mandatoryQueue_in, RubyRequest) {
       APPEND_TRANSITION_COMMENT(in_msg.LineAddress);
     } 
     stall_and_wait(mandatoryQueue_in, address);    
   }
 
   action(kd_wakeUpDependents, "kd", desc="wake-up dependents") {
-    wake_up_dependents(address);
+    wakeUpBuffers(address);
   }
 
   action(ka_wakeUpAllDependents, "ka", desc="wake-up all dependents") {
-    wake_up_all_dependents();
+    wakeUpAllBuffers();
   }
 
   //*****************************************************