1/* 2 * Copyright (c) 1999-2013 Mark D. Hill and David A. Wood 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29machine(MachineType:L1Cache, "MESI Directory L1 Cache CMP") 30 : Sequencer * sequencer; 31 CacheMemory * L1Icache; 32 CacheMemory * L1Dcache; 33 Prefetcher * prefetcher; 34 int l2_select_num_bits; 35 Cycles l1_request_latency := 2; 36 Cycles l1_response_latency := 2; 37 Cycles to_l2_latency := 1; 38 bool send_evictions; 39 bool enable_prefetch := "False"; 40 41 // Message Queues 42 // From this node's L1 cache TO the network 43 44 // a local L1 -> this L2 bank, currently ordered with directory forwarded requests 45 MessageBuffer * requestFromL1Cache, network="To", virtual_network="0", 46 vnet_type="request"; 47 48 // a local L1 -> this L2 bank 49 MessageBuffer * responseFromL1Cache, network="To", virtual_network="1", 50 vnet_type="response"; 51 52 MessageBuffer * unblockFromL1Cache, network="To", virtual_network="2", 53 vnet_type="unblock"; 54 55 56 // To this node's L1 cache FROM the network 57 // a L2 bank -> this L1 58 MessageBuffer * requestToL1Cache, network="From", virtual_network="2", 59 vnet_type="request"; 60 61 // a L2 bank -> this L1 62 MessageBuffer * responseToL1Cache, network="From", virtual_network="1", 63 vnet_type="response"; 64 65 // Request Buffer for prefetches 66 MessageBuffer * optionalQueue; 67 68 // Buffer for requests generated by the processor core. 69 MessageBuffer * mandatoryQueue; 70{ 71 // STATES 72 state_declaration(State, desc="Cache states", default="L1Cache_State_I") { 73 // Base states 74 NP, AccessPermission:Invalid, desc="Not present in either cache"; 75 I, AccessPermission:Invalid, desc="a L1 cache entry Idle"; 76 S, AccessPermission:Read_Only, desc="a L1 cache entry Shared"; 77 E, AccessPermission:Read_Only, desc="a L1 cache entry Exclusive"; 78 M, AccessPermission:Read_Write, desc="a L1 cache entry Modified", format="!b"; 79 80 // Transient States 81 IS, AccessPermission:Busy, desc="L1 idle, issued GETS, have not seen response yet"; 82 IM, AccessPermission:Busy, desc="L1 idle, issued GETX, have not seen response yet"; 83 SM, AccessPermission:Read_Only, desc="L1 idle, issued GETX, have not seen response yet"; 84 IS_I, AccessPermission:Busy, desc="L1 idle, issued GETS, saw Inv before data because directory doesn't block on GETS hit"; 85 86 M_I, AccessPermission:Busy, desc="L1 replacing, waiting for ACK"; 87 SINK_WB_ACK, AccessPermission:Busy, desc="This is to sink WB_Acks from L2"; 88 89 // Transient States in which block is being prefetched 90 PF_IS, AccessPermission:Busy, desc="Issued GETS, have not seen response yet"; 91 PF_IM, AccessPermission:Busy, desc="Issued GETX, have not seen response yet"; 92 PF_SM, AccessPermission:Busy, desc="Issued GETX, received data, waiting for acks"; 93 PF_IS_I, AccessPermission:Busy, desc="Issued GETs, saw inv before data"; 94 } 95 96 // EVENTS 97 enumeration(Event, desc="Cache events") { 98 // L1 events 99 Load, desc="Load request from the home processor"; 100 Ifetch, desc="I-fetch request from the home processor"; 101 Store, desc="Store request from the home processor"; 102 103 Inv, desc="Invalidate request from L2 bank"; 104 105 // internal generated request 106 L1_Replacement, desc="L1 Replacement", format="!r"; 107 PF_L1_Replacement, desc="Prefetch L1 Replacement", format="!pr"; 108 109 // other requests 110 Fwd_GETX, desc="GETX from other processor"; 111 Fwd_GETS, desc="GETS from other processor"; 112 Fwd_GET_INSTR, desc="GET_INSTR from other processor"; 113 114 Data, desc="Data for processor"; 115 Data_Exclusive, desc="Data for processor"; 116 DataS_fromL1, desc="data for GETS request, need to unblock directory"; 117 Data_all_Acks, desc="Data for processor, all acks"; 118 119 Ack, desc="Ack for processor"; 120 Ack_all, desc="Last ack for processor"; 121 122 WB_Ack, desc="Ack for replacement"; 123 124 PF_Load, desc="load request from prefetcher"; 125 PF_Ifetch, desc="instruction fetch request from prefetcher"; 126 PF_Store, desc="exclusive load request from prefetcher"; 127 } 128 129 // TYPES 130 131 // CacheEntry 132 structure(Entry, desc="...", interface="AbstractCacheEntry" ) { 133 State CacheState, desc="cache state"; 134 DataBlock DataBlk, desc="data for the block"; 135 bool Dirty, default="false", desc="data is dirty"; 136 bool isPrefetch, desc="Set if this block was prefetched and not yet accessed"; 137 } 138 139 // TBE fields 140 structure(TBE, desc="...") { 141 Addr addr, desc="Physical address for this TBE"; 142 State TBEState, desc="Transient state"; 143 DataBlock DataBlk, desc="Buffer for the data block"; 144 bool Dirty, default="false", desc="data is dirty"; 145 bool isPrefetch, desc="Set if this was caused by a prefetch"; 146 int pendingAcks, default="0", desc="number of pending acks"; 147 } 148 149 structure(TBETable, external="yes") { 150 TBE lookup(Addr); 151 void allocate(Addr); 152 void deallocate(Addr); 153 bool isPresent(Addr); 154 } 155 156 TBETable TBEs, template="<L1Cache_TBE>", constructor="m_number_of_TBEs"; 157 158 int l2_select_low_bit, default="RubySystem::getBlockSizeBits()"; 159 160 Tick clockEdge(); 161 Cycles ticksToCycles(Tick t); 162 void set_cache_entry(AbstractCacheEntry a); 163 void unset_cache_entry(); 164 void set_tbe(TBE a); 165 void unset_tbe(); 166 void wakeUpBuffers(Addr a); 167 void profileMsgDelay(int virtualNetworkType, Cycles c); 168 169 // inclusive cache returns L1 entries only 170 Entry getCacheEntry(Addr addr), return_by_pointer="yes" { 171 Entry L1Dcache_entry := static_cast(Entry, "pointer", L1Dcache[addr]); 172 if(is_valid(L1Dcache_entry)) { 173 return L1Dcache_entry; 174 } 175 176 Entry L1Icache_entry := static_cast(Entry, "pointer", L1Icache[addr]); 177 return L1Icache_entry; 178 } 179 180 Entry getL1DCacheEntry(Addr addr), return_by_pointer="yes" { 181 Entry L1Dcache_entry := static_cast(Entry, "pointer", L1Dcache[addr]); 182 return L1Dcache_entry; 183 } 184 185 Entry getL1ICacheEntry(Addr addr), return_by_pointer="yes" { 186 Entry L1Icache_entry := static_cast(Entry, "pointer", L1Icache[addr]); 187 return L1Icache_entry; 188 } 189 190 State getState(TBE tbe, Entry cache_entry, Addr addr) { 191 assert((L1Dcache.isTagPresent(addr) && L1Icache.isTagPresent(addr)) == false); 192 193 if(is_valid(tbe)) { 194 return tbe.TBEState; 195 } else if (is_valid(cache_entry)) { 196 return cache_entry.CacheState; 197 } 198 return State:NP; 199 } 200 201 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) { 202 assert((L1Dcache.isTagPresent(addr) && L1Icache.isTagPresent(addr)) == false); 203 204 // MUST CHANGE 205 if(is_valid(tbe)) { 206 tbe.TBEState := state; 207 } 208 209 if (is_valid(cache_entry)) { 210 cache_entry.CacheState := state; 211 } 212 } 213 214 AccessPermission getAccessPermission(Addr addr) { 215 TBE tbe := TBEs[addr]; 216 if(is_valid(tbe)) { 217 DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(tbe.TBEState)); 218 return L1Cache_State_to_permission(tbe.TBEState); 219 } 220 221 Entry cache_entry := getCacheEntry(addr); 222 if(is_valid(cache_entry)) { 223 DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(cache_entry.CacheState)); 224 return L1Cache_State_to_permission(cache_entry.CacheState); 225 } 226 227 DPRINTF(RubySlicc, "%s\n", AccessPermission:NotPresent); 228 return AccessPermission:NotPresent; 229 } 230 231 void functionalRead(Addr addr, Packet *pkt) { 232 TBE tbe := TBEs[addr]; 233 if(is_valid(tbe)) { 234 testAndRead(addr, tbe.DataBlk, pkt); 235 } else { 236 testAndRead(addr, getCacheEntry(addr).DataBlk, pkt); 237 } 238 } 239 240 int functionalWrite(Addr addr, Packet *pkt) { 241 int num_functional_writes := 0; 242 243 TBE tbe := TBEs[addr]; 244 if(is_valid(tbe)) { 245 num_functional_writes := num_functional_writes + 246 testAndWrite(addr, tbe.DataBlk, pkt); 247 return num_functional_writes; 248 } 249 250 num_functional_writes := num_functional_writes + 251 testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt); 252 return num_functional_writes; 253 } 254 255 void setAccessPermission(Entry cache_entry, Addr addr, State state) { 256 if (is_valid(cache_entry)) { 257 cache_entry.changePermission(L1Cache_State_to_permission(state)); 258 } 259 } 260 261 Event mandatory_request_type_to_event(RubyRequestType type) { 262 if (type == RubyRequestType:LD) { 263 return Event:Load; 264 } else if (type == RubyRequestType:IFETCH) { 265 return Event:Ifetch; 266 } else if ((type == RubyRequestType:ST) || (type == RubyRequestType:ATOMIC)) { 267 return Event:Store; 268 } else { 269 error("Invalid RubyRequestType"); 270 } 271 } 272 273 Event prefetch_request_type_to_event(RubyRequestType type) { 274 if (type == RubyRequestType:LD) { 275 return Event:PF_Load; 276 } else if (type == RubyRequestType:IFETCH) { 277 return Event:PF_Ifetch; 278 } else if ((type == RubyRequestType:ST) || 279 (type == RubyRequestType:ATOMIC)) { 280 return Event:PF_Store; 281 } else { 282 error("Invalid RubyRequestType"); 283 } 284 } 285 286 int getPendingAcks(TBE tbe) { 287 return tbe.pendingAcks; 288 } 289 290 out_port(requestL1Network_out, RequestMsg, requestFromL1Cache); 291 out_port(responseL1Network_out, ResponseMsg, responseFromL1Cache); 292 out_port(unblockNetwork_out, ResponseMsg, unblockFromL1Cache); 293 out_port(optionalQueue_out, RubyRequest, optionalQueue); 294 295 296 // Prefetch queue between the controller and the prefetcher 297 // As per Spracklen et al. (HPCA 2005), the prefetch queue should be 298 // implemented as a LIFO structure. The structure would allow for fast 299 // searches of all entries in the queue, not just the head msg. All 300 // msgs in the structure can be invalidated if a demand miss matches. 301 in_port(optionalQueue_in, RubyRequest, optionalQueue, desc="...", rank = 3) { 302 if (optionalQueue_in.isReady(clockEdge())) { 303 peek(optionalQueue_in, RubyRequest) { 304 // Instruction Prefetch 305 if (in_msg.Type == RubyRequestType:IFETCH) { 306 Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); 307 if (is_valid(L1Icache_entry)) { 308 // The block to be prefetched is already present in the 309 // cache. We should drop this request. 310 trigger(prefetch_request_type_to_event(in_msg.Type), 311 in_msg.LineAddress, 312 L1Icache_entry, TBEs[in_msg.LineAddress]); 313 } 314 315 // Check to see if it is in the OTHER L1 316 Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); 317 if (is_valid(L1Dcache_entry)) { 318 // The block is in the wrong L1 cache. We should drop 319 // this request. 320 trigger(prefetch_request_type_to_event(in_msg.Type), 321 in_msg.LineAddress, 322 L1Dcache_entry, TBEs[in_msg.LineAddress]); 323 } 324 325 if (L1Icache.cacheAvail(in_msg.LineAddress)) { 326 // L1 does't have the line, but we have space for it 327 // in the L1 so let's see if the L2 has it 328 trigger(prefetch_request_type_to_event(in_msg.Type), 329 in_msg.LineAddress, 330 L1Icache_entry, TBEs[in_msg.LineAddress]); 331 } else { 332 // No room in the L1, so we need to make room in the L1
| 1/* 2 * Copyright (c) 1999-2013 Mark D. Hill and David A. Wood 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29machine(MachineType:L1Cache, "MESI Directory L1 Cache CMP") 30 : Sequencer * sequencer; 31 CacheMemory * L1Icache; 32 CacheMemory * L1Dcache; 33 Prefetcher * prefetcher; 34 int l2_select_num_bits; 35 Cycles l1_request_latency := 2; 36 Cycles l1_response_latency := 2; 37 Cycles to_l2_latency := 1; 38 bool send_evictions; 39 bool enable_prefetch := "False"; 40 41 // Message Queues 42 // From this node's L1 cache TO the network 43 44 // a local L1 -> this L2 bank, currently ordered with directory forwarded requests 45 MessageBuffer * requestFromL1Cache, network="To", virtual_network="0", 46 vnet_type="request"; 47 48 // a local L1 -> this L2 bank 49 MessageBuffer * responseFromL1Cache, network="To", virtual_network="1", 50 vnet_type="response"; 51 52 MessageBuffer * unblockFromL1Cache, network="To", virtual_network="2", 53 vnet_type="unblock"; 54 55 56 // To this node's L1 cache FROM the network 57 // a L2 bank -> this L1 58 MessageBuffer * requestToL1Cache, network="From", virtual_network="2", 59 vnet_type="request"; 60 61 // a L2 bank -> this L1 62 MessageBuffer * responseToL1Cache, network="From", virtual_network="1", 63 vnet_type="response"; 64 65 // Request Buffer for prefetches 66 MessageBuffer * optionalQueue; 67 68 // Buffer for requests generated by the processor core. 69 MessageBuffer * mandatoryQueue; 70{ 71 // STATES 72 state_declaration(State, desc="Cache states", default="L1Cache_State_I") { 73 // Base states 74 NP, AccessPermission:Invalid, desc="Not present in either cache"; 75 I, AccessPermission:Invalid, desc="a L1 cache entry Idle"; 76 S, AccessPermission:Read_Only, desc="a L1 cache entry Shared"; 77 E, AccessPermission:Read_Only, desc="a L1 cache entry Exclusive"; 78 M, AccessPermission:Read_Write, desc="a L1 cache entry Modified", format="!b"; 79 80 // Transient States 81 IS, AccessPermission:Busy, desc="L1 idle, issued GETS, have not seen response yet"; 82 IM, AccessPermission:Busy, desc="L1 idle, issued GETX, have not seen response yet"; 83 SM, AccessPermission:Read_Only, desc="L1 idle, issued GETX, have not seen response yet"; 84 IS_I, AccessPermission:Busy, desc="L1 idle, issued GETS, saw Inv before data because directory doesn't block on GETS hit"; 85 86 M_I, AccessPermission:Busy, desc="L1 replacing, waiting for ACK"; 87 SINK_WB_ACK, AccessPermission:Busy, desc="This is to sink WB_Acks from L2"; 88 89 // Transient States in which block is being prefetched 90 PF_IS, AccessPermission:Busy, desc="Issued GETS, have not seen response yet"; 91 PF_IM, AccessPermission:Busy, desc="Issued GETX, have not seen response yet"; 92 PF_SM, AccessPermission:Busy, desc="Issued GETX, received data, waiting for acks"; 93 PF_IS_I, AccessPermission:Busy, desc="Issued GETs, saw inv before data"; 94 } 95 96 // EVENTS 97 enumeration(Event, desc="Cache events") { 98 // L1 events 99 Load, desc="Load request from the home processor"; 100 Ifetch, desc="I-fetch request from the home processor"; 101 Store, desc="Store request from the home processor"; 102 103 Inv, desc="Invalidate request from L2 bank"; 104 105 // internal generated request 106 L1_Replacement, desc="L1 Replacement", format="!r"; 107 PF_L1_Replacement, desc="Prefetch L1 Replacement", format="!pr"; 108 109 // other requests 110 Fwd_GETX, desc="GETX from other processor"; 111 Fwd_GETS, desc="GETS from other processor"; 112 Fwd_GET_INSTR, desc="GET_INSTR from other processor"; 113 114 Data, desc="Data for processor"; 115 Data_Exclusive, desc="Data for processor"; 116 DataS_fromL1, desc="data for GETS request, need to unblock directory"; 117 Data_all_Acks, desc="Data for processor, all acks"; 118 119 Ack, desc="Ack for processor"; 120 Ack_all, desc="Last ack for processor"; 121 122 WB_Ack, desc="Ack for replacement"; 123 124 PF_Load, desc="load request from prefetcher"; 125 PF_Ifetch, desc="instruction fetch request from prefetcher"; 126 PF_Store, desc="exclusive load request from prefetcher"; 127 } 128 129 // TYPES 130 131 // CacheEntry 132 structure(Entry, desc="...", interface="AbstractCacheEntry" ) { 133 State CacheState, desc="cache state"; 134 DataBlock DataBlk, desc="data for the block"; 135 bool Dirty, default="false", desc="data is dirty"; 136 bool isPrefetch, desc="Set if this block was prefetched and not yet accessed"; 137 } 138 139 // TBE fields 140 structure(TBE, desc="...") { 141 Addr addr, desc="Physical address for this TBE"; 142 State TBEState, desc="Transient state"; 143 DataBlock DataBlk, desc="Buffer for the data block"; 144 bool Dirty, default="false", desc="data is dirty"; 145 bool isPrefetch, desc="Set if this was caused by a prefetch"; 146 int pendingAcks, default="0", desc="number of pending acks"; 147 } 148 149 structure(TBETable, external="yes") { 150 TBE lookup(Addr); 151 void allocate(Addr); 152 void deallocate(Addr); 153 bool isPresent(Addr); 154 } 155 156 TBETable TBEs, template="<L1Cache_TBE>", constructor="m_number_of_TBEs"; 157 158 int l2_select_low_bit, default="RubySystem::getBlockSizeBits()"; 159 160 Tick clockEdge(); 161 Cycles ticksToCycles(Tick t); 162 void set_cache_entry(AbstractCacheEntry a); 163 void unset_cache_entry(); 164 void set_tbe(TBE a); 165 void unset_tbe(); 166 void wakeUpBuffers(Addr a); 167 void profileMsgDelay(int virtualNetworkType, Cycles c); 168 169 // inclusive cache returns L1 entries only 170 Entry getCacheEntry(Addr addr), return_by_pointer="yes" { 171 Entry L1Dcache_entry := static_cast(Entry, "pointer", L1Dcache[addr]); 172 if(is_valid(L1Dcache_entry)) { 173 return L1Dcache_entry; 174 } 175 176 Entry L1Icache_entry := static_cast(Entry, "pointer", L1Icache[addr]); 177 return L1Icache_entry; 178 } 179 180 Entry getL1DCacheEntry(Addr addr), return_by_pointer="yes" { 181 Entry L1Dcache_entry := static_cast(Entry, "pointer", L1Dcache[addr]); 182 return L1Dcache_entry; 183 } 184 185 Entry getL1ICacheEntry(Addr addr), return_by_pointer="yes" { 186 Entry L1Icache_entry := static_cast(Entry, "pointer", L1Icache[addr]); 187 return L1Icache_entry; 188 } 189 190 State getState(TBE tbe, Entry cache_entry, Addr addr) { 191 assert((L1Dcache.isTagPresent(addr) && L1Icache.isTagPresent(addr)) == false); 192 193 if(is_valid(tbe)) { 194 return tbe.TBEState; 195 } else if (is_valid(cache_entry)) { 196 return cache_entry.CacheState; 197 } 198 return State:NP; 199 } 200 201 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) { 202 assert((L1Dcache.isTagPresent(addr) && L1Icache.isTagPresent(addr)) == false); 203 204 // MUST CHANGE 205 if(is_valid(tbe)) { 206 tbe.TBEState := state; 207 } 208 209 if (is_valid(cache_entry)) { 210 cache_entry.CacheState := state; 211 } 212 } 213 214 AccessPermission getAccessPermission(Addr addr) { 215 TBE tbe := TBEs[addr]; 216 if(is_valid(tbe)) { 217 DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(tbe.TBEState)); 218 return L1Cache_State_to_permission(tbe.TBEState); 219 } 220 221 Entry cache_entry := getCacheEntry(addr); 222 if(is_valid(cache_entry)) { 223 DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(cache_entry.CacheState)); 224 return L1Cache_State_to_permission(cache_entry.CacheState); 225 } 226 227 DPRINTF(RubySlicc, "%s\n", AccessPermission:NotPresent); 228 return AccessPermission:NotPresent; 229 } 230 231 void functionalRead(Addr addr, Packet *pkt) { 232 TBE tbe := TBEs[addr]; 233 if(is_valid(tbe)) { 234 testAndRead(addr, tbe.DataBlk, pkt); 235 } else { 236 testAndRead(addr, getCacheEntry(addr).DataBlk, pkt); 237 } 238 } 239 240 int functionalWrite(Addr addr, Packet *pkt) { 241 int num_functional_writes := 0; 242 243 TBE tbe := TBEs[addr]; 244 if(is_valid(tbe)) { 245 num_functional_writes := num_functional_writes + 246 testAndWrite(addr, tbe.DataBlk, pkt); 247 return num_functional_writes; 248 } 249 250 num_functional_writes := num_functional_writes + 251 testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt); 252 return num_functional_writes; 253 } 254 255 void setAccessPermission(Entry cache_entry, Addr addr, State state) { 256 if (is_valid(cache_entry)) { 257 cache_entry.changePermission(L1Cache_State_to_permission(state)); 258 } 259 } 260 261 Event mandatory_request_type_to_event(RubyRequestType type) { 262 if (type == RubyRequestType:LD) { 263 return Event:Load; 264 } else if (type == RubyRequestType:IFETCH) { 265 return Event:Ifetch; 266 } else if ((type == RubyRequestType:ST) || (type == RubyRequestType:ATOMIC)) { 267 return Event:Store; 268 } else { 269 error("Invalid RubyRequestType"); 270 } 271 } 272 273 Event prefetch_request_type_to_event(RubyRequestType type) { 274 if (type == RubyRequestType:LD) { 275 return Event:PF_Load; 276 } else if (type == RubyRequestType:IFETCH) { 277 return Event:PF_Ifetch; 278 } else if ((type == RubyRequestType:ST) || 279 (type == RubyRequestType:ATOMIC)) { 280 return Event:PF_Store; 281 } else { 282 error("Invalid RubyRequestType"); 283 } 284 } 285 286 int getPendingAcks(TBE tbe) { 287 return tbe.pendingAcks; 288 } 289 290 out_port(requestL1Network_out, RequestMsg, requestFromL1Cache); 291 out_port(responseL1Network_out, ResponseMsg, responseFromL1Cache); 292 out_port(unblockNetwork_out, ResponseMsg, unblockFromL1Cache); 293 out_port(optionalQueue_out, RubyRequest, optionalQueue); 294 295 296 // Prefetch queue between the controller and the prefetcher 297 // As per Spracklen et al. (HPCA 2005), the prefetch queue should be 298 // implemented as a LIFO structure. The structure would allow for fast 299 // searches of all entries in the queue, not just the head msg. All 300 // msgs in the structure can be invalidated if a demand miss matches. 301 in_port(optionalQueue_in, RubyRequest, optionalQueue, desc="...", rank = 3) { 302 if (optionalQueue_in.isReady(clockEdge())) { 303 peek(optionalQueue_in, RubyRequest) { 304 // Instruction Prefetch 305 if (in_msg.Type == RubyRequestType:IFETCH) { 306 Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); 307 if (is_valid(L1Icache_entry)) { 308 // The block to be prefetched is already present in the 309 // cache. We should drop this request. 310 trigger(prefetch_request_type_to_event(in_msg.Type), 311 in_msg.LineAddress, 312 L1Icache_entry, TBEs[in_msg.LineAddress]); 313 } 314 315 // Check to see if it is in the OTHER L1 316 Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); 317 if (is_valid(L1Dcache_entry)) { 318 // The block is in the wrong L1 cache. We should drop 319 // this request. 320 trigger(prefetch_request_type_to_event(in_msg.Type), 321 in_msg.LineAddress, 322 L1Dcache_entry, TBEs[in_msg.LineAddress]); 323 } 324 325 if (L1Icache.cacheAvail(in_msg.LineAddress)) { 326 // L1 does't have the line, but we have space for it 327 // in the L1 so let's see if the L2 has it 328 trigger(prefetch_request_type_to_event(in_msg.Type), 329 in_msg.LineAddress, 330 L1Icache_entry, TBEs[in_msg.LineAddress]); 331 } else { 332 // No room in the L1, so we need to make room in the L1
|
371 } 372 } 373 } 374 } 375 } 376 377 // Response L1 Network - response msg to this L1 cache 378 in_port(responseL1Network_in, ResponseMsg, responseToL1Cache, rank = 2) { 379 if (responseL1Network_in.isReady(clockEdge())) { 380 peek(responseL1Network_in, ResponseMsg, block_on="addr") { 381 assert(in_msg.Destination.isElement(machineID)); 382 383 Entry cache_entry := getCacheEntry(in_msg.addr); 384 TBE tbe := TBEs[in_msg.addr]; 385 386 if(in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) { 387 trigger(Event:Data_Exclusive, in_msg.addr, cache_entry, tbe); 388 } else if(in_msg.Type == CoherenceResponseType:DATA) { 389 if ((getState(tbe, cache_entry, in_msg.addr) == State:IS || 390 getState(tbe, cache_entry, in_msg.addr) == State:IS_I || 391 getState(tbe, cache_entry, in_msg.addr) == State:PF_IS || 392 getState(tbe, cache_entry, in_msg.addr) == State:PF_IS_I) && 393 machineIDToMachineType(in_msg.Sender) == MachineType:L1Cache) { 394 395 trigger(Event:DataS_fromL1, in_msg.addr, cache_entry, tbe); 396 397 } else if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) { 398 trigger(Event:Data_all_Acks, in_msg.addr, cache_entry, tbe); 399 } else { 400 trigger(Event:Data, in_msg.addr, cache_entry, tbe); 401 } 402 } else if (in_msg.Type == CoherenceResponseType:ACK) { 403 if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) { 404 trigger(Event:Ack_all, in_msg.addr, cache_entry, tbe); 405 } else { 406 trigger(Event:Ack, in_msg.addr, cache_entry, tbe); 407 } 408 } else if (in_msg.Type == CoherenceResponseType:WB_ACK) { 409 trigger(Event:WB_Ack, in_msg.addr, cache_entry, tbe); 410 } else { 411 error("Invalid L1 response type"); 412 } 413 } 414 } 415 } 416 417 // Request InterChip network - request from this L1 cache to the shared L2 418 in_port(requestL1Network_in, RequestMsg, requestToL1Cache, rank = 1) { 419 if(requestL1Network_in.isReady(clockEdge())) { 420 peek(requestL1Network_in, RequestMsg, block_on="addr") { 421 assert(in_msg.Destination.isElement(machineID)); 422 423 Entry cache_entry := getCacheEntry(in_msg.addr); 424 TBE tbe := TBEs[in_msg.addr]; 425 426 if (in_msg.Type == CoherenceRequestType:INV) { 427 trigger(Event:Inv, in_msg.addr, cache_entry, tbe); 428 } else if (in_msg.Type == CoherenceRequestType:GETX || 429 in_msg.Type == CoherenceRequestType:UPGRADE) { 430 // upgrade transforms to GETX due to race 431 trigger(Event:Fwd_GETX, in_msg.addr, cache_entry, tbe); 432 } else if (in_msg.Type == CoherenceRequestType:GETS) { 433 trigger(Event:Fwd_GETS, in_msg.addr, cache_entry, tbe); 434 } else if (in_msg.Type == CoherenceRequestType:GET_INSTR) { 435 trigger(Event:Fwd_GET_INSTR, in_msg.addr, cache_entry, tbe); 436 } else { 437 error("Invalid forwarded request type"); 438 } 439 } 440 } 441 } 442 443 // Mandatory Queue betweens Node's CPU and it's L1 caches 444 in_port(mandatoryQueue_in, RubyRequest, mandatoryQueue, desc="...", rank = 0) { 445 if (mandatoryQueue_in.isReady(clockEdge())) { 446 peek(mandatoryQueue_in, RubyRequest, block_on="LineAddress") { 447 448 // Check for data access to blocks in I-cache and ifetchs to blocks in D-cache 449 450 if (in_msg.Type == RubyRequestType:IFETCH) { 451 // ** INSTRUCTION ACCESS *** 452 453 Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); 454 if (is_valid(L1Icache_entry)) { 455 // The tag matches for the L1, so the L1 asks the L2 for it. 456 trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, 457 L1Icache_entry, TBEs[in_msg.LineAddress]); 458 } else { 459 460 // Check to see if it is in the OTHER L1 461 Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); 462 if (is_valid(L1Dcache_entry)) { 463 // The block is in the wrong L1, put the request on the queue to the shared L2 464 trigger(Event:L1_Replacement, in_msg.LineAddress, 465 L1Dcache_entry, TBEs[in_msg.LineAddress]); 466 } 467 468 if (L1Icache.cacheAvail(in_msg.LineAddress)) { 469 // L1 does't have the line, but we have space for it 470 // in the L1 so let's see if the L2 has it. 471 trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, 472 L1Icache_entry, TBEs[in_msg.LineAddress]); 473 } else { 474 // No room in the L1, so we need to make room in the L1 475 476 // Check if the line we want to evict is not locked 477 Addr addr := L1Icache.cacheProbe(in_msg.LineAddress); 478 check_on_cache_probe(mandatoryQueue_in, addr); 479 480 trigger(Event:L1_Replacement, addr, 481 getL1ICacheEntry(addr), 482 TBEs[addr]); 483 } 484 } 485 } else { 486 487 // *** DATA ACCESS *** 488 Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); 489 if (is_valid(L1Dcache_entry)) { 490 // The tag matches for the L1, so the L1 ask the L2 for it 491 trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, 492 L1Dcache_entry, TBEs[in_msg.LineAddress]); 493 } else { 494 495 // Check to see if it is in the OTHER L1 496 Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); 497 if (is_valid(L1Icache_entry)) { 498 // The block is in the wrong L1, put the request on the queue to the shared L2 499 trigger(Event:L1_Replacement, in_msg.LineAddress, 500 L1Icache_entry, TBEs[in_msg.LineAddress]); 501 } 502 503 if (L1Dcache.cacheAvail(in_msg.LineAddress)) { 504 // L1 does't have the line, but we have space for it 505 // in the L1 let's see if the L2 has it. 506 trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, 507 L1Dcache_entry, TBEs[in_msg.LineAddress]); 508 } else { 509 // No room in the L1, so we need to make room in the L1 510 511 // Check if the line we want to evict is not locked 512 Addr addr := L1Dcache.cacheProbe(in_msg.LineAddress); 513 check_on_cache_probe(mandatoryQueue_in, addr); 514 515 trigger(Event:L1_Replacement, addr, 516 getL1DCacheEntry(addr), 517 TBEs[addr]); 518 } 519 } 520 } 521 } 522 } 523 } 524 525 void enqueuePrefetch(Addr address, RubyRequestType type) { 526 enqueue(optionalQueue_out, RubyRequest, 1) { 527 out_msg.LineAddress := address; 528 out_msg.Type := type; 529 out_msg.AccessMode := RubyAccessMode:Supervisor; 530 } 531 } 532 533 // ACTIONS 534 action(a_issueGETS, "a", desc="Issue GETS") { 535 peek(mandatoryQueue_in, RubyRequest) { 536 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 537 out_msg.addr := address; 538 out_msg.Type := CoherenceRequestType:GETS; 539 out_msg.Requestor := machineID; 540 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 541 l2_select_low_bit, l2_select_num_bits, intToID(0))); 542 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 543 address, out_msg.Destination); 544 out_msg.MessageSize := MessageSizeType:Control; 545 out_msg.Prefetch := in_msg.Prefetch; 546 out_msg.AccessMode := in_msg.AccessMode; 547 } 548 } 549 } 550 551 action(pa_issuePfGETS, "pa", desc="Issue prefetch GETS") { 552 peek(optionalQueue_in, RubyRequest) { 553 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 554 out_msg.addr := address; 555 out_msg.Type := CoherenceRequestType:GETS; 556 out_msg.Requestor := machineID; 557 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 558 l2_select_low_bit, l2_select_num_bits, intToID(0))); 559 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 560 address, out_msg.Destination); 561 out_msg.MessageSize := MessageSizeType:Control; 562 out_msg.Prefetch := in_msg.Prefetch; 563 out_msg.AccessMode := in_msg.AccessMode; 564 } 565 } 566 } 567 568 action(ai_issueGETINSTR, "ai", desc="Issue GETINSTR") { 569 peek(mandatoryQueue_in, RubyRequest) { 570 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 571 out_msg.addr := address; 572 out_msg.Type := CoherenceRequestType:GET_INSTR; 573 out_msg.Requestor := machineID; 574 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 575 l2_select_low_bit, l2_select_num_bits, intToID(0))); 576 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 577 address, out_msg.Destination); 578 out_msg.MessageSize := MessageSizeType:Control; 579 out_msg.Prefetch := in_msg.Prefetch; 580 out_msg.AccessMode := in_msg.AccessMode; 581 } 582 } 583 } 584 585 action(pai_issuePfGETINSTR, "pai", 586 desc="Issue GETINSTR for prefetch request") { 587 peek(optionalQueue_in, RubyRequest) { 588 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 589 out_msg.addr := address; 590 out_msg.Type := CoherenceRequestType:GET_INSTR; 591 out_msg.Requestor := machineID; 592 out_msg.Destination.add( 593 mapAddressToRange(address, MachineType:L2Cache, 594 l2_select_low_bit, l2_select_num_bits, intToID(0))); 595 out_msg.MessageSize := MessageSizeType:Control; 596 out_msg.Prefetch := in_msg.Prefetch; 597 out_msg.AccessMode := in_msg.AccessMode; 598 599 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 600 address, out_msg.Destination); 601 } 602 } 603 } 604 605 action(b_issueGETX, "b", desc="Issue GETX") { 606 peek(mandatoryQueue_in, RubyRequest) { 607 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 608 out_msg.addr := address; 609 out_msg.Type := CoherenceRequestType:GETX; 610 out_msg.Requestor := machineID; 611 DPRINTF(RubySlicc, "%s\n", machineID); 612 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 613 l2_select_low_bit, l2_select_num_bits, intToID(0))); 614 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 615 address, out_msg.Destination); 616 out_msg.MessageSize := MessageSizeType:Control; 617 out_msg.Prefetch := in_msg.Prefetch; 618 out_msg.AccessMode := in_msg.AccessMode; 619 } 620 } 621 } 622 623 action(pb_issuePfGETX, "pb", desc="Issue prefetch GETX") { 624 peek(optionalQueue_in, RubyRequest) { 625 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 626 out_msg.addr := address; 627 out_msg.Type := CoherenceRequestType:GETX; 628 out_msg.Requestor := machineID; 629 DPRINTF(RubySlicc, "%s\n", machineID); 630 631 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 632 l2_select_low_bit, l2_select_num_bits, intToID(0))); 633 634 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 635 address, out_msg.Destination); 636 out_msg.MessageSize := MessageSizeType:Control; 637 out_msg.Prefetch := in_msg.Prefetch; 638 out_msg.AccessMode := in_msg.AccessMode; 639 } 640 } 641 } 642 643 action(c_issueUPGRADE, "c", desc="Issue GETX") { 644 peek(mandatoryQueue_in, RubyRequest) { 645 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 646 out_msg.addr := address; 647 out_msg.Type := CoherenceRequestType:UPGRADE; 648 out_msg.Requestor := machineID; 649 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 650 l2_select_low_bit, l2_select_num_bits, intToID(0))); 651 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 652 address, out_msg.Destination); 653 out_msg.MessageSize := MessageSizeType:Control; 654 out_msg.Prefetch := in_msg.Prefetch; 655 out_msg.AccessMode := in_msg.AccessMode; 656 } 657 } 658 } 659 660 action(d_sendDataToRequestor, "d", desc="send data to requestor") { 661 peek(requestL1Network_in, RequestMsg) { 662 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 663 assert(is_valid(cache_entry)); 664 out_msg.addr := address; 665 out_msg.Type := CoherenceResponseType:DATA; 666 out_msg.DataBlk := cache_entry.DataBlk; 667 out_msg.Dirty := cache_entry.Dirty; 668 out_msg.Sender := machineID; 669 out_msg.Destination.add(in_msg.Requestor); 670 out_msg.MessageSize := MessageSizeType:Response_Data; 671 } 672 } 673 } 674 675 action(d2_sendDataToL2, "d2", desc="send data to the L2 cache because of M downgrade") { 676 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 677 assert(is_valid(cache_entry)); 678 out_msg.addr := address; 679 out_msg.Type := CoherenceResponseType:DATA; 680 out_msg.DataBlk := cache_entry.DataBlk; 681 out_msg.Dirty := cache_entry.Dirty; 682 out_msg.Sender := machineID; 683 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 684 l2_select_low_bit, l2_select_num_bits, intToID(0))); 685 out_msg.MessageSize := MessageSizeType:Response_Data; 686 } 687 } 688 689 action(dt_sendDataToRequestor_fromTBE, "dt", desc="send data to requestor") { 690 peek(requestL1Network_in, RequestMsg) { 691 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 692 assert(is_valid(tbe)); 693 out_msg.addr := address; 694 out_msg.Type := CoherenceResponseType:DATA; 695 out_msg.DataBlk := tbe.DataBlk; 696 out_msg.Dirty := tbe.Dirty; 697 out_msg.Sender := machineID; 698 out_msg.Destination.add(in_msg.Requestor); 699 out_msg.MessageSize := MessageSizeType:Response_Data; 700 } 701 } 702 } 703 704 action(d2t_sendDataToL2_fromTBE, "d2t", desc="send data to the L2 cache") { 705 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 706 assert(is_valid(tbe)); 707 out_msg.addr := address; 708 out_msg.Type := CoherenceResponseType:DATA; 709 out_msg.DataBlk := tbe.DataBlk; 710 out_msg.Dirty := tbe.Dirty; 711 out_msg.Sender := machineID; 712 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 713 l2_select_low_bit, l2_select_num_bits, intToID(0))); 714 out_msg.MessageSize := MessageSizeType:Response_Data; 715 } 716 } 717 718 action(e_sendAckToRequestor, "e", desc="send invalidate ack to requestor (could be L2 or L1)") { 719 peek(requestL1Network_in, RequestMsg) { 720 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 721 out_msg.addr := address; 722 out_msg.Type := CoherenceResponseType:ACK; 723 out_msg.Sender := machineID; 724 out_msg.Destination.add(in_msg.Requestor); 725 out_msg.MessageSize := MessageSizeType:Response_Control; 726 } 727 } 728 } 729 730 action(f_sendDataToL2, "f", desc="send data to the L2 cache") { 731 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 732 assert(is_valid(cache_entry)); 733 out_msg.addr := address; 734 out_msg.Type := CoherenceResponseType:DATA; 735 out_msg.DataBlk := cache_entry.DataBlk; 736 out_msg.Dirty := cache_entry.Dirty; 737 out_msg.Sender := machineID; 738 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 739 l2_select_low_bit, l2_select_num_bits, intToID(0))); 740 out_msg.MessageSize := MessageSizeType:Writeback_Data; 741 } 742 } 743 744 action(ft_sendDataToL2_fromTBE, "ft", desc="send data to the L2 cache") { 745 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 746 assert(is_valid(tbe)); 747 out_msg.addr := address; 748 out_msg.Type := CoherenceResponseType:DATA; 749 out_msg.DataBlk := tbe.DataBlk; 750 out_msg.Dirty := tbe.Dirty; 751 out_msg.Sender := machineID; 752 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 753 l2_select_low_bit, l2_select_num_bits, intToID(0))); 754 out_msg.MessageSize := MessageSizeType:Writeback_Data; 755 } 756 } 757 758 action(fi_sendInvAck, "fi", desc="send data to the L2 cache") { 759 peek(requestL1Network_in, RequestMsg) { 760 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 761 out_msg.addr := address; 762 out_msg.Type := CoherenceResponseType:ACK; 763 out_msg.Sender := machineID; 764 out_msg.Destination.add(in_msg.Requestor); 765 out_msg.MessageSize := MessageSizeType:Response_Control; 766 out_msg.AckCount := 1; 767 } 768 } 769 } 770 771 action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") { 772 if (send_evictions) { 773 DPRINTF(RubySlicc, "Sending invalidation for %#x to the CPU\n", address); 774 sequencer.evictionCallback(address); 775 } 776 } 777 778 action(g_issuePUTX, "g", desc="send data to the L2 cache") { 779 enqueue(requestL1Network_out, RequestMsg, l1_response_latency) { 780 assert(is_valid(cache_entry)); 781 out_msg.addr := address; 782 out_msg.Type := CoherenceRequestType:PUTX; 783 out_msg.DataBlk := cache_entry.DataBlk; 784 out_msg.Dirty := cache_entry.Dirty; 785 out_msg.Requestor:= machineID; 786 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 787 l2_select_low_bit, l2_select_num_bits, intToID(0))); 788 if (cache_entry.Dirty) { 789 out_msg.MessageSize := MessageSizeType:Writeback_Data; 790 } else { 791 out_msg.MessageSize := MessageSizeType:Writeback_Control; 792 } 793 } 794 } 795 796 action(j_sendUnblock, "j", desc="send unblock to the L2 cache") { 797 enqueue(unblockNetwork_out, ResponseMsg, to_l2_latency) { 798 out_msg.addr := address; 799 out_msg.Type := CoherenceResponseType:UNBLOCK; 800 out_msg.Sender := machineID; 801 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 802 l2_select_low_bit, l2_select_num_bits, intToID(0))); 803 out_msg.MessageSize := MessageSizeType:Response_Control; 804 DPRINTF(RubySlicc, "%#x\n", address); 805 } 806 } 807 808 action(jj_sendExclusiveUnblock, "\j", desc="send unblock to the L2 cache") { 809 enqueue(unblockNetwork_out, ResponseMsg, to_l2_latency) { 810 out_msg.addr := address; 811 out_msg.Type := CoherenceResponseType:EXCLUSIVE_UNBLOCK; 812 out_msg.Sender := machineID; 813 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 814 l2_select_low_bit, l2_select_num_bits, intToID(0))); 815 out_msg.MessageSize := MessageSizeType:Response_Control; 816 DPRINTF(RubySlicc, "%#x\n", address); 817 818 } 819 } 820 821 action(dg_invalidate_sc, "dg", 822 desc="Invalidate store conditional as the cache lost permissions") { 823 sequencer.invalidateSC(address); 824 } 825 826 action(h_load_hit, "hd", 827 desc="Notify sequencer the load completed.") 828 { 829 assert(is_valid(cache_entry)); 830 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 831 L1Dcache.setMRU(cache_entry); 832 sequencer.readCallback(address, cache_entry.DataBlk); 833 } 834 835 action(h_ifetch_hit, "hi", desc="Notify sequencer the instruction fetch completed.") 836 { 837 assert(is_valid(cache_entry)); 838 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 839 L1Icache.setMRU(cache_entry); 840 sequencer.readCallback(address, cache_entry.DataBlk); 841 } 842 843 action(hx_load_hit, "hx", desc="Notify sequencer the load completed.") 844 { 845 assert(is_valid(cache_entry)); 846 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 847 L1Icache.setMRU(address); 848 L1Dcache.setMRU(address); 849 sequencer.readCallback(address, cache_entry.DataBlk, true); 850 } 851 852 action(hh_store_hit, "\h", desc="Notify sequencer that store completed.") 853 { 854 assert(is_valid(cache_entry)); 855 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 856 L1Dcache.setMRU(cache_entry); 857 sequencer.writeCallback(address, cache_entry.DataBlk); 858 cache_entry.Dirty := true; 859 } 860 861 action(hhx_store_hit, "\hx", desc="Notify sequencer that store completed.") 862 { 863 assert(is_valid(cache_entry)); 864 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 865 L1Icache.setMRU(address); 866 L1Dcache.setMRU(address); 867 sequencer.writeCallback(address, cache_entry.DataBlk, true); 868 cache_entry.Dirty := true; 869 } 870 871 action(i_allocateTBE, "i", desc="Allocate TBE (isPrefetch=0, number of invalidates=0)") { 872 check_allocate(TBEs); 873 assert(is_valid(cache_entry)); 874 TBEs.allocate(address); 875 set_tbe(TBEs[address]); 876 tbe.isPrefetch := false; 877 tbe.Dirty := cache_entry.Dirty; 878 tbe.DataBlk := cache_entry.DataBlk; 879 } 880 881 action(k_popMandatoryQueue, "k", desc="Pop mandatory queue.") { 882 mandatoryQueue_in.dequeue(clockEdge()); 883 } 884 885 action(l_popRequestQueue, "l", 886 desc="Pop incoming request queue and profile the delay within this virtual network") { 887 Tick delay := requestL1Network_in.dequeue(clockEdge()); 888 profileMsgDelay(2, ticksToCycles(delay)); 889 } 890 891 action(o_popIncomingResponseQueue, "o", 892 desc="Pop Incoming Response queue and profile the delay within this virtual network") { 893 Tick delay := responseL1Network_in.dequeue(clockEdge()); 894 profileMsgDelay(1, ticksToCycles(delay)); 895 } 896 897 action(s_deallocateTBE, "s", desc="Deallocate TBE") { 898 TBEs.deallocate(address); 899 unset_tbe(); 900 } 901 902 action(u_writeDataToL1Cache, "u", desc="Write data to cache") { 903 peek(responseL1Network_in, ResponseMsg) { 904 assert(is_valid(cache_entry)); 905 cache_entry.DataBlk := in_msg.DataBlk; 906 cache_entry.Dirty := in_msg.Dirty; 907 } 908 } 909 910 action(q_updateAckCount, "q", desc="Update ack count") { 911 peek(responseL1Network_in, ResponseMsg) { 912 assert(is_valid(tbe)); 913 tbe.pendingAcks := tbe.pendingAcks - in_msg.AckCount; 914 APPEND_TRANSITION_COMMENT(in_msg.AckCount); 915 APPEND_TRANSITION_COMMENT(" p: "); 916 APPEND_TRANSITION_COMMENT(tbe.pendingAcks); 917 } 918 } 919 920 action(ff_deallocateL1CacheBlock, "\f", desc="Deallocate L1 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") { 921 if (L1Dcache.isTagPresent(address)) { 922 L1Dcache.deallocate(address); 923 } else { 924 L1Icache.deallocate(address); 925 } 926 unset_cache_entry(); 927 } 928 929 action(oo_allocateL1DCacheBlock, "\o", desc="Set L1 D-cache tag equal to tag of block B.") { 930 if (is_invalid(cache_entry)) { 931 set_cache_entry(L1Dcache.allocate(address, new Entry)); 932 } 933 } 934 935 action(pp_allocateL1ICacheBlock, "\p", desc="Set L1 I-cache tag equal to tag of block B.") { 936 if (is_invalid(cache_entry)) { 937 set_cache_entry(L1Icache.allocate(address, new Entry)); 938 } 939 } 940 941 action(z_stallAndWaitMandatoryQueue, "\z", desc="Stall and wait the L1 mandatory request queue") { 942 stall_and_wait(mandatoryQueue_in, address); 943 } 944 945 action(z_stallAndWaitOptionalQueue, "\pz", desc="Stall and wait the L1 prefetch request queue") { 946 stall_and_wait(optionalQueue_in, address); 947 } 948 949 action(kd_wakeUpDependents, "kd", desc="wake-up dependents") { 950 wakeUpBuffers(address); 951 } 952 953 action(uu_profileInstMiss, "\uim", desc="Profile the demand miss") { 954 ++L1Icache.demand_misses; 955 } 956 957 action(uu_profileInstHit, "\uih", desc="Profile the demand hit") { 958 ++L1Icache.demand_hits; 959 } 960 961 action(uu_profileDataMiss, "\udm", desc="Profile the demand miss") { 962 ++L1Dcache.demand_misses; 963 } 964 965 action(uu_profileDataHit, "\udh", desc="Profile the demand hit") { 966 ++L1Dcache.demand_hits; 967 } 968 969 action(po_observeHit, "\ph", desc="Inform the prefetcher about the hit") { 970 peek(mandatoryQueue_in, RubyRequest) { 971 if (cache_entry.isPrefetch) { 972 prefetcher.observePfHit(in_msg.LineAddress); 973 cache_entry.isPrefetch := false; 974 } 975 } 976 } 977 978 action(po_observeMiss, "\po", desc="Inform the prefetcher about the miss") { 979 peek(mandatoryQueue_in, RubyRequest) { 980 if (enable_prefetch) { 981 prefetcher.observeMiss(in_msg.LineAddress, in_msg.Type); 982 } 983 } 984 } 985 986 action(ppm_observePfMiss, "\ppm", 987 desc="Inform the prefetcher about the partial miss") { 988 peek(mandatoryQueue_in, RubyRequest) { 989 prefetcher.observePfMiss(in_msg.LineAddress); 990 } 991 } 992 993 action(pq_popPrefetchQueue, "\pq", desc="Pop the prefetch request queue") { 994 optionalQueue_in.dequeue(clockEdge()); 995 } 996 997 action(mp_markPrefetched, "mp", desc="Set the isPrefetch flag") { 998 assert(is_valid(cache_entry)); 999 cache_entry.isPrefetch := true; 1000 } 1001 1002 1003 //***************************************************** 1004 // TRANSITIONS 1005 //***************************************************** 1006 1007 // Transitions for Load/Store/Replacement/WriteBack from transient states 1008 transition({IS, IM, IS_I, M_I, SM, SINK_WB_ACK}, {Load, Ifetch, Store, L1_Replacement}) { 1009 z_stallAndWaitMandatoryQueue; 1010 } 1011 1012 transition({PF_IS, PF_IS_I}, {Store, L1_Replacement}) { 1013 z_stallAndWaitMandatoryQueue; 1014 } 1015 1016 transition({PF_IM, PF_SM}, {Load, Ifetch, L1_Replacement}) { 1017 z_stallAndWaitMandatoryQueue; 1018 } 1019 1020 transition({IS, IM, IS_I, M_I, SM, SINK_WB_ACK, PF_IS, PF_IS_I, PF_IM, PF_SM}, PF_L1_Replacement) { 1021 z_stallAndWaitOptionalQueue; 1022 } 1023 1024 // Transitions from Idle 1025 transition({NP,I}, {L1_Replacement, PF_L1_Replacement}) { 1026 ff_deallocateL1CacheBlock; 1027 } 1028 1029 transition({S,E,M,IS,IM,SM,IS_I,PF_IS_I,M_I,SINK_WB_ACK,PF_IS,PF_IM}, 1030 {PF_Load, PF_Store, PF_Ifetch}) { 1031 pq_popPrefetchQueue; 1032 } 1033 1034 transition({NP,I}, Load, IS) { 1035 oo_allocateL1DCacheBlock; 1036 i_allocateTBE; 1037 a_issueGETS; 1038 uu_profileDataMiss; 1039 po_observeMiss; 1040 k_popMandatoryQueue; 1041 } 1042 1043 transition({NP,I}, PF_Load, PF_IS) { 1044 oo_allocateL1DCacheBlock; 1045 i_allocateTBE; 1046 pa_issuePfGETS; 1047 pq_popPrefetchQueue; 1048 } 1049 1050 transition(PF_IS, Load, IS) { 1051 uu_profileDataMiss; 1052 ppm_observePfMiss; 1053 k_popMandatoryQueue; 1054 } 1055 1056 transition(PF_IS_I, Load, IS_I) { 1057 uu_profileDataMiss; 1058 ppm_observePfMiss; 1059 k_popMandatoryQueue; 1060 } 1061 1062 transition(PF_IS_I, Ifetch, IS_I) { 1063 uu_profileInstMiss; 1064 ppm_observePfMiss; 1065 k_popMandatoryQueue; 1066 } 1067 1068 transition({NP,I}, Ifetch, IS) { 1069 pp_allocateL1ICacheBlock; 1070 i_allocateTBE; 1071 ai_issueGETINSTR; 1072 uu_profileInstMiss; 1073 po_observeMiss; 1074 k_popMandatoryQueue; 1075 } 1076 1077 transition({NP,I}, PF_Ifetch, PF_IS) { 1078 pp_allocateL1ICacheBlock; 1079 i_allocateTBE; 1080 pai_issuePfGETINSTR; 1081 pq_popPrefetchQueue; 1082 } 1083 1084 // We proactively assume that the prefetch is in to 1085 // the instruction cache 1086 transition(PF_IS, Ifetch, IS) { 1087 uu_profileDataMiss; 1088 ppm_observePfMiss; 1089 k_popMandatoryQueue; 1090 } 1091 1092 transition({NP,I}, Store, IM) { 1093 oo_allocateL1DCacheBlock; 1094 i_allocateTBE; 1095 b_issueGETX; 1096 uu_profileDataMiss; 1097 po_observeMiss; 1098 k_popMandatoryQueue; 1099 } 1100 1101 transition({NP,I}, PF_Store, PF_IM) { 1102 oo_allocateL1DCacheBlock; 1103 i_allocateTBE; 1104 pb_issuePfGETX; 1105 pq_popPrefetchQueue; 1106 } 1107 1108 transition(PF_IM, Store, IM) { 1109 uu_profileDataMiss; 1110 ppm_observePfMiss; 1111 k_popMandatoryQueue; 1112 } 1113 1114 transition(PF_SM, Store, SM) { 1115 uu_profileDataMiss; 1116 ppm_observePfMiss; 1117 k_popMandatoryQueue; 1118 } 1119 1120 transition({NP, I}, Inv) { 1121 fi_sendInvAck; 1122 l_popRequestQueue; 1123 } 1124 1125 // Transitions from Shared 1126 transition({S,E,M}, Load) { 1127 h_load_hit; 1128 uu_profileDataHit; 1129 po_observeHit; 1130 k_popMandatoryQueue; 1131 } 1132 1133 transition({S,E,M}, Ifetch) { 1134 h_ifetch_hit; 1135 uu_profileInstHit; 1136 po_observeHit; 1137 k_popMandatoryQueue; 1138 } 1139 1140 transition(S, Store, SM) { 1141 i_allocateTBE; 1142 c_issueUPGRADE; 1143 uu_profileDataMiss; 1144 k_popMandatoryQueue; 1145 } 1146 1147 transition(S, {L1_Replacement, PF_L1_Replacement}, I) { 1148 forward_eviction_to_cpu; 1149 ff_deallocateL1CacheBlock; 1150 } 1151 1152 transition(S, Inv, I) { 1153 forward_eviction_to_cpu; 1154 fi_sendInvAck; 1155 l_popRequestQueue; 1156 } 1157 1158 // Transitions from Exclusive 1159 1160 transition({E,M}, Store, M) { 1161 hh_store_hit; 1162 uu_profileDataHit; 1163 po_observeHit; 1164 k_popMandatoryQueue; 1165 } 1166 1167 transition(E, {L1_Replacement, PF_L1_Replacement}, M_I) { 1168 // silent E replacement?? 1169 forward_eviction_to_cpu; 1170 i_allocateTBE; 1171 g_issuePUTX; // send data, but hold in case forwarded request 1172 ff_deallocateL1CacheBlock; 1173 } 1174 1175 transition(E, Inv, I) { 1176 // don't send data 1177 forward_eviction_to_cpu; 1178 fi_sendInvAck; 1179 l_popRequestQueue; 1180 } 1181 1182 transition(E, Fwd_GETX, I) { 1183 forward_eviction_to_cpu; 1184 d_sendDataToRequestor; 1185 l_popRequestQueue; 1186 } 1187 1188 transition(E, {Fwd_GETS, Fwd_GET_INSTR}, S) { 1189 d_sendDataToRequestor; 1190 d2_sendDataToL2; 1191 l_popRequestQueue; 1192 } 1193 1194 // Transitions from Modified 1195 1196 transition(M, {L1_Replacement, PF_L1_Replacement}, M_I) { 1197 forward_eviction_to_cpu; 1198 i_allocateTBE; 1199 g_issuePUTX; // send data, but hold in case forwarded request 1200 ff_deallocateL1CacheBlock; 1201 } 1202 1203 transition(M_I, WB_Ack, I) { 1204 s_deallocateTBE; 1205 o_popIncomingResponseQueue; 1206 kd_wakeUpDependents; 1207 } 1208 1209 transition(M, Inv, I) { 1210 forward_eviction_to_cpu; 1211 f_sendDataToL2; 1212 l_popRequestQueue; 1213 } 1214 1215 transition(M_I, Inv, SINK_WB_ACK) { 1216 ft_sendDataToL2_fromTBE; 1217 l_popRequestQueue; 1218 } 1219 1220 transition(M, Fwd_GETX, I) { 1221 forward_eviction_to_cpu; 1222 d_sendDataToRequestor; 1223 l_popRequestQueue; 1224 } 1225 1226 transition(M, {Fwd_GETS, Fwd_GET_INSTR}, S) { 1227 d_sendDataToRequestor; 1228 d2_sendDataToL2; 1229 l_popRequestQueue; 1230 } 1231 1232 transition(M_I, Fwd_GETX, SINK_WB_ACK) { 1233 dt_sendDataToRequestor_fromTBE; 1234 l_popRequestQueue; 1235 } 1236 1237 transition(M_I, {Fwd_GETS, Fwd_GET_INSTR}, SINK_WB_ACK) { 1238 dt_sendDataToRequestor_fromTBE; 1239 d2t_sendDataToL2_fromTBE; 1240 l_popRequestQueue; 1241 } 1242 1243 // Transitions from IS 1244 transition({IS, IS_I}, Inv, IS_I) { 1245 fi_sendInvAck; 1246 l_popRequestQueue; 1247 } 1248 1249 transition({PF_IS, PF_IS_I}, Inv, PF_IS_I) { 1250 fi_sendInvAck; 1251 l_popRequestQueue; 1252 } 1253 1254 transition(IS, Data_all_Acks, S) { 1255 u_writeDataToL1Cache; 1256 hx_load_hit; 1257 s_deallocateTBE; 1258 o_popIncomingResponseQueue; 1259 kd_wakeUpDependents; 1260 } 1261 1262 transition(PF_IS, Data_all_Acks, S) { 1263 u_writeDataToL1Cache; 1264 s_deallocateTBE; 1265 mp_markPrefetched; 1266 o_popIncomingResponseQueue; 1267 kd_wakeUpDependents; 1268 } 1269 1270 transition(IS_I, Data_all_Acks, I) { 1271 u_writeDataToL1Cache; 1272 hx_load_hit; 1273 s_deallocateTBE; 1274 o_popIncomingResponseQueue; 1275 kd_wakeUpDependents; 1276 } 1277 1278 transition(PF_IS_I, Data_all_Acks, I) { 1279 s_deallocateTBE; 1280 o_popIncomingResponseQueue; 1281 kd_wakeUpDependents; 1282 } 1283 1284 transition(IS, DataS_fromL1, S) { 1285 u_writeDataToL1Cache; 1286 j_sendUnblock; 1287 hx_load_hit; 1288 s_deallocateTBE; 1289 o_popIncomingResponseQueue; 1290 kd_wakeUpDependents; 1291 } 1292 1293 transition(PF_IS, DataS_fromL1, S) { 1294 u_writeDataToL1Cache; 1295 j_sendUnblock; 1296 s_deallocateTBE; 1297 o_popIncomingResponseQueue; 1298 kd_wakeUpDependents; 1299 } 1300 1301 transition(IS_I, DataS_fromL1, I) { 1302 u_writeDataToL1Cache; 1303 j_sendUnblock; 1304 hx_load_hit; 1305 s_deallocateTBE; 1306 o_popIncomingResponseQueue; 1307 kd_wakeUpDependents; 1308 } 1309 1310 transition(PF_IS_I, DataS_fromL1, I) { 1311 j_sendUnblock; 1312 s_deallocateTBE; 1313 o_popIncomingResponseQueue; 1314 kd_wakeUpDependents; 1315 } 1316 1317 // directory is blocked when sending exclusive data 1318 transition(IS_I, Data_Exclusive, E) { 1319 u_writeDataToL1Cache; 1320 hx_load_hit; 1321 jj_sendExclusiveUnblock; 1322 s_deallocateTBE; 1323 o_popIncomingResponseQueue; 1324 kd_wakeUpDependents; 1325 } 1326 1327 // directory is blocked when sending exclusive data 1328 transition(PF_IS_I, Data_Exclusive, E) { 1329 u_writeDataToL1Cache; 1330 jj_sendExclusiveUnblock; 1331 s_deallocateTBE; 1332 o_popIncomingResponseQueue; 1333 kd_wakeUpDependents; 1334 } 1335 1336 transition(IS, Data_Exclusive, E) { 1337 u_writeDataToL1Cache; 1338 hx_load_hit; 1339 jj_sendExclusiveUnblock; 1340 s_deallocateTBE; 1341 o_popIncomingResponseQueue; 1342 kd_wakeUpDependents; 1343 } 1344 1345 transition(PF_IS, Data_Exclusive, E) { 1346 u_writeDataToL1Cache; 1347 jj_sendExclusiveUnblock; 1348 s_deallocateTBE; 1349 mp_markPrefetched; 1350 o_popIncomingResponseQueue; 1351 kd_wakeUpDependents; 1352 } 1353 1354 // Transitions from IM 1355 transition(IM, Inv, IM) { 1356 fi_sendInvAck; 1357 l_popRequestQueue; 1358 } 1359 1360 transition({PF_IM, PF_SM}, Inv, PF_IM) { 1361 fi_sendInvAck; 1362 l_popRequestQueue; 1363 } 1364 1365 transition(IM, Data, SM) { 1366 u_writeDataToL1Cache; 1367 q_updateAckCount; 1368 o_popIncomingResponseQueue; 1369 } 1370 1371 transition(PF_IM, Data, PF_SM) { 1372 u_writeDataToL1Cache; 1373 q_updateAckCount; 1374 o_popIncomingResponseQueue; 1375 } 1376 1377 transition(IM, Data_all_Acks, M) { 1378 u_writeDataToL1Cache; 1379 hhx_store_hit; 1380 jj_sendExclusiveUnblock; 1381 s_deallocateTBE; 1382 o_popIncomingResponseQueue; 1383 kd_wakeUpDependents; 1384 } 1385 1386 transition(PF_IM, Data_all_Acks, M) { 1387 u_writeDataToL1Cache; 1388 jj_sendExclusiveUnblock; 1389 s_deallocateTBE; 1390 mp_markPrefetched; 1391 o_popIncomingResponseQueue; 1392 kd_wakeUpDependents; 1393 } 1394 1395 // transitions from SM 1396 transition(SM, Inv, IM) { 1397 forward_eviction_to_cpu; 1398 fi_sendInvAck; 1399 dg_invalidate_sc; 1400 l_popRequestQueue; 1401 } 1402 1403 transition({SM, IM, PF_SM, PF_IM}, Ack) { 1404 q_updateAckCount; 1405 o_popIncomingResponseQueue; 1406 } 1407 1408 transition(SM, Ack_all, M) { 1409 jj_sendExclusiveUnblock; 1410 hhx_store_hit; 1411 s_deallocateTBE; 1412 o_popIncomingResponseQueue; 1413 kd_wakeUpDependents; 1414 } 1415 1416 transition(PF_SM, Ack_all, M) { 1417 jj_sendExclusiveUnblock; 1418 s_deallocateTBE; 1419 mp_markPrefetched; 1420 o_popIncomingResponseQueue; 1421 kd_wakeUpDependents; 1422 } 1423 1424 transition(SINK_WB_ACK, Inv){ 1425 fi_sendInvAck; 1426 l_popRequestQueue; 1427 } 1428 1429 transition(SINK_WB_ACK, WB_Ack, I){ 1430 s_deallocateTBE; 1431 o_popIncomingResponseQueue; 1432 kd_wakeUpDependents; 1433 } 1434}
| 369 } 370 } 371 } 372 } 373 } 374 375 // Response L1 Network - response msg to this L1 cache 376 in_port(responseL1Network_in, ResponseMsg, responseToL1Cache, rank = 2) { 377 if (responseL1Network_in.isReady(clockEdge())) { 378 peek(responseL1Network_in, ResponseMsg, block_on="addr") { 379 assert(in_msg.Destination.isElement(machineID)); 380 381 Entry cache_entry := getCacheEntry(in_msg.addr); 382 TBE tbe := TBEs[in_msg.addr]; 383 384 if(in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) { 385 trigger(Event:Data_Exclusive, in_msg.addr, cache_entry, tbe); 386 } else if(in_msg.Type == CoherenceResponseType:DATA) { 387 if ((getState(tbe, cache_entry, in_msg.addr) == State:IS || 388 getState(tbe, cache_entry, in_msg.addr) == State:IS_I || 389 getState(tbe, cache_entry, in_msg.addr) == State:PF_IS || 390 getState(tbe, cache_entry, in_msg.addr) == State:PF_IS_I) && 391 machineIDToMachineType(in_msg.Sender) == MachineType:L1Cache) { 392 393 trigger(Event:DataS_fromL1, in_msg.addr, cache_entry, tbe); 394 395 } else if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) { 396 trigger(Event:Data_all_Acks, in_msg.addr, cache_entry, tbe); 397 } else { 398 trigger(Event:Data, in_msg.addr, cache_entry, tbe); 399 } 400 } else if (in_msg.Type == CoherenceResponseType:ACK) { 401 if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) { 402 trigger(Event:Ack_all, in_msg.addr, cache_entry, tbe); 403 } else { 404 trigger(Event:Ack, in_msg.addr, cache_entry, tbe); 405 } 406 } else if (in_msg.Type == CoherenceResponseType:WB_ACK) { 407 trigger(Event:WB_Ack, in_msg.addr, cache_entry, tbe); 408 } else { 409 error("Invalid L1 response type"); 410 } 411 } 412 } 413 } 414 415 // Request InterChip network - request from this L1 cache to the shared L2 416 in_port(requestL1Network_in, RequestMsg, requestToL1Cache, rank = 1) { 417 if(requestL1Network_in.isReady(clockEdge())) { 418 peek(requestL1Network_in, RequestMsg, block_on="addr") { 419 assert(in_msg.Destination.isElement(machineID)); 420 421 Entry cache_entry := getCacheEntry(in_msg.addr); 422 TBE tbe := TBEs[in_msg.addr]; 423 424 if (in_msg.Type == CoherenceRequestType:INV) { 425 trigger(Event:Inv, in_msg.addr, cache_entry, tbe); 426 } else if (in_msg.Type == CoherenceRequestType:GETX || 427 in_msg.Type == CoherenceRequestType:UPGRADE) { 428 // upgrade transforms to GETX due to race 429 trigger(Event:Fwd_GETX, in_msg.addr, cache_entry, tbe); 430 } else if (in_msg.Type == CoherenceRequestType:GETS) { 431 trigger(Event:Fwd_GETS, in_msg.addr, cache_entry, tbe); 432 } else if (in_msg.Type == CoherenceRequestType:GET_INSTR) { 433 trigger(Event:Fwd_GET_INSTR, in_msg.addr, cache_entry, tbe); 434 } else { 435 error("Invalid forwarded request type"); 436 } 437 } 438 } 439 } 440 441 // Mandatory Queue betweens Node's CPU and it's L1 caches 442 in_port(mandatoryQueue_in, RubyRequest, mandatoryQueue, desc="...", rank = 0) { 443 if (mandatoryQueue_in.isReady(clockEdge())) { 444 peek(mandatoryQueue_in, RubyRequest, block_on="LineAddress") { 445 446 // Check for data access to blocks in I-cache and ifetchs to blocks in D-cache 447 448 if (in_msg.Type == RubyRequestType:IFETCH) { 449 // ** INSTRUCTION ACCESS *** 450 451 Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); 452 if (is_valid(L1Icache_entry)) { 453 // The tag matches for the L1, so the L1 asks the L2 for it. 454 trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, 455 L1Icache_entry, TBEs[in_msg.LineAddress]); 456 } else { 457 458 // Check to see if it is in the OTHER L1 459 Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); 460 if (is_valid(L1Dcache_entry)) { 461 // The block is in the wrong L1, put the request on the queue to the shared L2 462 trigger(Event:L1_Replacement, in_msg.LineAddress, 463 L1Dcache_entry, TBEs[in_msg.LineAddress]); 464 } 465 466 if (L1Icache.cacheAvail(in_msg.LineAddress)) { 467 // L1 does't have the line, but we have space for it 468 // in the L1 so let's see if the L2 has it. 469 trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, 470 L1Icache_entry, TBEs[in_msg.LineAddress]); 471 } else { 472 // No room in the L1, so we need to make room in the L1 473 474 // Check if the line we want to evict is not locked 475 Addr addr := L1Icache.cacheProbe(in_msg.LineAddress); 476 check_on_cache_probe(mandatoryQueue_in, addr); 477 478 trigger(Event:L1_Replacement, addr, 479 getL1ICacheEntry(addr), 480 TBEs[addr]); 481 } 482 } 483 } else { 484 485 // *** DATA ACCESS *** 486 Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); 487 if (is_valid(L1Dcache_entry)) { 488 // The tag matches for the L1, so the L1 ask the L2 for it 489 trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, 490 L1Dcache_entry, TBEs[in_msg.LineAddress]); 491 } else { 492 493 // Check to see if it is in the OTHER L1 494 Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); 495 if (is_valid(L1Icache_entry)) { 496 // The block is in the wrong L1, put the request on the queue to the shared L2 497 trigger(Event:L1_Replacement, in_msg.LineAddress, 498 L1Icache_entry, TBEs[in_msg.LineAddress]); 499 } 500 501 if (L1Dcache.cacheAvail(in_msg.LineAddress)) { 502 // L1 does't have the line, but we have space for it 503 // in the L1 let's see if the L2 has it. 504 trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress, 505 L1Dcache_entry, TBEs[in_msg.LineAddress]); 506 } else { 507 // No room in the L1, so we need to make room in the L1 508 509 // Check if the line we want to evict is not locked 510 Addr addr := L1Dcache.cacheProbe(in_msg.LineAddress); 511 check_on_cache_probe(mandatoryQueue_in, addr); 512 513 trigger(Event:L1_Replacement, addr, 514 getL1DCacheEntry(addr), 515 TBEs[addr]); 516 } 517 } 518 } 519 } 520 } 521 } 522 523 void enqueuePrefetch(Addr address, RubyRequestType type) { 524 enqueue(optionalQueue_out, RubyRequest, 1) { 525 out_msg.LineAddress := address; 526 out_msg.Type := type; 527 out_msg.AccessMode := RubyAccessMode:Supervisor; 528 } 529 } 530 531 // ACTIONS 532 action(a_issueGETS, "a", desc="Issue GETS") { 533 peek(mandatoryQueue_in, RubyRequest) { 534 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 535 out_msg.addr := address; 536 out_msg.Type := CoherenceRequestType:GETS; 537 out_msg.Requestor := machineID; 538 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 539 l2_select_low_bit, l2_select_num_bits, intToID(0))); 540 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 541 address, out_msg.Destination); 542 out_msg.MessageSize := MessageSizeType:Control; 543 out_msg.Prefetch := in_msg.Prefetch; 544 out_msg.AccessMode := in_msg.AccessMode; 545 } 546 } 547 } 548 549 action(pa_issuePfGETS, "pa", desc="Issue prefetch GETS") { 550 peek(optionalQueue_in, RubyRequest) { 551 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 552 out_msg.addr := address; 553 out_msg.Type := CoherenceRequestType:GETS; 554 out_msg.Requestor := machineID; 555 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 556 l2_select_low_bit, l2_select_num_bits, intToID(0))); 557 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 558 address, out_msg.Destination); 559 out_msg.MessageSize := MessageSizeType:Control; 560 out_msg.Prefetch := in_msg.Prefetch; 561 out_msg.AccessMode := in_msg.AccessMode; 562 } 563 } 564 } 565 566 action(ai_issueGETINSTR, "ai", desc="Issue GETINSTR") { 567 peek(mandatoryQueue_in, RubyRequest) { 568 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 569 out_msg.addr := address; 570 out_msg.Type := CoherenceRequestType:GET_INSTR; 571 out_msg.Requestor := machineID; 572 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 573 l2_select_low_bit, l2_select_num_bits, intToID(0))); 574 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 575 address, out_msg.Destination); 576 out_msg.MessageSize := MessageSizeType:Control; 577 out_msg.Prefetch := in_msg.Prefetch; 578 out_msg.AccessMode := in_msg.AccessMode; 579 } 580 } 581 } 582 583 action(pai_issuePfGETINSTR, "pai", 584 desc="Issue GETINSTR for prefetch request") { 585 peek(optionalQueue_in, RubyRequest) { 586 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 587 out_msg.addr := address; 588 out_msg.Type := CoherenceRequestType:GET_INSTR; 589 out_msg.Requestor := machineID; 590 out_msg.Destination.add( 591 mapAddressToRange(address, MachineType:L2Cache, 592 l2_select_low_bit, l2_select_num_bits, intToID(0))); 593 out_msg.MessageSize := MessageSizeType:Control; 594 out_msg.Prefetch := in_msg.Prefetch; 595 out_msg.AccessMode := in_msg.AccessMode; 596 597 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 598 address, out_msg.Destination); 599 } 600 } 601 } 602 603 action(b_issueGETX, "b", desc="Issue GETX") { 604 peek(mandatoryQueue_in, RubyRequest) { 605 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 606 out_msg.addr := address; 607 out_msg.Type := CoherenceRequestType:GETX; 608 out_msg.Requestor := machineID; 609 DPRINTF(RubySlicc, "%s\n", machineID); 610 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 611 l2_select_low_bit, l2_select_num_bits, intToID(0))); 612 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 613 address, out_msg.Destination); 614 out_msg.MessageSize := MessageSizeType:Control; 615 out_msg.Prefetch := in_msg.Prefetch; 616 out_msg.AccessMode := in_msg.AccessMode; 617 } 618 } 619 } 620 621 action(pb_issuePfGETX, "pb", desc="Issue prefetch GETX") { 622 peek(optionalQueue_in, RubyRequest) { 623 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 624 out_msg.addr := address; 625 out_msg.Type := CoherenceRequestType:GETX; 626 out_msg.Requestor := machineID; 627 DPRINTF(RubySlicc, "%s\n", machineID); 628 629 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 630 l2_select_low_bit, l2_select_num_bits, intToID(0))); 631 632 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 633 address, out_msg.Destination); 634 out_msg.MessageSize := MessageSizeType:Control; 635 out_msg.Prefetch := in_msg.Prefetch; 636 out_msg.AccessMode := in_msg.AccessMode; 637 } 638 } 639 } 640 641 action(c_issueUPGRADE, "c", desc="Issue GETX") { 642 peek(mandatoryQueue_in, RubyRequest) { 643 enqueue(requestL1Network_out, RequestMsg, l1_request_latency) { 644 out_msg.addr := address; 645 out_msg.Type := CoherenceRequestType:UPGRADE; 646 out_msg.Requestor := machineID; 647 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 648 l2_select_low_bit, l2_select_num_bits, intToID(0))); 649 DPRINTF(RubySlicc, "address: %#x, destination: %s\n", 650 address, out_msg.Destination); 651 out_msg.MessageSize := MessageSizeType:Control; 652 out_msg.Prefetch := in_msg.Prefetch; 653 out_msg.AccessMode := in_msg.AccessMode; 654 } 655 } 656 } 657 658 action(d_sendDataToRequestor, "d", desc="send data to requestor") { 659 peek(requestL1Network_in, RequestMsg) { 660 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 661 assert(is_valid(cache_entry)); 662 out_msg.addr := address; 663 out_msg.Type := CoherenceResponseType:DATA; 664 out_msg.DataBlk := cache_entry.DataBlk; 665 out_msg.Dirty := cache_entry.Dirty; 666 out_msg.Sender := machineID; 667 out_msg.Destination.add(in_msg.Requestor); 668 out_msg.MessageSize := MessageSizeType:Response_Data; 669 } 670 } 671 } 672 673 action(d2_sendDataToL2, "d2", desc="send data to the L2 cache because of M downgrade") { 674 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 675 assert(is_valid(cache_entry)); 676 out_msg.addr := address; 677 out_msg.Type := CoherenceResponseType:DATA; 678 out_msg.DataBlk := cache_entry.DataBlk; 679 out_msg.Dirty := cache_entry.Dirty; 680 out_msg.Sender := machineID; 681 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 682 l2_select_low_bit, l2_select_num_bits, intToID(0))); 683 out_msg.MessageSize := MessageSizeType:Response_Data; 684 } 685 } 686 687 action(dt_sendDataToRequestor_fromTBE, "dt", desc="send data to requestor") { 688 peek(requestL1Network_in, RequestMsg) { 689 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 690 assert(is_valid(tbe)); 691 out_msg.addr := address; 692 out_msg.Type := CoherenceResponseType:DATA; 693 out_msg.DataBlk := tbe.DataBlk; 694 out_msg.Dirty := tbe.Dirty; 695 out_msg.Sender := machineID; 696 out_msg.Destination.add(in_msg.Requestor); 697 out_msg.MessageSize := MessageSizeType:Response_Data; 698 } 699 } 700 } 701 702 action(d2t_sendDataToL2_fromTBE, "d2t", desc="send data to the L2 cache") { 703 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 704 assert(is_valid(tbe)); 705 out_msg.addr := address; 706 out_msg.Type := CoherenceResponseType:DATA; 707 out_msg.DataBlk := tbe.DataBlk; 708 out_msg.Dirty := tbe.Dirty; 709 out_msg.Sender := machineID; 710 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 711 l2_select_low_bit, l2_select_num_bits, intToID(0))); 712 out_msg.MessageSize := MessageSizeType:Response_Data; 713 } 714 } 715 716 action(e_sendAckToRequestor, "e", desc="send invalidate ack to requestor (could be L2 or L1)") { 717 peek(requestL1Network_in, RequestMsg) { 718 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 719 out_msg.addr := address; 720 out_msg.Type := CoherenceResponseType:ACK; 721 out_msg.Sender := machineID; 722 out_msg.Destination.add(in_msg.Requestor); 723 out_msg.MessageSize := MessageSizeType:Response_Control; 724 } 725 } 726 } 727 728 action(f_sendDataToL2, "f", desc="send data to the L2 cache") { 729 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 730 assert(is_valid(cache_entry)); 731 out_msg.addr := address; 732 out_msg.Type := CoherenceResponseType:DATA; 733 out_msg.DataBlk := cache_entry.DataBlk; 734 out_msg.Dirty := cache_entry.Dirty; 735 out_msg.Sender := machineID; 736 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 737 l2_select_low_bit, l2_select_num_bits, intToID(0))); 738 out_msg.MessageSize := MessageSizeType:Writeback_Data; 739 } 740 } 741 742 action(ft_sendDataToL2_fromTBE, "ft", desc="send data to the L2 cache") { 743 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 744 assert(is_valid(tbe)); 745 out_msg.addr := address; 746 out_msg.Type := CoherenceResponseType:DATA; 747 out_msg.DataBlk := tbe.DataBlk; 748 out_msg.Dirty := tbe.Dirty; 749 out_msg.Sender := machineID; 750 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 751 l2_select_low_bit, l2_select_num_bits, intToID(0))); 752 out_msg.MessageSize := MessageSizeType:Writeback_Data; 753 } 754 } 755 756 action(fi_sendInvAck, "fi", desc="send data to the L2 cache") { 757 peek(requestL1Network_in, RequestMsg) { 758 enqueue(responseL1Network_out, ResponseMsg, l1_response_latency) { 759 out_msg.addr := address; 760 out_msg.Type := CoherenceResponseType:ACK; 761 out_msg.Sender := machineID; 762 out_msg.Destination.add(in_msg.Requestor); 763 out_msg.MessageSize := MessageSizeType:Response_Control; 764 out_msg.AckCount := 1; 765 } 766 } 767 } 768 769 action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") { 770 if (send_evictions) { 771 DPRINTF(RubySlicc, "Sending invalidation for %#x to the CPU\n", address); 772 sequencer.evictionCallback(address); 773 } 774 } 775 776 action(g_issuePUTX, "g", desc="send data to the L2 cache") { 777 enqueue(requestL1Network_out, RequestMsg, l1_response_latency) { 778 assert(is_valid(cache_entry)); 779 out_msg.addr := address; 780 out_msg.Type := CoherenceRequestType:PUTX; 781 out_msg.DataBlk := cache_entry.DataBlk; 782 out_msg.Dirty := cache_entry.Dirty; 783 out_msg.Requestor:= machineID; 784 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 785 l2_select_low_bit, l2_select_num_bits, intToID(0))); 786 if (cache_entry.Dirty) { 787 out_msg.MessageSize := MessageSizeType:Writeback_Data; 788 } else { 789 out_msg.MessageSize := MessageSizeType:Writeback_Control; 790 } 791 } 792 } 793 794 action(j_sendUnblock, "j", desc="send unblock to the L2 cache") { 795 enqueue(unblockNetwork_out, ResponseMsg, to_l2_latency) { 796 out_msg.addr := address; 797 out_msg.Type := CoherenceResponseType:UNBLOCK; 798 out_msg.Sender := machineID; 799 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 800 l2_select_low_bit, l2_select_num_bits, intToID(0))); 801 out_msg.MessageSize := MessageSizeType:Response_Control; 802 DPRINTF(RubySlicc, "%#x\n", address); 803 } 804 } 805 806 action(jj_sendExclusiveUnblock, "\j", desc="send unblock to the L2 cache") { 807 enqueue(unblockNetwork_out, ResponseMsg, to_l2_latency) { 808 out_msg.addr := address; 809 out_msg.Type := CoherenceResponseType:EXCLUSIVE_UNBLOCK; 810 out_msg.Sender := machineID; 811 out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache, 812 l2_select_low_bit, l2_select_num_bits, intToID(0))); 813 out_msg.MessageSize := MessageSizeType:Response_Control; 814 DPRINTF(RubySlicc, "%#x\n", address); 815 816 } 817 } 818 819 action(dg_invalidate_sc, "dg", 820 desc="Invalidate store conditional as the cache lost permissions") { 821 sequencer.invalidateSC(address); 822 } 823 824 action(h_load_hit, "hd", 825 desc="Notify sequencer the load completed.") 826 { 827 assert(is_valid(cache_entry)); 828 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 829 L1Dcache.setMRU(cache_entry); 830 sequencer.readCallback(address, cache_entry.DataBlk); 831 } 832 833 action(h_ifetch_hit, "hi", desc="Notify sequencer the instruction fetch completed.") 834 { 835 assert(is_valid(cache_entry)); 836 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 837 L1Icache.setMRU(cache_entry); 838 sequencer.readCallback(address, cache_entry.DataBlk); 839 } 840 841 action(hx_load_hit, "hx", desc="Notify sequencer the load completed.") 842 { 843 assert(is_valid(cache_entry)); 844 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 845 L1Icache.setMRU(address); 846 L1Dcache.setMRU(address); 847 sequencer.readCallback(address, cache_entry.DataBlk, true); 848 } 849 850 action(hh_store_hit, "\h", desc="Notify sequencer that store completed.") 851 { 852 assert(is_valid(cache_entry)); 853 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 854 L1Dcache.setMRU(cache_entry); 855 sequencer.writeCallback(address, cache_entry.DataBlk); 856 cache_entry.Dirty := true; 857 } 858 859 action(hhx_store_hit, "\hx", desc="Notify sequencer that store completed.") 860 { 861 assert(is_valid(cache_entry)); 862 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 863 L1Icache.setMRU(address); 864 L1Dcache.setMRU(address); 865 sequencer.writeCallback(address, cache_entry.DataBlk, true); 866 cache_entry.Dirty := true; 867 } 868 869 action(i_allocateTBE, "i", desc="Allocate TBE (isPrefetch=0, number of invalidates=0)") { 870 check_allocate(TBEs); 871 assert(is_valid(cache_entry)); 872 TBEs.allocate(address); 873 set_tbe(TBEs[address]); 874 tbe.isPrefetch := false; 875 tbe.Dirty := cache_entry.Dirty; 876 tbe.DataBlk := cache_entry.DataBlk; 877 } 878 879 action(k_popMandatoryQueue, "k", desc="Pop mandatory queue.") { 880 mandatoryQueue_in.dequeue(clockEdge()); 881 } 882 883 action(l_popRequestQueue, "l", 884 desc="Pop incoming request queue and profile the delay within this virtual network") { 885 Tick delay := requestL1Network_in.dequeue(clockEdge()); 886 profileMsgDelay(2, ticksToCycles(delay)); 887 } 888 889 action(o_popIncomingResponseQueue, "o", 890 desc="Pop Incoming Response queue and profile the delay within this virtual network") { 891 Tick delay := responseL1Network_in.dequeue(clockEdge()); 892 profileMsgDelay(1, ticksToCycles(delay)); 893 } 894 895 action(s_deallocateTBE, "s", desc="Deallocate TBE") { 896 TBEs.deallocate(address); 897 unset_tbe(); 898 } 899 900 action(u_writeDataToL1Cache, "u", desc="Write data to cache") { 901 peek(responseL1Network_in, ResponseMsg) { 902 assert(is_valid(cache_entry)); 903 cache_entry.DataBlk := in_msg.DataBlk; 904 cache_entry.Dirty := in_msg.Dirty; 905 } 906 } 907 908 action(q_updateAckCount, "q", desc="Update ack count") { 909 peek(responseL1Network_in, ResponseMsg) { 910 assert(is_valid(tbe)); 911 tbe.pendingAcks := tbe.pendingAcks - in_msg.AckCount; 912 APPEND_TRANSITION_COMMENT(in_msg.AckCount); 913 APPEND_TRANSITION_COMMENT(" p: "); 914 APPEND_TRANSITION_COMMENT(tbe.pendingAcks); 915 } 916 } 917 918 action(ff_deallocateL1CacheBlock, "\f", desc="Deallocate L1 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") { 919 if (L1Dcache.isTagPresent(address)) { 920 L1Dcache.deallocate(address); 921 } else { 922 L1Icache.deallocate(address); 923 } 924 unset_cache_entry(); 925 } 926 927 action(oo_allocateL1DCacheBlock, "\o", desc="Set L1 D-cache tag equal to tag of block B.") { 928 if (is_invalid(cache_entry)) { 929 set_cache_entry(L1Dcache.allocate(address, new Entry)); 930 } 931 } 932 933 action(pp_allocateL1ICacheBlock, "\p", desc="Set L1 I-cache tag equal to tag of block B.") { 934 if (is_invalid(cache_entry)) { 935 set_cache_entry(L1Icache.allocate(address, new Entry)); 936 } 937 } 938 939 action(z_stallAndWaitMandatoryQueue, "\z", desc="Stall and wait the L1 mandatory request queue") { 940 stall_and_wait(mandatoryQueue_in, address); 941 } 942 943 action(z_stallAndWaitOptionalQueue, "\pz", desc="Stall and wait the L1 prefetch request queue") { 944 stall_and_wait(optionalQueue_in, address); 945 } 946 947 action(kd_wakeUpDependents, "kd", desc="wake-up dependents") { 948 wakeUpBuffers(address); 949 } 950 951 action(uu_profileInstMiss, "\uim", desc="Profile the demand miss") { 952 ++L1Icache.demand_misses; 953 } 954 955 action(uu_profileInstHit, "\uih", desc="Profile the demand hit") { 956 ++L1Icache.demand_hits; 957 } 958 959 action(uu_profileDataMiss, "\udm", desc="Profile the demand miss") { 960 ++L1Dcache.demand_misses; 961 } 962 963 action(uu_profileDataHit, "\udh", desc="Profile the demand hit") { 964 ++L1Dcache.demand_hits; 965 } 966 967 action(po_observeHit, "\ph", desc="Inform the prefetcher about the hit") { 968 peek(mandatoryQueue_in, RubyRequest) { 969 if (cache_entry.isPrefetch) { 970 prefetcher.observePfHit(in_msg.LineAddress); 971 cache_entry.isPrefetch := false; 972 } 973 } 974 } 975 976 action(po_observeMiss, "\po", desc="Inform the prefetcher about the miss") { 977 peek(mandatoryQueue_in, RubyRequest) { 978 if (enable_prefetch) { 979 prefetcher.observeMiss(in_msg.LineAddress, in_msg.Type); 980 } 981 } 982 } 983 984 action(ppm_observePfMiss, "\ppm", 985 desc="Inform the prefetcher about the partial miss") { 986 peek(mandatoryQueue_in, RubyRequest) { 987 prefetcher.observePfMiss(in_msg.LineAddress); 988 } 989 } 990 991 action(pq_popPrefetchQueue, "\pq", desc="Pop the prefetch request queue") { 992 optionalQueue_in.dequeue(clockEdge()); 993 } 994 995 action(mp_markPrefetched, "mp", desc="Set the isPrefetch flag") { 996 assert(is_valid(cache_entry)); 997 cache_entry.isPrefetch := true; 998 } 999 1000 1001 //***************************************************** 1002 // TRANSITIONS 1003 //***************************************************** 1004 1005 // Transitions for Load/Store/Replacement/WriteBack from transient states 1006 transition({IS, IM, IS_I, M_I, SM, SINK_WB_ACK}, {Load, Ifetch, Store, L1_Replacement}) { 1007 z_stallAndWaitMandatoryQueue; 1008 } 1009 1010 transition({PF_IS, PF_IS_I}, {Store, L1_Replacement}) { 1011 z_stallAndWaitMandatoryQueue; 1012 } 1013 1014 transition({PF_IM, PF_SM}, {Load, Ifetch, L1_Replacement}) { 1015 z_stallAndWaitMandatoryQueue; 1016 } 1017 1018 transition({IS, IM, IS_I, M_I, SM, SINK_WB_ACK, PF_IS, PF_IS_I, PF_IM, PF_SM}, PF_L1_Replacement) { 1019 z_stallAndWaitOptionalQueue; 1020 } 1021 1022 // Transitions from Idle 1023 transition({NP,I}, {L1_Replacement, PF_L1_Replacement}) { 1024 ff_deallocateL1CacheBlock; 1025 } 1026 1027 transition({S,E,M,IS,IM,SM,IS_I,PF_IS_I,M_I,SINK_WB_ACK,PF_IS,PF_IM}, 1028 {PF_Load, PF_Store, PF_Ifetch}) { 1029 pq_popPrefetchQueue; 1030 } 1031 1032 transition({NP,I}, Load, IS) { 1033 oo_allocateL1DCacheBlock; 1034 i_allocateTBE; 1035 a_issueGETS; 1036 uu_profileDataMiss; 1037 po_observeMiss; 1038 k_popMandatoryQueue; 1039 } 1040 1041 transition({NP,I}, PF_Load, PF_IS) { 1042 oo_allocateL1DCacheBlock; 1043 i_allocateTBE; 1044 pa_issuePfGETS; 1045 pq_popPrefetchQueue; 1046 } 1047 1048 transition(PF_IS, Load, IS) { 1049 uu_profileDataMiss; 1050 ppm_observePfMiss; 1051 k_popMandatoryQueue; 1052 } 1053 1054 transition(PF_IS_I, Load, IS_I) { 1055 uu_profileDataMiss; 1056 ppm_observePfMiss; 1057 k_popMandatoryQueue; 1058 } 1059 1060 transition(PF_IS_I, Ifetch, IS_I) { 1061 uu_profileInstMiss; 1062 ppm_observePfMiss; 1063 k_popMandatoryQueue; 1064 } 1065 1066 transition({NP,I}, Ifetch, IS) { 1067 pp_allocateL1ICacheBlock; 1068 i_allocateTBE; 1069 ai_issueGETINSTR; 1070 uu_profileInstMiss; 1071 po_observeMiss; 1072 k_popMandatoryQueue; 1073 } 1074 1075 transition({NP,I}, PF_Ifetch, PF_IS) { 1076 pp_allocateL1ICacheBlock; 1077 i_allocateTBE; 1078 pai_issuePfGETINSTR; 1079 pq_popPrefetchQueue; 1080 } 1081 1082 // We proactively assume that the prefetch is in to 1083 // the instruction cache 1084 transition(PF_IS, Ifetch, IS) { 1085 uu_profileDataMiss; 1086 ppm_observePfMiss; 1087 k_popMandatoryQueue; 1088 } 1089 1090 transition({NP,I}, Store, IM) { 1091 oo_allocateL1DCacheBlock; 1092 i_allocateTBE; 1093 b_issueGETX; 1094 uu_profileDataMiss; 1095 po_observeMiss; 1096 k_popMandatoryQueue; 1097 } 1098 1099 transition({NP,I}, PF_Store, PF_IM) { 1100 oo_allocateL1DCacheBlock; 1101 i_allocateTBE; 1102 pb_issuePfGETX; 1103 pq_popPrefetchQueue; 1104 } 1105 1106 transition(PF_IM, Store, IM) { 1107 uu_profileDataMiss; 1108 ppm_observePfMiss; 1109 k_popMandatoryQueue; 1110 } 1111 1112 transition(PF_SM, Store, SM) { 1113 uu_profileDataMiss; 1114 ppm_observePfMiss; 1115 k_popMandatoryQueue; 1116 } 1117 1118 transition({NP, I}, Inv) { 1119 fi_sendInvAck; 1120 l_popRequestQueue; 1121 } 1122 1123 // Transitions from Shared 1124 transition({S,E,M}, Load) { 1125 h_load_hit; 1126 uu_profileDataHit; 1127 po_observeHit; 1128 k_popMandatoryQueue; 1129 } 1130 1131 transition({S,E,M}, Ifetch) { 1132 h_ifetch_hit; 1133 uu_profileInstHit; 1134 po_observeHit; 1135 k_popMandatoryQueue; 1136 } 1137 1138 transition(S, Store, SM) { 1139 i_allocateTBE; 1140 c_issueUPGRADE; 1141 uu_profileDataMiss; 1142 k_popMandatoryQueue; 1143 } 1144 1145 transition(S, {L1_Replacement, PF_L1_Replacement}, I) { 1146 forward_eviction_to_cpu; 1147 ff_deallocateL1CacheBlock; 1148 } 1149 1150 transition(S, Inv, I) { 1151 forward_eviction_to_cpu; 1152 fi_sendInvAck; 1153 l_popRequestQueue; 1154 } 1155 1156 // Transitions from Exclusive 1157 1158 transition({E,M}, Store, M) { 1159 hh_store_hit; 1160 uu_profileDataHit; 1161 po_observeHit; 1162 k_popMandatoryQueue; 1163 } 1164 1165 transition(E, {L1_Replacement, PF_L1_Replacement}, M_I) { 1166 // silent E replacement?? 1167 forward_eviction_to_cpu; 1168 i_allocateTBE; 1169 g_issuePUTX; // send data, but hold in case forwarded request 1170 ff_deallocateL1CacheBlock; 1171 } 1172 1173 transition(E, Inv, I) { 1174 // don't send data 1175 forward_eviction_to_cpu; 1176 fi_sendInvAck; 1177 l_popRequestQueue; 1178 } 1179 1180 transition(E, Fwd_GETX, I) { 1181 forward_eviction_to_cpu; 1182 d_sendDataToRequestor; 1183 l_popRequestQueue; 1184 } 1185 1186 transition(E, {Fwd_GETS, Fwd_GET_INSTR}, S) { 1187 d_sendDataToRequestor; 1188 d2_sendDataToL2; 1189 l_popRequestQueue; 1190 } 1191 1192 // Transitions from Modified 1193 1194 transition(M, {L1_Replacement, PF_L1_Replacement}, M_I) { 1195 forward_eviction_to_cpu; 1196 i_allocateTBE; 1197 g_issuePUTX; // send data, but hold in case forwarded request 1198 ff_deallocateL1CacheBlock; 1199 } 1200 1201 transition(M_I, WB_Ack, I) { 1202 s_deallocateTBE; 1203 o_popIncomingResponseQueue; 1204 kd_wakeUpDependents; 1205 } 1206 1207 transition(M, Inv, I) { 1208 forward_eviction_to_cpu; 1209 f_sendDataToL2; 1210 l_popRequestQueue; 1211 } 1212 1213 transition(M_I, Inv, SINK_WB_ACK) { 1214 ft_sendDataToL2_fromTBE; 1215 l_popRequestQueue; 1216 } 1217 1218 transition(M, Fwd_GETX, I) { 1219 forward_eviction_to_cpu; 1220 d_sendDataToRequestor; 1221 l_popRequestQueue; 1222 } 1223 1224 transition(M, {Fwd_GETS, Fwd_GET_INSTR}, S) { 1225 d_sendDataToRequestor; 1226 d2_sendDataToL2; 1227 l_popRequestQueue; 1228 } 1229 1230 transition(M_I, Fwd_GETX, SINK_WB_ACK) { 1231 dt_sendDataToRequestor_fromTBE; 1232 l_popRequestQueue; 1233 } 1234 1235 transition(M_I, {Fwd_GETS, Fwd_GET_INSTR}, SINK_WB_ACK) { 1236 dt_sendDataToRequestor_fromTBE; 1237 d2t_sendDataToL2_fromTBE; 1238 l_popRequestQueue; 1239 } 1240 1241 // Transitions from IS 1242 transition({IS, IS_I}, Inv, IS_I) { 1243 fi_sendInvAck; 1244 l_popRequestQueue; 1245 } 1246 1247 transition({PF_IS, PF_IS_I}, Inv, PF_IS_I) { 1248 fi_sendInvAck; 1249 l_popRequestQueue; 1250 } 1251 1252 transition(IS, Data_all_Acks, S) { 1253 u_writeDataToL1Cache; 1254 hx_load_hit; 1255 s_deallocateTBE; 1256 o_popIncomingResponseQueue; 1257 kd_wakeUpDependents; 1258 } 1259 1260 transition(PF_IS, Data_all_Acks, S) { 1261 u_writeDataToL1Cache; 1262 s_deallocateTBE; 1263 mp_markPrefetched; 1264 o_popIncomingResponseQueue; 1265 kd_wakeUpDependents; 1266 } 1267 1268 transition(IS_I, Data_all_Acks, I) { 1269 u_writeDataToL1Cache; 1270 hx_load_hit; 1271 s_deallocateTBE; 1272 o_popIncomingResponseQueue; 1273 kd_wakeUpDependents; 1274 } 1275 1276 transition(PF_IS_I, Data_all_Acks, I) { 1277 s_deallocateTBE; 1278 o_popIncomingResponseQueue; 1279 kd_wakeUpDependents; 1280 } 1281 1282 transition(IS, DataS_fromL1, S) { 1283 u_writeDataToL1Cache; 1284 j_sendUnblock; 1285 hx_load_hit; 1286 s_deallocateTBE; 1287 o_popIncomingResponseQueue; 1288 kd_wakeUpDependents; 1289 } 1290 1291 transition(PF_IS, DataS_fromL1, S) { 1292 u_writeDataToL1Cache; 1293 j_sendUnblock; 1294 s_deallocateTBE; 1295 o_popIncomingResponseQueue; 1296 kd_wakeUpDependents; 1297 } 1298 1299 transition(IS_I, DataS_fromL1, I) { 1300 u_writeDataToL1Cache; 1301 j_sendUnblock; 1302 hx_load_hit; 1303 s_deallocateTBE; 1304 o_popIncomingResponseQueue; 1305 kd_wakeUpDependents; 1306 } 1307 1308 transition(PF_IS_I, DataS_fromL1, I) { 1309 j_sendUnblock; 1310 s_deallocateTBE; 1311 o_popIncomingResponseQueue; 1312 kd_wakeUpDependents; 1313 } 1314 1315 // directory is blocked when sending exclusive data 1316 transition(IS_I, Data_Exclusive, E) { 1317 u_writeDataToL1Cache; 1318 hx_load_hit; 1319 jj_sendExclusiveUnblock; 1320 s_deallocateTBE; 1321 o_popIncomingResponseQueue; 1322 kd_wakeUpDependents; 1323 } 1324 1325 // directory is blocked when sending exclusive data 1326 transition(PF_IS_I, Data_Exclusive, E) { 1327 u_writeDataToL1Cache; 1328 jj_sendExclusiveUnblock; 1329 s_deallocateTBE; 1330 o_popIncomingResponseQueue; 1331 kd_wakeUpDependents; 1332 } 1333 1334 transition(IS, Data_Exclusive, E) { 1335 u_writeDataToL1Cache; 1336 hx_load_hit; 1337 jj_sendExclusiveUnblock; 1338 s_deallocateTBE; 1339 o_popIncomingResponseQueue; 1340 kd_wakeUpDependents; 1341 } 1342 1343 transition(PF_IS, Data_Exclusive, E) { 1344 u_writeDataToL1Cache; 1345 jj_sendExclusiveUnblock; 1346 s_deallocateTBE; 1347 mp_markPrefetched; 1348 o_popIncomingResponseQueue; 1349 kd_wakeUpDependents; 1350 } 1351 1352 // Transitions from IM 1353 transition(IM, Inv, IM) { 1354 fi_sendInvAck; 1355 l_popRequestQueue; 1356 } 1357 1358 transition({PF_IM, PF_SM}, Inv, PF_IM) { 1359 fi_sendInvAck; 1360 l_popRequestQueue; 1361 } 1362 1363 transition(IM, Data, SM) { 1364 u_writeDataToL1Cache; 1365 q_updateAckCount; 1366 o_popIncomingResponseQueue; 1367 } 1368 1369 transition(PF_IM, Data, PF_SM) { 1370 u_writeDataToL1Cache; 1371 q_updateAckCount; 1372 o_popIncomingResponseQueue; 1373 } 1374 1375 transition(IM, Data_all_Acks, M) { 1376 u_writeDataToL1Cache; 1377 hhx_store_hit; 1378 jj_sendExclusiveUnblock; 1379 s_deallocateTBE; 1380 o_popIncomingResponseQueue; 1381 kd_wakeUpDependents; 1382 } 1383 1384 transition(PF_IM, Data_all_Acks, M) { 1385 u_writeDataToL1Cache; 1386 jj_sendExclusiveUnblock; 1387 s_deallocateTBE; 1388 mp_markPrefetched; 1389 o_popIncomingResponseQueue; 1390 kd_wakeUpDependents; 1391 } 1392 1393 // transitions from SM 1394 transition(SM, Inv, IM) { 1395 forward_eviction_to_cpu; 1396 fi_sendInvAck; 1397 dg_invalidate_sc; 1398 l_popRequestQueue; 1399 } 1400 1401 transition({SM, IM, PF_SM, PF_IM}, Ack) { 1402 q_updateAckCount; 1403 o_popIncomingResponseQueue; 1404 } 1405 1406 transition(SM, Ack_all, M) { 1407 jj_sendExclusiveUnblock; 1408 hhx_store_hit; 1409 s_deallocateTBE; 1410 o_popIncomingResponseQueue; 1411 kd_wakeUpDependents; 1412 } 1413 1414 transition(PF_SM, Ack_all, M) { 1415 jj_sendExclusiveUnblock; 1416 s_deallocateTBE; 1417 mp_markPrefetched; 1418 o_popIncomingResponseQueue; 1419 kd_wakeUpDependents; 1420 } 1421 1422 transition(SINK_WB_ACK, Inv){ 1423 fi_sendInvAck; 1424 l_popRequestQueue; 1425 } 1426 1427 transition(SINK_WB_ACK, WB_Ack, I){ 1428 s_deallocateTBE; 1429 o_popIncomingResponseQueue; 1430 kd_wakeUpDependents; 1431 } 1432}
|