MOESI_hammer-dir.sm (14184:11ac1337c5e2) MOESI_hammer-dir.sm (14300:22183ae13998)
1/*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3 * Copyright (c) 2009 Advanced Micro Devices, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * AMD's contributions to the MOESI hammer protocol do not constitute an
30 * endorsement of its similarity to any AMD products.
31 *
32 * Authors: Milo Martin
33 * Brad Beckmann
34 */
35
36machine(MachineType:Directory, "AMD Hammer-like protocol")
37 : DirectoryMemory * directory;
38 CacheMemory * probeFilter;
39 Cycles from_memory_controller_latency := 2;
40 Cycles to_memory_controller_latency := 1;
41 bool probe_filter_enabled := "False";
42 bool full_bit_dir_enabled := "False";
43
44 MessageBuffer * forwardFromDir, network="To", virtual_network="3",
45 vnet_type="forward";
46
47 MessageBuffer * responseFromDir, network="To", virtual_network="4",
48 vnet_type="response";
49
50 // For a finite buffered network, note that the DMA response network only
51 // works at this relatively lower numbered (lower priority) virtual network
52 // because the trigger queue decouples cache responses from DMA responses.
53 MessageBuffer * dmaResponseFromDir, network="To", virtual_network="1",
54 vnet_type="response";
55
56 MessageBuffer * unblockToDir, network="From", virtual_network="5",
57 vnet_type="unblock";
58
59 MessageBuffer * responseToDir, network="From", virtual_network="4",
60 vnet_type="response";
61
62 MessageBuffer * requestToDir, network="From", virtual_network="2",
63 vnet_type="request";
64
65 MessageBuffer * dmaRequestToDir, network="From", virtual_network="0",
66 vnet_type="request";
67
68 MessageBuffer * triggerQueue;
69 MessageBuffer * responseFromMemory;
70{
71 // STATES
72 state_declaration(State, desc="Directory states", default="Directory_State_E") {
73 // Base states
74 NX, AccessPermission:Maybe_Stale, desc="Not Owner, probe filter entry exists, block in O at Owner";
75 NO, AccessPermission:Maybe_Stale, desc="Not Owner, probe filter entry exists, block in E/M at Owner";
76 S, AccessPermission:Read_Only, desc="Data clean, probe filter entry exists pointing to the current owner";
77 O, AccessPermission:Read_Only, desc="Data clean, probe filter entry exists";
78 E, AccessPermission:Read_Write, desc="Exclusive Owner, no probe filter entry";
79
80 O_R, AccessPermission:Read_Only, desc="Was data Owner, replacing probe filter entry";
81 S_R, AccessPermission:Read_Only, desc="Was Not Owner or Sharer, replacing probe filter entry";
82 NO_R, AccessPermission:Busy, desc="Was Not Owner or Sharer, replacing probe filter entry";
83
84 NO_B, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked";
85 NO_B_X, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, next queued request GETX";
86 NO_B_S, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, next queued request GETS";
87 NO_B_S_W, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, forwarded merged GETS, waiting for responses";
88 O_B, AccessPermission:Busy, "O^B", desc="Owner, Blocked";
89 NO_B_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram";
90 O_B_W, AccessPermission:Busy, desc="Owner, Blocked, waiting for Dram";
91 NO_W, AccessPermission:Busy, desc="Not Owner, waiting for Dram";
92 O_W, AccessPermission:Busy, desc="Owner, waiting for Dram";
93 NO_DW_B_W, AccessPermission:Busy, desc="Not Owner, Dma Write waiting for Dram and cache responses";
94 NO_DR_B_W, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for Dram and cache responses";
95 NO_DR_B_D, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for cache responses including dirty data";
96 NO_DR_B, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for cache responses";
97 NO_DW_W, AccessPermission:Busy, desc="Not Owner, Dma Write waiting for Dram";
98 O_DR_B_W, AccessPermission:Busy, desc="Owner, Dma Read waiting for Dram and cache responses";
99 O_DR_B, AccessPermission:Busy, desc="Owner, Dma Read waiting for cache responses";
100 WB, AccessPermission:Busy, desc="Blocked on a writeback";
101 WB_O_W, AccessPermission:Busy, desc="Blocked on memory write, will go to O";
102 WB_E_W, AccessPermission:Busy, desc="Blocked on memory write, will go to E";
103
104 NO_F, AccessPermission:Busy, desc="Blocked on a flush";
105 NO_F_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram";
106 }
107
108 // Events
109 enumeration(Event, desc="Directory events") {
110 GETX, desc="A GETX arrives";
111 GETS, desc="A GETS arrives";
112 PUT, desc="A PUT arrives";
113 Unblock, desc="An unblock message arrives";
114 UnblockS, desc="An unblock message arrives";
115 UnblockM, desc="An unblock message arrives";
116 Writeback_Clean, desc="The final part of a PutX (no data)";
117 Writeback_Dirty, desc="The final part of a PutX (data)";
118 Writeback_Exclusive_Clean, desc="The final part of a PutX (no data, exclusive)";
119 Writeback_Exclusive_Dirty, desc="The final part of a PutX (data, exclusive)";
120
121 // Probe filter
122 Pf_Replacement, desc="probe filter replacement";
123
124 // DMA requests
125 DMA_READ, desc="A DMA Read memory request";
126 DMA_WRITE, desc="A DMA Write memory request";
127
128 // Memory Controller
129 Memory_Data, desc="Fetched data from memory arrives";
130 Memory_Ack, desc="Writeback Ack from memory arrives";
131
132 // Cache responses required to handle DMA
133 Ack, desc="Received an ack message";
134 Shared_Ack, desc="Received an ack message, responder has a shared copy";
135 Shared_Data, desc="Received a data message, responder has a shared copy";
136 Data, desc="Received a data message, responder had a owner or exclusive copy, they gave it to us";
137 Exclusive_Data, desc="Received a data message, responder had an exclusive copy, they gave it to us";
138
139 // Triggers
140 All_acks_and_shared_data, desc="Received shared data and message acks";
141 All_acks_and_owner_data, desc="Received shared data and message acks";
142 All_acks_and_data_no_sharers, desc="Received all acks and no other processor has a shared copy";
143 All_Unblocks, desc="Received all unblocks for a merged gets request";
144 GETF, desc="A GETF arrives";
145 PUTF, desc="A PUTF arrives";
146 }
147
148 // TYPES
149
150 // DirectoryEntry
151 structure(Entry, desc="...", interface="AbstractEntry") {
152 State DirectoryState, desc="Directory state";
153 }
154
155 // ProbeFilterEntry
156 structure(PfEntry, desc="...", interface="AbstractCacheEntry") {
157 State PfState, desc="Directory state";
158 MachineID Owner, desc="Owner node";
159 Set Sharers, desc="sharing vector for full bit directory";
160 }
161
162 // TBE entries for DMA requests
163 structure(TBE, desc="TBE entries for outstanding DMA requests") {
164 Addr PhysicalAddress, desc="physical address";
165 State TBEState, desc="Transient State";
166 CoherenceResponseType ResponseType, desc="The type for the subsequent response message";
167 int Acks, default="0", desc="The number of acks that the waiting response represents";
168 int SilentAcks, default="0", desc="The number of silent acks associated with this transaction";
169 DataBlock DmaDataBlk, desc="DMA Data to be written. Partial blocks need to merged with system memory";
170 DataBlock DataBlk, desc="The current view of system memory";
171 int Len, desc="...";
172 MachineID DmaRequestor, desc="DMA requestor";
173 NetDest GetSRequestors, desc="GETS merged requestors";
174 int NumPendingMsgs, desc="Number of pending acks/messages";
175 bool CacheDirty, default="false", desc="Indicates whether a cache has responded with dirty data";
176 bool Sharers, default="false", desc="Indicates whether a cache has indicated it is currently a sharer";
177 bool Owned, default="false", desc="Indicates whether a cache has indicated it is currently a sharer";
178 }
179
180 structure(TBETable, external="yes") {
181 TBE lookup(Addr);
182 void allocate(Addr);
183 void deallocate(Addr);
184 bool isPresent(Addr);
185 }
186
187 Tick clockEdge();
188 void set_cache_entry(AbstractCacheEntry b);
189 void unset_cache_entry();
190 void set_tbe(TBE a);
191 void unset_tbe();
192 void wakeUpBuffers(Addr a);
193 Cycles curCycle();
194
195 // ** OBJECTS **
196
197 Set fwd_set;
198
199 TBETable TBEs, template="<Directory_TBE>", constructor="m_number_of_TBEs";
200
201 Entry getDirectoryEntry(Addr addr), return_by_pointer="yes" {
202 Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
203
204 if (is_valid(dir_entry)) {
205 return dir_entry;
206 }
207
208 dir_entry := static_cast(Entry, "pointer",
209 directory.allocate(addr, new Entry));
210 return dir_entry;
211 }
212
213 PfEntry getProbeFilterEntry(Addr addr), return_by_pointer="yes" {
214 if (probe_filter_enabled || full_bit_dir_enabled) {
215 PfEntry pfEntry := static_cast(PfEntry, "pointer", probeFilter.lookup(addr));
216 return pfEntry;
217 }
218 return OOD;
219 }
220
221 State getState(TBE tbe, PfEntry pf_entry, Addr addr) {
222 if (is_valid(tbe)) {
223 return tbe.TBEState;
224 } else {
225 if (probe_filter_enabled || full_bit_dir_enabled) {
226 if (is_valid(pf_entry)) {
227 assert(pf_entry.PfState == getDirectoryEntry(addr).DirectoryState);
228 }
229 }
230 return getDirectoryEntry(addr).DirectoryState;
231 }
232 }
233
234 void setState(TBE tbe, PfEntry pf_entry, Addr addr, State state) {
235 if (is_valid(tbe)) {
236 tbe.TBEState := state;
237 }
238 if (probe_filter_enabled || full_bit_dir_enabled) {
239 if (is_valid(pf_entry)) {
240 pf_entry.PfState := state;
241 }
242 if (state == State:NX || state == State:NO || state == State:S || state == State:O) {
243 assert(is_valid(pf_entry));
244 }
245 if (state == State:E) {
246 assert(is_valid(pf_entry) == false);
247 }
248 }
249 if (state == State:E || state == State:NX || state == State:NO || state == State:S ||
250 state == State:O) {
251 assert(is_valid(tbe) == false);
252 }
253 getDirectoryEntry(addr).DirectoryState := state;
254 }
255
256 AccessPermission getAccessPermission(Addr addr) {
257 TBE tbe := TBEs[addr];
258 if(is_valid(tbe)) {
259 return Directory_State_to_permission(tbe.TBEState);
260 }
261
262 if(directory.isPresent(addr)) {
263 return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
264 }
265
266 return AccessPermission:NotPresent;
267 }
268
269 void setAccessPermission(PfEntry pf_entry, Addr addr, State state) {
270 getDirectoryEntry(addr).changePermission(Directory_State_to_permission(state));
271 }
272
273 void functionalRead(Addr addr, Packet *pkt) {
274 TBE tbe := TBEs[addr];
275 if(is_valid(tbe)) {
276 testAndRead(addr, tbe.DataBlk, pkt);
277 } else {
278 functionalMemoryRead(pkt);
279 }
280 }
281
282 int functionalWrite(Addr addr, Packet *pkt) {
283 int num_functional_writes := 0;
284
285 TBE tbe := TBEs[addr];
286 if(is_valid(tbe)) {
287 num_functional_writes := num_functional_writes +
288 testAndWrite(addr, tbe.DataBlk, pkt);
289 }
290
291 num_functional_writes := num_functional_writes + functionalMemoryWrite(pkt);
292 return num_functional_writes;
293 }
294
295 Event cache_request_to_event(CoherenceRequestType type) {
296 if (type == CoherenceRequestType:GETS) {
297 return Event:GETS;
298 } else if (type == CoherenceRequestType:GETX) {
299 return Event:GETX;
300 } else if (type == CoherenceRequestType:GETF) {
301 return Event:GETF;
302 } else {
303 error("Invalid CoherenceRequestType");
304 }
305 }
306
307 // ** OUT_PORTS **
308 out_port(requestQueue_out, ResponseMsg, requestToDir); // For recycling requests
309 out_port(forwardNetwork_out, RequestMsg, forwardFromDir);
310 out_port(responseNetwork_out, ResponseMsg, responseFromDir);
311 out_port(dmaResponseNetwork_out, DMAResponseMsg, dmaResponseFromDir);
312 out_port(triggerQueue_out, TriggerMsg, triggerQueue);
313
314 // ** IN_PORTS **
315
316 // Trigger Queue
317 in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=5) {
318 if (triggerQueue_in.isReady(clockEdge())) {
319 peek(triggerQueue_in, TriggerMsg) {
320 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
321 TBE tbe := TBEs[in_msg.addr];
322 if (in_msg.Type == TriggerType:ALL_ACKS) {
323 trigger(Event:All_acks_and_owner_data, in_msg.addr,
324 pf_entry, tbe);
325 } else if (in_msg.Type == TriggerType:ALL_ACKS_OWNER_EXISTS) {
326 trigger(Event:All_acks_and_shared_data, in_msg.addr,
327 pf_entry, tbe);
328 } else if (in_msg.Type == TriggerType:ALL_ACKS_NO_SHARERS) {
329 trigger(Event:All_acks_and_data_no_sharers, in_msg.addr,
330 pf_entry, tbe);
331 } else if (in_msg.Type == TriggerType:ALL_UNBLOCKS) {
332 trigger(Event:All_Unblocks, in_msg.addr,
333 pf_entry, tbe);
334 } else {
335 error("Unexpected message");
336 }
337 }
338 }
339 }
340
341 in_port(unblockNetwork_in, ResponseMsg, unblockToDir, rank=4) {
342 if (unblockNetwork_in.isReady(clockEdge())) {
343 peek(unblockNetwork_in, ResponseMsg) {
344 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
345 TBE tbe := TBEs[in_msg.addr];
346 if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
347 trigger(Event:Unblock, in_msg.addr, pf_entry, tbe);
348 } else if (in_msg.Type == CoherenceResponseType:UNBLOCKS) {
349 trigger(Event:UnblockS, in_msg.addr, pf_entry, tbe);
350 } else if (in_msg.Type == CoherenceResponseType:UNBLOCKM) {
351 trigger(Event:UnblockM, in_msg.addr, pf_entry, tbe);
352 } else if (in_msg.Type == CoherenceResponseType:WB_CLEAN) {
353 trigger(Event:Writeback_Clean, in_msg.addr, pf_entry, tbe);
354 } else if (in_msg.Type == CoherenceResponseType:WB_DIRTY) {
355 trigger(Event:Writeback_Dirty, in_msg.addr, pf_entry, tbe);
356 } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_CLEAN) {
357 trigger(Event:Writeback_Exclusive_Clean, in_msg.addr,
358 pf_entry, tbe);
359 } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_DIRTY) {
360 trigger(Event:Writeback_Exclusive_Dirty, in_msg.addr,
361 pf_entry, tbe);
362 } else {
363 error("Invalid message");
364 }
365 }
366 }
367 }
368
369 // Response Network
370 in_port(responseToDir_in, ResponseMsg, responseToDir, rank=3) {
371 if (responseToDir_in.isReady(clockEdge())) {
372 peek(responseToDir_in, ResponseMsg) {
373 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
374 TBE tbe := TBEs[in_msg.addr];
375 if (in_msg.Type == CoherenceResponseType:ACK) {
376 trigger(Event:Ack, in_msg.addr, pf_entry, tbe);
377 } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) {
378 trigger(Event:Shared_Ack, in_msg.addr, pf_entry, tbe);
379 } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) {
380 trigger(Event:Shared_Data, in_msg.addr, pf_entry, tbe);
381 } else if (in_msg.Type == CoherenceResponseType:DATA) {
382 trigger(Event:Data, in_msg.addr, pf_entry, tbe);
383 } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
384 trigger(Event:Exclusive_Data, in_msg.addr, pf_entry, tbe);
385 } else {
386 error("Unexpected message");
387 }
388 }
389 }
390 }
391
392 // off-chip memory request/response is done
393 in_port(memQueue_in, MemoryMsg, responseFromMemory, rank=2) {
394 if (memQueue_in.isReady(clockEdge())) {
395 peek(memQueue_in, MemoryMsg) {
396 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
397 TBE tbe := TBEs[in_msg.addr];
398 if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
399 trigger(Event:Memory_Data, in_msg.addr, pf_entry, tbe);
400 } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
401 trigger(Event:Memory_Ack, in_msg.addr, pf_entry, tbe);
402 } else {
403 DPRINTF(RubySlicc, "%d\n", in_msg.Type);
404 error("Invalid message");
405 }
406 }
407 }
408 }
409
410 in_port(requestQueue_in, RequestMsg, requestToDir, rank=1) {
411 if (requestQueue_in.isReady(clockEdge())) {
412 peek(requestQueue_in, RequestMsg) {
413 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
414 TBE tbe := TBEs[in_msg.addr];
415 if (in_msg.Type == CoherenceRequestType:PUT) {
416 trigger(Event:PUT, in_msg.addr, pf_entry, tbe);
417 } else if (in_msg.Type == CoherenceRequestType:PUTF) {
418 trigger(Event:PUTF, in_msg.addr, pf_entry, tbe);
419 } else {
420 if (probe_filter_enabled || full_bit_dir_enabled) {
421 if (is_valid(pf_entry)) {
422 trigger(cache_request_to_event(in_msg.Type), in_msg.addr,
423 pf_entry, tbe);
424 } else {
425 if (probeFilter.cacheAvail(in_msg.addr)) {
426 trigger(cache_request_to_event(in_msg.Type), in_msg.addr,
427 pf_entry, tbe);
428 } else {
429 trigger(Event:Pf_Replacement,
1/*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3 * Copyright (c) 2009 Advanced Micro Devices, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * AMD's contributions to the MOESI hammer protocol do not constitute an
30 * endorsement of its similarity to any AMD products.
31 *
32 * Authors: Milo Martin
33 * Brad Beckmann
34 */
35
36machine(MachineType:Directory, "AMD Hammer-like protocol")
37 : DirectoryMemory * directory;
38 CacheMemory * probeFilter;
39 Cycles from_memory_controller_latency := 2;
40 Cycles to_memory_controller_latency := 1;
41 bool probe_filter_enabled := "False";
42 bool full_bit_dir_enabled := "False";
43
44 MessageBuffer * forwardFromDir, network="To", virtual_network="3",
45 vnet_type="forward";
46
47 MessageBuffer * responseFromDir, network="To", virtual_network="4",
48 vnet_type="response";
49
50 // For a finite buffered network, note that the DMA response network only
51 // works at this relatively lower numbered (lower priority) virtual network
52 // because the trigger queue decouples cache responses from DMA responses.
53 MessageBuffer * dmaResponseFromDir, network="To", virtual_network="1",
54 vnet_type="response";
55
56 MessageBuffer * unblockToDir, network="From", virtual_network="5",
57 vnet_type="unblock";
58
59 MessageBuffer * responseToDir, network="From", virtual_network="4",
60 vnet_type="response";
61
62 MessageBuffer * requestToDir, network="From", virtual_network="2",
63 vnet_type="request";
64
65 MessageBuffer * dmaRequestToDir, network="From", virtual_network="0",
66 vnet_type="request";
67
68 MessageBuffer * triggerQueue;
69 MessageBuffer * responseFromMemory;
70{
71 // STATES
72 state_declaration(State, desc="Directory states", default="Directory_State_E") {
73 // Base states
74 NX, AccessPermission:Maybe_Stale, desc="Not Owner, probe filter entry exists, block in O at Owner";
75 NO, AccessPermission:Maybe_Stale, desc="Not Owner, probe filter entry exists, block in E/M at Owner";
76 S, AccessPermission:Read_Only, desc="Data clean, probe filter entry exists pointing to the current owner";
77 O, AccessPermission:Read_Only, desc="Data clean, probe filter entry exists";
78 E, AccessPermission:Read_Write, desc="Exclusive Owner, no probe filter entry";
79
80 O_R, AccessPermission:Read_Only, desc="Was data Owner, replacing probe filter entry";
81 S_R, AccessPermission:Read_Only, desc="Was Not Owner or Sharer, replacing probe filter entry";
82 NO_R, AccessPermission:Busy, desc="Was Not Owner or Sharer, replacing probe filter entry";
83
84 NO_B, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked";
85 NO_B_X, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, next queued request GETX";
86 NO_B_S, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, next queued request GETS";
87 NO_B_S_W, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, forwarded merged GETS, waiting for responses";
88 O_B, AccessPermission:Busy, "O^B", desc="Owner, Blocked";
89 NO_B_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram";
90 O_B_W, AccessPermission:Busy, desc="Owner, Blocked, waiting for Dram";
91 NO_W, AccessPermission:Busy, desc="Not Owner, waiting for Dram";
92 O_W, AccessPermission:Busy, desc="Owner, waiting for Dram";
93 NO_DW_B_W, AccessPermission:Busy, desc="Not Owner, Dma Write waiting for Dram and cache responses";
94 NO_DR_B_W, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for Dram and cache responses";
95 NO_DR_B_D, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for cache responses including dirty data";
96 NO_DR_B, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for cache responses";
97 NO_DW_W, AccessPermission:Busy, desc="Not Owner, Dma Write waiting for Dram";
98 O_DR_B_W, AccessPermission:Busy, desc="Owner, Dma Read waiting for Dram and cache responses";
99 O_DR_B, AccessPermission:Busy, desc="Owner, Dma Read waiting for cache responses";
100 WB, AccessPermission:Busy, desc="Blocked on a writeback";
101 WB_O_W, AccessPermission:Busy, desc="Blocked on memory write, will go to O";
102 WB_E_W, AccessPermission:Busy, desc="Blocked on memory write, will go to E";
103
104 NO_F, AccessPermission:Busy, desc="Blocked on a flush";
105 NO_F_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram";
106 }
107
108 // Events
109 enumeration(Event, desc="Directory events") {
110 GETX, desc="A GETX arrives";
111 GETS, desc="A GETS arrives";
112 PUT, desc="A PUT arrives";
113 Unblock, desc="An unblock message arrives";
114 UnblockS, desc="An unblock message arrives";
115 UnblockM, desc="An unblock message arrives";
116 Writeback_Clean, desc="The final part of a PutX (no data)";
117 Writeback_Dirty, desc="The final part of a PutX (data)";
118 Writeback_Exclusive_Clean, desc="The final part of a PutX (no data, exclusive)";
119 Writeback_Exclusive_Dirty, desc="The final part of a PutX (data, exclusive)";
120
121 // Probe filter
122 Pf_Replacement, desc="probe filter replacement";
123
124 // DMA requests
125 DMA_READ, desc="A DMA Read memory request";
126 DMA_WRITE, desc="A DMA Write memory request";
127
128 // Memory Controller
129 Memory_Data, desc="Fetched data from memory arrives";
130 Memory_Ack, desc="Writeback Ack from memory arrives";
131
132 // Cache responses required to handle DMA
133 Ack, desc="Received an ack message";
134 Shared_Ack, desc="Received an ack message, responder has a shared copy";
135 Shared_Data, desc="Received a data message, responder has a shared copy";
136 Data, desc="Received a data message, responder had a owner or exclusive copy, they gave it to us";
137 Exclusive_Data, desc="Received a data message, responder had an exclusive copy, they gave it to us";
138
139 // Triggers
140 All_acks_and_shared_data, desc="Received shared data and message acks";
141 All_acks_and_owner_data, desc="Received shared data and message acks";
142 All_acks_and_data_no_sharers, desc="Received all acks and no other processor has a shared copy";
143 All_Unblocks, desc="Received all unblocks for a merged gets request";
144 GETF, desc="A GETF arrives";
145 PUTF, desc="A PUTF arrives";
146 }
147
148 // TYPES
149
150 // DirectoryEntry
151 structure(Entry, desc="...", interface="AbstractEntry") {
152 State DirectoryState, desc="Directory state";
153 }
154
155 // ProbeFilterEntry
156 structure(PfEntry, desc="...", interface="AbstractCacheEntry") {
157 State PfState, desc="Directory state";
158 MachineID Owner, desc="Owner node";
159 Set Sharers, desc="sharing vector for full bit directory";
160 }
161
162 // TBE entries for DMA requests
163 structure(TBE, desc="TBE entries for outstanding DMA requests") {
164 Addr PhysicalAddress, desc="physical address";
165 State TBEState, desc="Transient State";
166 CoherenceResponseType ResponseType, desc="The type for the subsequent response message";
167 int Acks, default="0", desc="The number of acks that the waiting response represents";
168 int SilentAcks, default="0", desc="The number of silent acks associated with this transaction";
169 DataBlock DmaDataBlk, desc="DMA Data to be written. Partial blocks need to merged with system memory";
170 DataBlock DataBlk, desc="The current view of system memory";
171 int Len, desc="...";
172 MachineID DmaRequestor, desc="DMA requestor";
173 NetDest GetSRequestors, desc="GETS merged requestors";
174 int NumPendingMsgs, desc="Number of pending acks/messages";
175 bool CacheDirty, default="false", desc="Indicates whether a cache has responded with dirty data";
176 bool Sharers, default="false", desc="Indicates whether a cache has indicated it is currently a sharer";
177 bool Owned, default="false", desc="Indicates whether a cache has indicated it is currently a sharer";
178 }
179
180 structure(TBETable, external="yes") {
181 TBE lookup(Addr);
182 void allocate(Addr);
183 void deallocate(Addr);
184 bool isPresent(Addr);
185 }
186
187 Tick clockEdge();
188 void set_cache_entry(AbstractCacheEntry b);
189 void unset_cache_entry();
190 void set_tbe(TBE a);
191 void unset_tbe();
192 void wakeUpBuffers(Addr a);
193 Cycles curCycle();
194
195 // ** OBJECTS **
196
197 Set fwd_set;
198
199 TBETable TBEs, template="<Directory_TBE>", constructor="m_number_of_TBEs";
200
201 Entry getDirectoryEntry(Addr addr), return_by_pointer="yes" {
202 Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
203
204 if (is_valid(dir_entry)) {
205 return dir_entry;
206 }
207
208 dir_entry := static_cast(Entry, "pointer",
209 directory.allocate(addr, new Entry));
210 return dir_entry;
211 }
212
213 PfEntry getProbeFilterEntry(Addr addr), return_by_pointer="yes" {
214 if (probe_filter_enabled || full_bit_dir_enabled) {
215 PfEntry pfEntry := static_cast(PfEntry, "pointer", probeFilter.lookup(addr));
216 return pfEntry;
217 }
218 return OOD;
219 }
220
221 State getState(TBE tbe, PfEntry pf_entry, Addr addr) {
222 if (is_valid(tbe)) {
223 return tbe.TBEState;
224 } else {
225 if (probe_filter_enabled || full_bit_dir_enabled) {
226 if (is_valid(pf_entry)) {
227 assert(pf_entry.PfState == getDirectoryEntry(addr).DirectoryState);
228 }
229 }
230 return getDirectoryEntry(addr).DirectoryState;
231 }
232 }
233
234 void setState(TBE tbe, PfEntry pf_entry, Addr addr, State state) {
235 if (is_valid(tbe)) {
236 tbe.TBEState := state;
237 }
238 if (probe_filter_enabled || full_bit_dir_enabled) {
239 if (is_valid(pf_entry)) {
240 pf_entry.PfState := state;
241 }
242 if (state == State:NX || state == State:NO || state == State:S || state == State:O) {
243 assert(is_valid(pf_entry));
244 }
245 if (state == State:E) {
246 assert(is_valid(pf_entry) == false);
247 }
248 }
249 if (state == State:E || state == State:NX || state == State:NO || state == State:S ||
250 state == State:O) {
251 assert(is_valid(tbe) == false);
252 }
253 getDirectoryEntry(addr).DirectoryState := state;
254 }
255
256 AccessPermission getAccessPermission(Addr addr) {
257 TBE tbe := TBEs[addr];
258 if(is_valid(tbe)) {
259 return Directory_State_to_permission(tbe.TBEState);
260 }
261
262 if(directory.isPresent(addr)) {
263 return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
264 }
265
266 return AccessPermission:NotPresent;
267 }
268
269 void setAccessPermission(PfEntry pf_entry, Addr addr, State state) {
270 getDirectoryEntry(addr).changePermission(Directory_State_to_permission(state));
271 }
272
273 void functionalRead(Addr addr, Packet *pkt) {
274 TBE tbe := TBEs[addr];
275 if(is_valid(tbe)) {
276 testAndRead(addr, tbe.DataBlk, pkt);
277 } else {
278 functionalMemoryRead(pkt);
279 }
280 }
281
282 int functionalWrite(Addr addr, Packet *pkt) {
283 int num_functional_writes := 0;
284
285 TBE tbe := TBEs[addr];
286 if(is_valid(tbe)) {
287 num_functional_writes := num_functional_writes +
288 testAndWrite(addr, tbe.DataBlk, pkt);
289 }
290
291 num_functional_writes := num_functional_writes + functionalMemoryWrite(pkt);
292 return num_functional_writes;
293 }
294
295 Event cache_request_to_event(CoherenceRequestType type) {
296 if (type == CoherenceRequestType:GETS) {
297 return Event:GETS;
298 } else if (type == CoherenceRequestType:GETX) {
299 return Event:GETX;
300 } else if (type == CoherenceRequestType:GETF) {
301 return Event:GETF;
302 } else {
303 error("Invalid CoherenceRequestType");
304 }
305 }
306
307 // ** OUT_PORTS **
308 out_port(requestQueue_out, ResponseMsg, requestToDir); // For recycling requests
309 out_port(forwardNetwork_out, RequestMsg, forwardFromDir);
310 out_port(responseNetwork_out, ResponseMsg, responseFromDir);
311 out_port(dmaResponseNetwork_out, DMAResponseMsg, dmaResponseFromDir);
312 out_port(triggerQueue_out, TriggerMsg, triggerQueue);
313
314 // ** IN_PORTS **
315
316 // Trigger Queue
317 in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=5) {
318 if (triggerQueue_in.isReady(clockEdge())) {
319 peek(triggerQueue_in, TriggerMsg) {
320 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
321 TBE tbe := TBEs[in_msg.addr];
322 if (in_msg.Type == TriggerType:ALL_ACKS) {
323 trigger(Event:All_acks_and_owner_data, in_msg.addr,
324 pf_entry, tbe);
325 } else if (in_msg.Type == TriggerType:ALL_ACKS_OWNER_EXISTS) {
326 trigger(Event:All_acks_and_shared_data, in_msg.addr,
327 pf_entry, tbe);
328 } else if (in_msg.Type == TriggerType:ALL_ACKS_NO_SHARERS) {
329 trigger(Event:All_acks_and_data_no_sharers, in_msg.addr,
330 pf_entry, tbe);
331 } else if (in_msg.Type == TriggerType:ALL_UNBLOCKS) {
332 trigger(Event:All_Unblocks, in_msg.addr,
333 pf_entry, tbe);
334 } else {
335 error("Unexpected message");
336 }
337 }
338 }
339 }
340
341 in_port(unblockNetwork_in, ResponseMsg, unblockToDir, rank=4) {
342 if (unblockNetwork_in.isReady(clockEdge())) {
343 peek(unblockNetwork_in, ResponseMsg) {
344 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
345 TBE tbe := TBEs[in_msg.addr];
346 if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
347 trigger(Event:Unblock, in_msg.addr, pf_entry, tbe);
348 } else if (in_msg.Type == CoherenceResponseType:UNBLOCKS) {
349 trigger(Event:UnblockS, in_msg.addr, pf_entry, tbe);
350 } else if (in_msg.Type == CoherenceResponseType:UNBLOCKM) {
351 trigger(Event:UnblockM, in_msg.addr, pf_entry, tbe);
352 } else if (in_msg.Type == CoherenceResponseType:WB_CLEAN) {
353 trigger(Event:Writeback_Clean, in_msg.addr, pf_entry, tbe);
354 } else if (in_msg.Type == CoherenceResponseType:WB_DIRTY) {
355 trigger(Event:Writeback_Dirty, in_msg.addr, pf_entry, tbe);
356 } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_CLEAN) {
357 trigger(Event:Writeback_Exclusive_Clean, in_msg.addr,
358 pf_entry, tbe);
359 } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_DIRTY) {
360 trigger(Event:Writeback_Exclusive_Dirty, in_msg.addr,
361 pf_entry, tbe);
362 } else {
363 error("Invalid message");
364 }
365 }
366 }
367 }
368
369 // Response Network
370 in_port(responseToDir_in, ResponseMsg, responseToDir, rank=3) {
371 if (responseToDir_in.isReady(clockEdge())) {
372 peek(responseToDir_in, ResponseMsg) {
373 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
374 TBE tbe := TBEs[in_msg.addr];
375 if (in_msg.Type == CoherenceResponseType:ACK) {
376 trigger(Event:Ack, in_msg.addr, pf_entry, tbe);
377 } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) {
378 trigger(Event:Shared_Ack, in_msg.addr, pf_entry, tbe);
379 } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) {
380 trigger(Event:Shared_Data, in_msg.addr, pf_entry, tbe);
381 } else if (in_msg.Type == CoherenceResponseType:DATA) {
382 trigger(Event:Data, in_msg.addr, pf_entry, tbe);
383 } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
384 trigger(Event:Exclusive_Data, in_msg.addr, pf_entry, tbe);
385 } else {
386 error("Unexpected message");
387 }
388 }
389 }
390 }
391
392 // off-chip memory request/response is done
393 in_port(memQueue_in, MemoryMsg, responseFromMemory, rank=2) {
394 if (memQueue_in.isReady(clockEdge())) {
395 peek(memQueue_in, MemoryMsg) {
396 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
397 TBE tbe := TBEs[in_msg.addr];
398 if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
399 trigger(Event:Memory_Data, in_msg.addr, pf_entry, tbe);
400 } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
401 trigger(Event:Memory_Ack, in_msg.addr, pf_entry, tbe);
402 } else {
403 DPRINTF(RubySlicc, "%d\n", in_msg.Type);
404 error("Invalid message");
405 }
406 }
407 }
408 }
409
410 in_port(requestQueue_in, RequestMsg, requestToDir, rank=1) {
411 if (requestQueue_in.isReady(clockEdge())) {
412 peek(requestQueue_in, RequestMsg) {
413 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
414 TBE tbe := TBEs[in_msg.addr];
415 if (in_msg.Type == CoherenceRequestType:PUT) {
416 trigger(Event:PUT, in_msg.addr, pf_entry, tbe);
417 } else if (in_msg.Type == CoherenceRequestType:PUTF) {
418 trigger(Event:PUTF, in_msg.addr, pf_entry, tbe);
419 } else {
420 if (probe_filter_enabled || full_bit_dir_enabled) {
421 if (is_valid(pf_entry)) {
422 trigger(cache_request_to_event(in_msg.Type), in_msg.addr,
423 pf_entry, tbe);
424 } else {
425 if (probeFilter.cacheAvail(in_msg.addr)) {
426 trigger(cache_request_to_event(in_msg.Type), in_msg.addr,
427 pf_entry, tbe);
428 } else {
429 trigger(Event:Pf_Replacement,
430 probeFilter.cacheProbe(in_msg.addr),
431 getProbeFilterEntry(probeFilter.cacheProbe(in_msg.addr)),
432 TBEs[probeFilter.cacheProbe(in_msg.addr)]);
430 Addr victim := probeFilter.cacheProbe(in_msg.addr);
431 trigger(Event:Pf_Replacement,
432 victim, getProbeFilterEntry(victim), TBEs[victim]);
433 }
434 }
435 } else {
436 trigger(cache_request_to_event(in_msg.Type), in_msg.addr,
437 pf_entry, tbe);
438 }
439 }
440 }
441 }
442 }
443
444 in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir, rank=0) {
445 if (dmaRequestQueue_in.isReady(clockEdge())) {
446 peek(dmaRequestQueue_in, DMARequestMsg) {
447 PfEntry pf_entry := getProbeFilterEntry(in_msg.LineAddress);
448 TBE tbe := TBEs[in_msg.LineAddress];
449 if (in_msg.Type == DMARequestType:READ) {
450 trigger(Event:DMA_READ, in_msg.LineAddress, pf_entry, tbe);
451 } else if (in_msg.Type == DMARequestType:WRITE) {
452 trigger(Event:DMA_WRITE, in_msg.LineAddress, pf_entry, tbe);
453 } else {
454 error("Invalid message");
455 }
456 }
457 }
458 }
459
460 // Actions
461
462 action(r_setMRU, "\rr", desc="manually set the MRU bit for pf entry" ) {
463 if (probe_filter_enabled || full_bit_dir_enabled) {
464 assert(is_valid(cache_entry));
465 probeFilter.setMRU(address);
466 }
467 }
468
469 action(auno_assertUnblockerNotOwner, "auno", desc="assert unblocker not owner") {
470 if (probe_filter_enabled || full_bit_dir_enabled) {
471 assert(is_valid(cache_entry));
472 peek(unblockNetwork_in, ResponseMsg) {
473 assert(cache_entry.Owner != in_msg.Sender);
474 if (full_bit_dir_enabled) {
475 assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Sender)) == false);
476 }
477 }
478 }
479 }
480
481 action(uo_updateOwnerIfPf, "uo", desc="update owner") {
482 if (probe_filter_enabled || full_bit_dir_enabled) {
483 assert(is_valid(cache_entry));
484 peek(unblockNetwork_in, ResponseMsg) {
485 cache_entry.Owner := in_msg.Sender;
486 if (full_bit_dir_enabled) {
487 cache_entry.Sharers.clear();
488 cache_entry.Sharers.add(machineIDToNodeID(in_msg.Sender));
489 APPEND_TRANSITION_COMMENT(cache_entry.Sharers);
490 DPRINTF(RubySlicc, "Sharers = %d\n", cache_entry.Sharers);
491 }
492 }
493 }
494 }
495
496 action(us_updateSharerIfFBD, "us", desc="update sharer if full-bit directory") {
497 if (full_bit_dir_enabled) {
498 assert(probeFilter.isTagPresent(address));
499 peek(unblockNetwork_in, ResponseMsg) {
500 cache_entry.Sharers.add(machineIDToNodeID(in_msg.Sender));
501 }
502 }
503 }
504
505 action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") {
506 peek(requestQueue_in, RequestMsg) {
507 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
508 out_msg.addr := address;
509 out_msg.Type := CoherenceRequestType:WB_ACK;
510 out_msg.Requestor := in_msg.Requestor;
511 out_msg.Destination.add(in_msg.Requestor);
512 out_msg.MessageSize := MessageSizeType:Writeback_Control;
513 }
514 }
515 }
516
517 action(oc_sendBlockAck, "oc", desc="Send block ack to the owner") {
518 peek(requestQueue_in, RequestMsg) {
519 if (((probe_filter_enabled || full_bit_dir_enabled) && (in_msg.Requestor == cache_entry.Owner)) || machineCount(MachineType:L1Cache) == 1) {
520 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
521 out_msg.addr := address;
522 out_msg.Type := CoherenceRequestType:BLOCK_ACK;
523 out_msg.Requestor := in_msg.Requestor;
524 out_msg.Destination.add(in_msg.Requestor);
525 out_msg.MessageSize := MessageSizeType:Writeback_Control;
526 }
527 }
528 }
529 }
530
531 action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") {
532 peek(requestQueue_in, RequestMsg) {
533 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
534 out_msg.addr := address;
535 out_msg.Type := CoherenceRequestType:WB_NACK;
536 out_msg.Requestor := in_msg.Requestor;
537 out_msg.Destination.add(in_msg.Requestor);
538 out_msg.MessageSize := MessageSizeType:Writeback_Control;
539 }
540 }
541 }
542
543 action(pfa_probeFilterAllocate, "pfa", desc="Allocate ProbeFilterEntry") {
544 if (probe_filter_enabled || full_bit_dir_enabled) {
545 peek(requestQueue_in, RequestMsg) {
546 set_cache_entry(probeFilter.allocate(address, new PfEntry));
547 cache_entry.Owner := in_msg.Requestor;
548 cache_entry.Sharers.setSize(machineCount(MachineType:L1Cache));
549 }
550 }
551 }
552
553 action(pfd_probeFilterDeallocate, "pfd", desc="Deallocate ProbeFilterEntry") {
554 if (probe_filter_enabled || full_bit_dir_enabled) {
555 probeFilter.deallocate(address);
556 unset_cache_entry();
557 }
558 }
559
560 action(ppfd_possibleProbeFilterDeallocate, "ppfd", desc="Deallocate ProbeFilterEntry") {
561 if ((probe_filter_enabled || full_bit_dir_enabled) && is_valid(cache_entry)) {
562 probeFilter.deallocate(address);
563 unset_cache_entry();
564 }
565 }
566
567 action(v_allocateTBE, "v", desc="Allocate TBE") {
568 check_allocate(TBEs);
569 peek(requestQueue_in, RequestMsg) {
570 TBEs.allocate(address);
571 set_tbe(TBEs[address]);
572 tbe.PhysicalAddress := address;
573 tbe.ResponseType := CoherenceResponseType:NULL;
574 }
575 }
576
577 action(vd_allocateDmaRequestInTBE, "vd", desc="Record Data in TBE") {
578 check_allocate(TBEs);
579 peek(dmaRequestQueue_in, DMARequestMsg) {
580 TBEs.allocate(address);
581 set_tbe(TBEs[address]);
582 tbe.DmaDataBlk := in_msg.DataBlk;
583 tbe.PhysicalAddress := in_msg.PhysicalAddress;
584 tbe.Len := in_msg.Len;
585 tbe.DmaRequestor := in_msg.Requestor;
586 tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
587 //
588 // One ack for each last-level cache
589 //
590 tbe.NumPendingMsgs := machineCount(MachineType:L1Cache);
591 //
592 // Assume initially that the caches store a clean copy and that memory
593 // will provide the data
594 //
595 tbe.CacheDirty := false;
596 }
597 }
598
599 action(pa_setPendingMsgsToAll, "pa", desc="set pending msgs to all") {
600 assert(is_valid(tbe));
601 if (full_bit_dir_enabled) {
602 assert(is_valid(cache_entry));
603 tbe.NumPendingMsgs := cache_entry.Sharers.count();
604 } else {
605 tbe.NumPendingMsgs := machineCount(MachineType:L1Cache);
606 }
607 }
608
609 action(po_setPendingMsgsToOne, "po", desc="set pending msgs to one") {
610 assert(is_valid(tbe));
611 tbe.NumPendingMsgs := 1;
612 }
613
614 action(w_deallocateTBE, "w", desc="Deallocate TBE") {
615 TBEs.deallocate(address);
616 unset_tbe();
617 }
618
619 action(sa_setAcksToOne, "sa", desc="Forwarded request, set the ack amount to one") {
620 assert(is_valid(tbe));
621 peek(requestQueue_in, RequestMsg) {
622 if (full_bit_dir_enabled) {
623 assert(is_valid(cache_entry));
624 //
625 // If we are using the full-bit directory and no sharers exists beyond
626 // the requestor, then we must set the ack number to all, not one
627 //
628 fwd_set := cache_entry.Sharers;
629 fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
630 if (fwd_set.count() > 0) {
631 tbe.Acks := 1;
632 tbe.SilentAcks := machineCount(MachineType:L1Cache) - fwd_set.count();
633 tbe.SilentAcks := tbe.SilentAcks - 1;
634 } else {
635 tbe.Acks := machineCount(MachineType:L1Cache);
636 tbe.SilentAcks := 0;
637 }
638 } else {
639 tbe.Acks := 1;
640 }
641 }
642 }
643
644 action(saa_setAcksToAllIfPF, "saa", desc="Non-forwarded request, set the ack amount to all") {
645 assert(is_valid(tbe));
646 if (probe_filter_enabled || full_bit_dir_enabled) {
647 tbe.Acks := machineCount(MachineType:L1Cache);
648 tbe.SilentAcks := 0;
649 } else {
650 tbe.Acks := 1;
651 }
652 }
653
654 action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") {
655 peek(responseToDir_in, ResponseMsg) {
656 assert(is_valid(tbe));
657 assert(in_msg.Acks > 0);
658 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
659 //
660 // Note that cache data responses will have an ack count of 2. However,
661 // directory DMA requests must wait for acks from all LLC caches, so
662 // only decrement by 1.
663 //
664 if ((in_msg.Type == CoherenceResponseType:DATA_SHARED) ||
665 (in_msg.Type == CoherenceResponseType:DATA) ||
666 (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE)) {
667 tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1;
668 } else {
669 tbe.NumPendingMsgs := tbe.NumPendingMsgs - in_msg.Acks;
670 }
671 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
672 }
673 }
674
675 action(mu_decrementNumberOfUnblocks, "mu", desc="Decrement the number of messages for which we're waiting") {
676 peek(unblockNetwork_in, ResponseMsg) {
677 assert(is_valid(tbe));
678 assert(in_msg.Type == CoherenceResponseType:UNBLOCKS);
679 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
680 tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1;
681 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
682 }
683 }
684
685 action(n_popResponseQueue, "n", desc="Pop response queue") {
686 responseToDir_in.dequeue(clockEdge());
687 }
688
689 action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") {
690 assert(is_valid(tbe));
691 if (tbe.NumPendingMsgs == 0) {
692 enqueue(triggerQueue_out, TriggerMsg) {
693 out_msg.addr := address;
694 if (tbe.Sharers) {
695 if (tbe.Owned) {
696 out_msg.Type := TriggerType:ALL_ACKS_OWNER_EXISTS;
697 } else {
698 out_msg.Type := TriggerType:ALL_ACKS;
699 }
700 } else {
701 out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS;
702 }
703 }
704 }
705 }
706
707 action(os_checkForMergedGetSCompletion, "os", desc="Check for merged GETS completion") {
708 assert(is_valid(tbe));
709 if (tbe.NumPendingMsgs == 0) {
710 enqueue(triggerQueue_out, TriggerMsg) {
711 out_msg.addr := address;
712 out_msg.Type := TriggerType:ALL_UNBLOCKS;
713 }
714 }
715 }
716
717 action(sp_setPendingMsgsToMergedSharers, "sp", desc="Set pending messages to waiting sharers") {
718 assert(is_valid(tbe));
719 tbe.NumPendingMsgs := tbe.GetSRequestors.count();
720 }
721
722 action(spa_setPendingAcksToZeroIfPF, "spa", desc="if probe filter, no need to wait for acks") {
723 if (probe_filter_enabled || full_bit_dir_enabled) {
724 assert(is_valid(tbe));
725 tbe.NumPendingMsgs := 0;
726 }
727 }
728
729 action(sc_signalCompletionIfPF, "sc", desc="indicate that we should skip waiting for cpu acks") {
730 assert(is_valid(tbe));
731 if (tbe.NumPendingMsgs == 0) {
732 assert(probe_filter_enabled || full_bit_dir_enabled);
733 enqueue(triggerQueue_out, TriggerMsg) {
734 out_msg.addr := address;
735 out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS;
736 }
737 }
738 }
739
740 action(d_sendData, "d", desc="Send data to requestor") {
741 peek(memQueue_in, MemoryMsg) {
742 enqueue(responseNetwork_out, ResponseMsg, 1) {
743 assert(is_valid(tbe));
744 out_msg.addr := address;
745 out_msg.Type := tbe.ResponseType;
746 out_msg.Sender := machineID;
747 out_msg.Destination.add(in_msg.OriginalRequestorMachId);
748 out_msg.DataBlk := in_msg.DataBlk;
749 DPRINTF(RubySlicc, "%s\n", out_msg.DataBlk);
750 out_msg.Dirty := false; // By definition, the block is now clean
751 out_msg.Acks := tbe.Acks;
752 out_msg.SilentAcks := tbe.SilentAcks;
753 DPRINTF(RubySlicc, "%d\n", out_msg.Acks);
754 assert(out_msg.Acks > 0);
755 out_msg.MessageSize := MessageSizeType:Response_Data;
756 }
757 }
758 }
759
760 action(dr_sendDmaData, "dr", desc="Send Data to DMA controller from memory") {
761 peek(memQueue_in, MemoryMsg) {
762 enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) {
763 assert(is_valid(tbe));
764 out_msg.PhysicalAddress := address;
765 out_msg.LineAddress := address;
766 out_msg.Type := DMAResponseType:DATA;
767 //
768 // we send the entire data block and rely on the dma controller to
769 // split it up if need be
770 //
771 out_msg.DataBlk := in_msg.DataBlk;
772 out_msg.Destination.add(tbe.DmaRequestor);
773 out_msg.MessageSize := MessageSizeType:Response_Data;
774 }
775 }
776 }
777
778 action(dt_sendDmaDataFromTbe, "dt", desc="Send Data to DMA controller from tbe") {
779 peek(triggerQueue_in, TriggerMsg) {
780 enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) {
781 assert(is_valid(tbe));
782 out_msg.PhysicalAddress := address;
783 out_msg.LineAddress := address;
784 out_msg.Type := DMAResponseType:DATA;
785 //
786 // we send the entire data block and rely on the dma controller to
787 // split it up if need be
788 //
789 out_msg.DataBlk := tbe.DataBlk;
790 out_msg.Destination.add(tbe.DmaRequestor);
791 out_msg.MessageSize := MessageSizeType:Response_Data;
792 }
793 }
794 }
795
796 action(da_sendDmaAck, "da", desc="Send Ack to DMA controller") {
797 enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) {
798 assert(is_valid(tbe));
799 out_msg.PhysicalAddress := address;
800 out_msg.LineAddress := address;
801 out_msg.Type := DMAResponseType:ACK;
802 out_msg.Destination.add(tbe.DmaRequestor);
803 out_msg.MessageSize := MessageSizeType:Writeback_Control;
804 }
805 }
806
807 action(rx_recordExclusiveInTBE, "rx", desc="Record Exclusive in TBE") {
808 peek(requestQueue_in, RequestMsg) {
809 assert(is_valid(tbe));
810 tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
811 }
812 }
813
814 action(r_recordDataInTBE, "rt", desc="Record Data in TBE") {
815 peek(requestQueue_in, RequestMsg) {
816 assert(is_valid(tbe));
817 if (full_bit_dir_enabled) {
818 fwd_set := cache_entry.Sharers;
819 fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
820 if (fwd_set.count() > 0) {
821 tbe.ResponseType := CoherenceResponseType:DATA;
822 } else {
823 tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
824 }
825 } else {
826 tbe.ResponseType := CoherenceResponseType:DATA;
827 }
828 }
829 }
830
831 action(rs_recordGetSRequestor, "rs", desc="Record GETS requestor in TBE") {
832 peek(requestQueue_in, RequestMsg) {
833 assert(is_valid(tbe));
834 tbe.GetSRequestors.add(in_msg.Requestor);
835 }
836 }
837
838 action(r_setSharerBit, "r", desc="We saw other sharers") {
839 assert(is_valid(tbe));
840 tbe.Sharers := true;
841 }
842
843 action(so_setOwnerBit, "so", desc="We saw other sharers") {
844 assert(is_valid(tbe));
845 tbe.Sharers := true;
846 tbe.Owned := true;
847 }
848
849 action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") {
850 peek(requestQueue_in, RequestMsg) {
851 queueMemoryRead(in_msg.Requestor, address, to_memory_controller_latency);
852 }
853 }
854
855 action(qd_queueMemoryRequestFromDmaRead, "qd", desc="Queue off-chip fetch request") {
856 peek(dmaRequestQueue_in, DMARequestMsg) {
857 queueMemoryRead(in_msg.Requestor, address, to_memory_controller_latency);
858 }
859 }
860
861 action(fn_forwardRequestIfNecessary, "fn", desc="Forward requests if necessary") {
862 assert(is_valid(tbe));
863 if ((machineCount(MachineType:L1Cache) > 1) && (tbe.Acks <= 1)) {
864 if (full_bit_dir_enabled) {
865 assert(is_valid(cache_entry));
866 peek(requestQueue_in, RequestMsg) {
867 fwd_set := cache_entry.Sharers;
868 fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
869 if (fwd_set.count() > 0) {
870 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
871 out_msg.addr := address;
872 out_msg.Type := in_msg.Type;
873 out_msg.Requestor := in_msg.Requestor;
874 out_msg.Destination.setNetDest(MachineType:L1Cache, fwd_set);
875 out_msg.MessageSize := MessageSizeType:Multicast_Control;
876 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
877 out_msg.ForwardRequestTime := curCycle();
878 assert(tbe.SilentAcks > 0);
879 out_msg.SilentAcks := tbe.SilentAcks;
880 }
881 }
882 }
883 } else {
884 peek(requestQueue_in, RequestMsg) {
885 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
886 out_msg.addr := address;
887 out_msg.Type := in_msg.Type;
888 out_msg.Requestor := in_msg.Requestor;
889 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
890 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
891 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
892 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
893 out_msg.ForwardRequestTime := curCycle();
894 }
895 }
896 }
897 }
898 }
899
900 action(ia_invalidateAllRequest, "ia", desc="invalidate all copies") {
901 if (machineCount(MachineType:L1Cache) > 1) {
902 if (full_bit_dir_enabled) {
903 assert(cache_entry.Sharers.count() > 0);
904 peek(requestQueue_in, RequestMsg) {
905 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
906 out_msg.addr := address;
907 out_msg.Type := CoherenceRequestType:INV;
908 out_msg.Requestor := machineID;
909 out_msg.Destination.setNetDest(MachineType:L1Cache, cache_entry.Sharers);
910 out_msg.MessageSize := MessageSizeType:Multicast_Control;
911 }
912 }
913 } else {
914 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
915 out_msg.addr := address;
916 out_msg.Type := CoherenceRequestType:INV;
917 out_msg.Requestor := machineID;
918 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
919 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
920 }
921 }
922 }
923 }
924
925 action(io_invalidateOwnerRequest, "io", desc="invalidate all copies") {
926 if (machineCount(MachineType:L1Cache) > 1) {
927 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
928 assert(is_valid(cache_entry));
929 out_msg.addr := address;
930 out_msg.Type := CoherenceRequestType:INV;
931 out_msg.Requestor := machineID;
932 out_msg.Destination.add(cache_entry.Owner);
933 out_msg.MessageSize := MessageSizeType:Request_Control;
934 out_msg.DirectedProbe := true;
935 }
936 }
937 }
938
939 action(fb_forwardRequestBcast, "fb", desc="Forward requests to all nodes") {
940 if (machineCount(MachineType:L1Cache) > 1) {
941 peek(requestQueue_in, RequestMsg) {
942 if (full_bit_dir_enabled) {
943 fwd_set := cache_entry.Sharers;
944 fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
945 if (fwd_set.count() > 0) {
946 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
947 out_msg.addr := address;
948 out_msg.Type := in_msg.Type;
949 out_msg.Requestor := in_msg.Requestor;
950 out_msg.Destination.setNetDest(MachineType:L1Cache, fwd_set);
951 out_msg.MessageSize := MessageSizeType:Multicast_Control;
952 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
953 out_msg.ForwardRequestTime := curCycle();
954 out_msg.SilentAcks := machineCount(MachineType:L1Cache) - fwd_set.count();
955 out_msg.SilentAcks := out_msg.SilentAcks - 1;
956 }
957 }
958 } else {
959 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
960 out_msg.addr := address;
961 out_msg.Type := in_msg.Type;
962 out_msg.Requestor := in_msg.Requestor;
963 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
964 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
965 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
966 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
967 out_msg.ForwardRequestTime := curCycle();
968 }
969 }
970 }
971 } else {
972 peek(requestQueue_in, RequestMsg) {
973 enqueue(responseNetwork_out, ResponseMsg, 1) {
974 out_msg.addr := address;
975 out_msg.Type := CoherenceResponseType:ACK;
976 out_msg.Sender := machineID;
977 out_msg.Destination.add(in_msg.Requestor);
978 out_msg.Dirty := false; // By definition, the block is now clean
979 out_msg.Acks := 0;
980 out_msg.SilentAcks := 0;
981 DPRINTF(RubySlicc, "%d\n", out_msg.Acks);
982 out_msg.MessageSize := MessageSizeType:Response_Control;
983 }
984 }
985 }
986 }
987
988 action(fr_forwardMergeReadRequestsToOwner, "frr", desc="Forward coalesced read request to owner") {
989 assert(machineCount(MachineType:L1Cache) > 1);
990 //
991 // Fixme! The unblock network should not stall on the forward network. Add a trigger queue to
992 // decouple the two.
993 //
994 peek(unblockNetwork_in, ResponseMsg) {
995 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
996 assert(is_valid(tbe));
997 out_msg.addr := address;
998 out_msg.Type := CoherenceRequestType:MERGED_GETS;
999 out_msg.MergedRequestors := tbe.GetSRequestors;
1000 if (in_msg.Type == CoherenceResponseType:UNBLOCKS) {
1001 out_msg.Destination.add(in_msg.CurOwner);
1002 } else {
1003 out_msg.Destination.add(in_msg.Sender);
1004 }
1005 out_msg.MessageSize := MessageSizeType:Request_Control;
1006 out_msg.InitialRequestTime := zero_time();
1007 out_msg.ForwardRequestTime := curCycle();
1008 }
1009 }
1010 }
1011
1012 action(fc_forwardRequestConditionalOwner, "fc", desc="Forward request to one or more nodes") {
1013 assert(machineCount(MachineType:L1Cache) > 1);
1014 if (probe_filter_enabled || full_bit_dir_enabled) {
1015 peek(requestQueue_in, RequestMsg) {
1016 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1017 assert(is_valid(cache_entry));
1018 out_msg.addr := address;
1019 out_msg.Type := in_msg.Type;
1020 out_msg.Requestor := in_msg.Requestor;
1021 out_msg.Destination.add(cache_entry.Owner);
1022 out_msg.MessageSize := MessageSizeType:Request_Control;
1023 out_msg.DirectedProbe := true;
1024 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1025 out_msg.ForwardRequestTime := curCycle();
1026 }
1027 }
1028 } else {
1029 peek(requestQueue_in, RequestMsg) {
1030 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1031 out_msg.addr := address;
1032 out_msg.Type := in_msg.Type;
1033 out_msg.Requestor := in_msg.Requestor;
1034 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
1035 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
1036 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1037 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1038 out_msg.ForwardRequestTime := curCycle();
1039 }
1040 }
1041 }
1042 }
1043
1044 action(nofc_forwardRequestConditionalOwner, "nofc", desc="Forward request to one or more nodes if the requestor is not the owner") {
1045 if (machineCount(MachineType:L1Cache) > 1) {
1046
1047 if (probe_filter_enabled || full_bit_dir_enabled) {
1048 peek(requestQueue_in, RequestMsg) {
1049 if (in_msg.Requestor != cache_entry.Owner) {
1050 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1051 assert(is_valid(cache_entry));
1052 out_msg.addr := address;
1053 out_msg.Type := in_msg.Type;
1054 out_msg.Requestor := in_msg.Requestor;
1055 out_msg.Destination.add(cache_entry.Owner);
1056 out_msg.MessageSize := MessageSizeType:Request_Control;
1057 out_msg.DirectedProbe := true;
1058 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1059 out_msg.ForwardRequestTime := curCycle();
1060 }
1061 }
1062 }
1063 } else {
1064 peek(requestQueue_in, RequestMsg) {
1065 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1066 out_msg.addr := address;
1067 out_msg.Type := in_msg.Type;
1068 out_msg.Requestor := in_msg.Requestor;
1069 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
1070 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
1071 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1072 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1073 out_msg.ForwardRequestTime := curCycle();
1074 }
1075 }
1076 }
1077 }
1078 }
1079
1080 action(f_forwardWriteFromDma, "fw", desc="Forward requests") {
1081 assert(is_valid(tbe));
1082 if (tbe.NumPendingMsgs > 0) {
1083 peek(dmaRequestQueue_in, DMARequestMsg) {
1084 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1085 out_msg.addr := address;
1086 out_msg.Type := CoherenceRequestType:GETX;
1087 //
1088 // Send to all L1 caches, since the requestor is the memory controller
1089 // itself
1090 //
1091 out_msg.Requestor := machineID;
1092 out_msg.Destination.broadcast(MachineType:L1Cache);
1093 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1094 }
1095 }
1096 }
1097 }
1098
1099 action(f_forwardReadFromDma, "fr", desc="Forward requests") {
1100 assert(is_valid(tbe));
1101 if (tbe.NumPendingMsgs > 0) {
1102 peek(dmaRequestQueue_in, DMARequestMsg) {
1103 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1104 out_msg.addr := address;
1105 out_msg.Type := CoherenceRequestType:GETS;
1106 //
1107 // Send to all L1 caches, since the requestor is the memory controller
1108 // itself
1109 //
1110 out_msg.Requestor := machineID;
1111 out_msg.Destination.broadcast(MachineType:L1Cache);
1112 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1113 }
1114 }
1115 }
1116 }
1117
1118 action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") {
1119 requestQueue_in.dequeue(clockEdge());
1120 }
1121
1122 action(j_popIncomingUnblockQueue, "j", desc="Pop incoming unblock queue") {
1123 peek(unblockNetwork_in, ResponseMsg) {
1124 APPEND_TRANSITION_COMMENT(in_msg.Sender);
1125 }
1126 unblockNetwork_in.dequeue(clockEdge());
1127 }
1128
1129 action(k_wakeUpDependents, "k", desc="wake-up dependents") {
1130 wakeUpBuffers(address);
1131 }
1132
1133 action(l_popMemQueue, "q", desc="Pop off-chip request queue") {
1134 memQueue_in.dequeue(clockEdge());
1135 }
1136
1137 action(g_popTriggerQueue, "g", desc="Pop trigger queue") {
1138 triggerQueue_in.dequeue(clockEdge());
1139 }
1140
1141 action(p_popDmaRequestQueue, "pd", desc="pop dma request queue") {
1142 dmaRequestQueue_in.dequeue(clockEdge());
1143 }
1144
1145 action(zd_stallAndWaitDMARequest, "zd", desc="Stall and wait the dma request queue") {
1146 peek(dmaRequestQueue_in, DMARequestMsg) {
1147 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1148 }
1149 stall_and_wait(dmaRequestQueue_in, address);
1150 }
1151
1152 action(r_recordMemoryData, "rd", desc="record data from memory to TBE") {
1153 peek(memQueue_in, MemoryMsg) {
1154 assert(is_valid(tbe));
1155 if (tbe.CacheDirty == false) {
1156 tbe.DataBlk := in_msg.DataBlk;
1157 }
1158 }
1159 }
1160
1161 action(r_recordCacheData, "rc", desc="record data from cache response to TBE") {
1162 peek(responseToDir_in, ResponseMsg) {
1163 assert(is_valid(tbe));
1164 tbe.CacheDirty := true;
1165 tbe.DataBlk := in_msg.DataBlk;
1166 }
1167 }
1168
1169 action(a_assertCacheData, "ac", desc="Assert that a cache provided the data") {
1170 assert(is_valid(tbe));
1171 assert(tbe.CacheDirty);
1172 }
1173
1174 action(ano_assertNotOwner, "ano", desc="Assert that request is not current owner") {
1175 if (probe_filter_enabled || full_bit_dir_enabled) {
1176 peek(requestQueue_in, RequestMsg) {
1177 assert(is_valid(cache_entry));
1178 assert(cache_entry.Owner != in_msg.Requestor);
1179 }
1180 }
1181 }
1182
1183 action(ans_assertNotSharer, "ans", desc="Assert that request is not a current sharer") {
1184 if (full_bit_dir_enabled) {
1185 peek(requestQueue_in, RequestMsg) {
1186 assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Requestor)) == false);
1187 }
1188 }
1189 }
1190
1191 action(rs_removeSharer, "s", desc="remove current sharer") {
1192 if (full_bit_dir_enabled) {
1193 peek(unblockNetwork_in, ResponseMsg) {
1194 assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Sender)));
1195 cache_entry.Sharers.remove(machineIDToNodeID(in_msg.Sender));
1196 }
1197 }
1198 }
1199
1200 action(cs_clearSharers, "cs", desc="clear current sharers") {
1201 if (full_bit_dir_enabled) {
1202 peek(requestQueue_in, RequestMsg) {
1203 cache_entry.Sharers.clear();
1204 cache_entry.Sharers.add(machineIDToNodeID(in_msg.Requestor));
1205 }
1206 }
1207 }
1208
1209 action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") {
1210 peek(unblockNetwork_in, ResponseMsg) {
1211 queueMemoryWrite(in_msg.Sender, address, to_memory_controller_latency,
1212 in_msg.DataBlk);
1213 }
1214 }
1215
1216 action(ld_queueMemoryDmaWrite, "ld", desc="Write DMA data to memory") {
1217 assert(is_valid(tbe));
1218 queueMemoryWritePartial(tbe.DmaRequestor, tbe.PhysicalAddress,
1219 to_memory_controller_latency, tbe.DmaDataBlk,
1220 tbe.Len);
1221 }
1222
1223 action(ly_queueMemoryWriteFromTBE, "ly", desc="Write data to memory from TBE") {
1224 queueMemoryWrite(machineID, address, to_memory_controller_latency,
1225 tbe.DataBlk);
1226 }
1227
1228 action(ll_checkIncomingWriteback, "\l", desc="Check PUTX/PUTO response message") {
1229 peek(unblockNetwork_in, ResponseMsg) {
1230 assert(in_msg.Dirty == false);
1231 assert(in_msg.MessageSize == MessageSizeType:Writeback_Control);
1232 DPRINTF(RubySlicc, "%s\n", in_msg.DataBlk);
1233 }
1234 }
1235
1236 action(z_stallAndWaitRequest, "z", desc="Recycle the request queue") {
1237 peek(requestQueue_in, RequestMsg) {
1238 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1239 }
1240 stall_and_wait(requestQueue_in, address);
1241 }
1242
1243 // TRANSITIONS
1244
1245 // Transitions out of E state
1246 transition(E, GETX, NO_B_W) {
1247 pfa_probeFilterAllocate;
1248 v_allocateTBE;
1249 rx_recordExclusiveInTBE;
1250 saa_setAcksToAllIfPF;
1251 qf_queueMemoryFetchRequest;
1252 fn_forwardRequestIfNecessary;
1253 i_popIncomingRequestQueue;
1254 }
1255
1256 transition(E, GETF, NO_F_W) {
1257 pfa_probeFilterAllocate;
1258 v_allocateTBE;
1259 rx_recordExclusiveInTBE;
1260 saa_setAcksToAllIfPF;
1261 qf_queueMemoryFetchRequest;
1262 fn_forwardRequestIfNecessary;
1263 i_popIncomingRequestQueue;
1264 }
1265
1266 transition(E, GETS, NO_B_W) {
1267 pfa_probeFilterAllocate;
1268 v_allocateTBE;
1269 rx_recordExclusiveInTBE;
1270 saa_setAcksToAllIfPF;
1271 qf_queueMemoryFetchRequest;
1272 fn_forwardRequestIfNecessary;
1273 i_popIncomingRequestQueue;
1274 }
1275
1276 transition(E, DMA_READ, NO_DR_B_W) {
1277 vd_allocateDmaRequestInTBE;
1278 qd_queueMemoryRequestFromDmaRead;
1279 spa_setPendingAcksToZeroIfPF;
1280 f_forwardReadFromDma;
1281 p_popDmaRequestQueue;
1282 }
1283
1284 transition(E, DMA_WRITE, NO_DW_B_W) {
1285 vd_allocateDmaRequestInTBE;
1286 spa_setPendingAcksToZeroIfPF;
1287 sc_signalCompletionIfPF;
1288 f_forwardWriteFromDma;
1289 p_popDmaRequestQueue;
1290 }
1291
1292 // Transitions out of O state
1293 transition(O, GETX, NO_B_W) {
1294 r_setMRU;
1295 v_allocateTBE;
1296 r_recordDataInTBE;
1297 sa_setAcksToOne;
1298 qf_queueMemoryFetchRequest;
1299 fb_forwardRequestBcast;
1300 cs_clearSharers;
1301 i_popIncomingRequestQueue;
1302 }
1303
1304 transition(O, GETF, NO_F_W) {
1305 r_setMRU;
1306 v_allocateTBE;
1307 r_recordDataInTBE;
1308 sa_setAcksToOne;
1309 qf_queueMemoryFetchRequest;
1310 fb_forwardRequestBcast;
1311 cs_clearSharers;
1312 i_popIncomingRequestQueue;
1313 }
1314
1315 // This transition is dumb, if a shared copy exists on-chip, then that should
1316 // provide data, not slow off-chip dram. The problem is that the current
1317 // caches don't provide data in S state
1318 transition(O, GETS, O_B_W) {
1319 r_setMRU;
1320 v_allocateTBE;
1321 r_recordDataInTBE;
1322 saa_setAcksToAllIfPF;
1323 qf_queueMemoryFetchRequest;
1324 fn_forwardRequestIfNecessary;
1325 i_popIncomingRequestQueue;
1326 }
1327
1328 transition(O, DMA_READ, O_DR_B_W) {
1329 vd_allocateDmaRequestInTBE;
1330 spa_setPendingAcksToZeroIfPF;
1331 qd_queueMemoryRequestFromDmaRead;
1332 f_forwardReadFromDma;
1333 p_popDmaRequestQueue;
1334 }
1335
1336 transition(O, Pf_Replacement, O_R) {
1337 v_allocateTBE;
1338 pa_setPendingMsgsToAll;
1339 ia_invalidateAllRequest;
1340 pfd_probeFilterDeallocate;
1341 }
1342
1343 transition(S, Pf_Replacement, S_R) {
1344 v_allocateTBE;
1345 pa_setPendingMsgsToAll;
1346 ia_invalidateAllRequest;
1347 pfd_probeFilterDeallocate;
1348 }
1349
1350 transition(NO, Pf_Replacement, NO_R) {
1351 v_allocateTBE;
1352 po_setPendingMsgsToOne;
1353 io_invalidateOwnerRequest;
1354 pfd_probeFilterDeallocate;
1355 }
1356
1357 transition(NX, Pf_Replacement, NO_R) {
1358 v_allocateTBE;
1359 pa_setPendingMsgsToAll;
1360 ia_invalidateAllRequest;
1361 pfd_probeFilterDeallocate;
1362 }
1363
1364 transition({O, S, NO, NX}, DMA_WRITE, NO_DW_B_W) {
1365 vd_allocateDmaRequestInTBE;
1366 f_forwardWriteFromDma;
1367 p_popDmaRequestQueue;
1368 }
1369
1370 // Transitions out of NO state
1371 transition(NX, GETX, NO_B) {
1372 r_setMRU;
1373 fb_forwardRequestBcast;
1374 cs_clearSharers;
1375 i_popIncomingRequestQueue;
1376 }
1377
1378 transition(NX, GETF, NO_F) {
1379 r_setMRU;
1380 fb_forwardRequestBcast;
1381 cs_clearSharers;
1382 i_popIncomingRequestQueue;
1383 }
1384
1385 // Transitions out of NO state
1386 transition(NO, GETX, NO_B) {
1387 r_setMRU;
1388 ano_assertNotOwner;
1389 fc_forwardRequestConditionalOwner;
1390 cs_clearSharers;
1391 i_popIncomingRequestQueue;
1392 }
1393
1394 transition(NO, GETF, NO_F) {
1395 r_setMRU;
1396 //ano_assertNotOwner;
1397 nofc_forwardRequestConditionalOwner; //forward request if the requester is not the owner
1398 cs_clearSharers;
1399 oc_sendBlockAck; // send ack if the owner
1400 i_popIncomingRequestQueue;
1401 }
1402
1403 transition(S, GETX, NO_B) {
1404 r_setMRU;
1405 fb_forwardRequestBcast;
1406 cs_clearSharers;
1407 i_popIncomingRequestQueue;
1408 }
1409
1410 transition(S, GETF, NO_F) {
1411 r_setMRU;
1412 fb_forwardRequestBcast;
1413 cs_clearSharers;
1414 i_popIncomingRequestQueue;
1415 }
1416
1417 transition(S, GETS, NO_B) {
1418 r_setMRU;
1419 ano_assertNotOwner;
1420 fb_forwardRequestBcast;
1421 i_popIncomingRequestQueue;
1422 }
1423
1424 transition(NO, GETS, NO_B) {
1425 r_setMRU;
1426 ano_assertNotOwner;
1427 ans_assertNotSharer;
1428 fc_forwardRequestConditionalOwner;
1429 i_popIncomingRequestQueue;
1430 }
1431
1432 transition(NX, GETS, NO_B) {
1433 r_setMRU;
1434 ano_assertNotOwner;
1435 fc_forwardRequestConditionalOwner;
1436 i_popIncomingRequestQueue;
1437 }
1438
1439 transition({NO, NX, S}, PUT, WB) {
1440 //
1441 // note that the PUT requestor may not be the current owner if an invalidate
1442 // raced with PUT
1443 //
1444 a_sendWriteBackAck;
1445 i_popIncomingRequestQueue;
1446 }
1447
1448 transition({NO, NX, S}, DMA_READ, NO_DR_B_D) {
1449 vd_allocateDmaRequestInTBE;
1450 f_forwardReadFromDma;
1451 p_popDmaRequestQueue;
1452 }
1453
1454 // Nack PUT requests when races cause us to believe we own the data
1455 transition({O, E}, PUT) {
1456 b_sendWriteBackNack;
1457 i_popIncomingRequestQueue;
1458 }
1459
1460 // Blocked transient states
1461 transition({NO_B_X, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D,
1462 NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, NO_B_S_W,
1463 NO_W, O_W, WB, WB_E_W, WB_O_W, O_R, S_R, NO_R, NO_F_W},
1464 {GETS, GETX, GETF, PUT, Pf_Replacement}) {
1465 z_stallAndWaitRequest;
1466 }
1467
1468 transition(NO_F, {GETS, GETX, GETF, PUT, Pf_Replacement}){
1469 z_stallAndWaitRequest;
1470 }
1471
1472 transition(NO_B, {GETX, GETF}, NO_B_X) {
1473 z_stallAndWaitRequest;
1474 }
1475
1476 transition(NO_B, {PUT, Pf_Replacement}) {
1477 z_stallAndWaitRequest;
1478 }
1479
1480 transition(NO_B_S, {GETX, GETF, PUT, Pf_Replacement}) {
1481 z_stallAndWaitRequest;
1482 }
1483
1484 transition({NO_B_X, NO_B, NO_B_S, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D,
1485 NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, NO_B_S_W,
1486 NO_W, O_W, WB, WB_E_W, WB_O_W, O_R, S_R, NO_R, NO_F_W},
1487 {DMA_READ, DMA_WRITE}) {
1488 zd_stallAndWaitDMARequest;
1489 }
1490
1491 // merge GETS into one response
1492 transition(NO_B, GETS, NO_B_S) {
1493 v_allocateTBE;
1494 rs_recordGetSRequestor;
1495 i_popIncomingRequestQueue;
1496 }
1497
1498 transition(NO_B_S, GETS) {
1499 rs_recordGetSRequestor;
1500 i_popIncomingRequestQueue;
1501 }
1502
1503 // unblock responses
1504 transition({NO_B, NO_B_X}, UnblockS, NX) {
1505 us_updateSharerIfFBD;
1506 k_wakeUpDependents;
1507 j_popIncomingUnblockQueue;
1508 }
1509
1510 transition({NO_B, NO_B_X}, UnblockM, NO) {
1511 uo_updateOwnerIfPf;
1512 us_updateSharerIfFBD;
1513 k_wakeUpDependents;
1514 j_popIncomingUnblockQueue;
1515 }
1516
1517 transition(NO_B_S, UnblockS, NO_B_S_W) {
1518 us_updateSharerIfFBD;
1519 fr_forwardMergeReadRequestsToOwner;
1520 sp_setPendingMsgsToMergedSharers;
1521 j_popIncomingUnblockQueue;
1522 }
1523
1524 transition(NO_B_S, UnblockM, NO_B_S_W) {
1525 uo_updateOwnerIfPf;
1526 fr_forwardMergeReadRequestsToOwner;
1527 sp_setPendingMsgsToMergedSharers;
1528 j_popIncomingUnblockQueue;
1529 }
1530
1531 transition(NO_B_S_W, UnblockS) {
1532 us_updateSharerIfFBD;
1533 mu_decrementNumberOfUnblocks;
1534 os_checkForMergedGetSCompletion;
1535 j_popIncomingUnblockQueue;
1536 }
1537
1538 transition(NO_B_S_W, All_Unblocks, NX) {
1539 w_deallocateTBE;
1540 k_wakeUpDependents;
1541 g_popTriggerQueue;
1542 }
1543
1544 transition(O_B, UnblockS, O) {
1545 us_updateSharerIfFBD;
1546 k_wakeUpDependents;
1547 j_popIncomingUnblockQueue;
1548 }
1549
1550 transition(O_B, UnblockM, NO) {
1551 us_updateSharerIfFBD;
1552 uo_updateOwnerIfPf;
1553 k_wakeUpDependents;
1554 j_popIncomingUnblockQueue;
1555 }
1556
1557 transition(NO_B_W, Memory_Data, NO_B) {
1558 d_sendData;
1559 w_deallocateTBE;
1560 l_popMemQueue;
1561 }
1562
1563 transition(NO_F_W, Memory_Data, NO_F) {
1564 d_sendData;
1565 w_deallocateTBE;
1566 l_popMemQueue;
1567 }
1568
1569 transition(NO_DR_B_W, Memory_Data, NO_DR_B) {
1570 r_recordMemoryData;
1571 o_checkForCompletion;
1572 l_popMemQueue;
1573 }
1574
1575 transition(O_DR_B_W, Memory_Data, O_DR_B) {
1576 r_recordMemoryData;
1577 dr_sendDmaData;
1578 o_checkForCompletion;
1579 l_popMemQueue;
1580 }
1581
1582 transition({NO_DR_B, O_DR_B, NO_DR_B_D, NO_DW_B_W}, Ack) {
1583 m_decrementNumberOfMessages;
1584 o_checkForCompletion;
1585 n_popResponseQueue;
1586 }
1587
1588 transition({O_R, S_R, NO_R}, Ack) {
1589 m_decrementNumberOfMessages;
1590 o_checkForCompletion;
1591 n_popResponseQueue;
1592 }
1593
1594 transition(S_R, Data) {
1595 m_decrementNumberOfMessages;
1596 o_checkForCompletion;
1597 n_popResponseQueue;
1598 }
1599
1600 transition(NO_R, {Data, Exclusive_Data}) {
1601 r_recordCacheData;
1602 m_decrementNumberOfMessages;
1603 o_checkForCompletion;
1604 n_popResponseQueue;
1605 }
1606
1607 transition({O_R, S_R}, All_acks_and_data_no_sharers, E) {
1608 w_deallocateTBE;
1609 k_wakeUpDependents;
1610 g_popTriggerQueue;
1611 }
1612
1613 transition(NO_R, All_acks_and_data_no_sharers, WB_E_W) {
1614 ly_queueMemoryWriteFromTBE;
1615 w_deallocateTBE;
1616 k_wakeUpDependents;
1617 g_popTriggerQueue;
1618 }
1619
1620 transition({NO_DR_B_W, O_DR_B_W}, Ack) {
1621 m_decrementNumberOfMessages;
1622 n_popResponseQueue;
1623 }
1624
1625 transition(NO_DR_B_W, Shared_Ack) {
1626 m_decrementNumberOfMessages;
1627 r_setSharerBit;
1628 n_popResponseQueue;
1629 }
1630
1631 transition(O_DR_B, Shared_Ack) {
1632 m_decrementNumberOfMessages;
1633 r_setSharerBit;
1634 o_checkForCompletion;
1635 n_popResponseQueue;
1636 }
1637
1638 transition(O_DR_B_W, Shared_Ack) {
1639 m_decrementNumberOfMessages;
1640 r_setSharerBit;
1641 n_popResponseQueue;
1642 }
1643
1644 transition({NO_DR_B, NO_DR_B_D}, Shared_Ack) {
1645 m_decrementNumberOfMessages;
1646 r_setSharerBit;
1647 o_checkForCompletion;
1648 n_popResponseQueue;
1649 }
1650
1651 transition(NO_DR_B_W, Shared_Data) {
1652 r_recordCacheData;
1653 m_decrementNumberOfMessages;
1654 so_setOwnerBit;
1655 o_checkForCompletion;
1656 n_popResponseQueue;
1657 }
1658
1659 transition({NO_DR_B, NO_DR_B_D}, Shared_Data) {
1660 r_recordCacheData;
1661 m_decrementNumberOfMessages;
1662 so_setOwnerBit;
1663 o_checkForCompletion;
1664 n_popResponseQueue;
1665 }
1666
1667 transition(NO_DR_B_W, {Exclusive_Data, Data}) {
1668 r_recordCacheData;
1669 m_decrementNumberOfMessages;
1670 n_popResponseQueue;
1671 }
1672
1673 transition({NO_DR_B, NO_DR_B_D, NO_DW_B_W}, {Exclusive_Data, Data}) {
1674 r_recordCacheData;
1675 m_decrementNumberOfMessages;
1676 o_checkForCompletion;
1677 n_popResponseQueue;
1678 }
1679
1680 transition(NO_DR_B, All_acks_and_owner_data, WB_O_W) {
1681 //
1682 // Note that the DMA consistency model allows us to send the DMA device
1683 // a response as soon as we receive valid data and prior to receiving
1684 // all acks. However, to simplify the protocol we wait for all acks.
1685 //
1686 dt_sendDmaDataFromTbe;
1687 ly_queueMemoryWriteFromTBE;
1688 w_deallocateTBE;
1689 k_wakeUpDependents;
1690 g_popTriggerQueue;
1691 }
1692
1693 transition(NO_DR_B, All_acks_and_shared_data, S) {
1694 //
1695 // Note that the DMA consistency model allows us to send the DMA device
1696 // a response as soon as we receive valid data and prior to receiving
1697 // all acks. However, to simplify the protocol we wait for all acks.
1698 //
1699 dt_sendDmaDataFromTbe;
1700 w_deallocateTBE;
1701 k_wakeUpDependents;
1702 g_popTriggerQueue;
1703 }
1704
1705 transition(NO_DR_B_D, All_acks_and_owner_data, WB_O_W) {
1706 //
1707 // Note that the DMA consistency model allows us to send the DMA device
1708 // a response as soon as we receive valid data and prior to receiving
1709 // all acks. However, to simplify the protocol we wait for all acks.
1710 //
1711 dt_sendDmaDataFromTbe;
1712 ly_queueMemoryWriteFromTBE;
1713 w_deallocateTBE;
1714 k_wakeUpDependents;
1715 g_popTriggerQueue;
1716 }
1717
1718 transition(NO_DR_B_D, All_acks_and_shared_data, S) {
1719 //
1720 // Note that the DMA consistency model allows us to send the DMA device
1721 // a response as soon as we receive valid data and prior to receiving
1722 // all acks. However, to simplify the protocol we wait for all acks.
1723 //
1724 dt_sendDmaDataFromTbe;
1725 w_deallocateTBE;
1726 k_wakeUpDependents;
1727 g_popTriggerQueue;
1728 }
1729
1730 transition(O_DR_B, All_acks_and_owner_data, WB_O_W) {
1731 ly_queueMemoryWriteFromTBE;
1732 w_deallocateTBE;
1733 k_wakeUpDependents;
1734 g_popTriggerQueue;
1735 }
1736
1737 transition(O_DR_B, All_acks_and_data_no_sharers, WB_E_W) {
1738 ly_queueMemoryWriteFromTBE;
1739 w_deallocateTBE;
1740 pfd_probeFilterDeallocate;
1741 k_wakeUpDependents;
1742 g_popTriggerQueue;
1743 }
1744
1745 transition(NO_DR_B, All_acks_and_data_no_sharers, WB_E_W) {
1746 //
1747 // Note that the DMA consistency model allows us to send the DMA device
1748 // a response as soon as we receive valid data and prior to receiving
1749 // all acks. However, to simplify the protocol we wait for all acks.
1750 //
1751 dt_sendDmaDataFromTbe;
1752 ly_queueMemoryWriteFromTBE;
1753 w_deallocateTBE;
1754 ppfd_possibleProbeFilterDeallocate;
1755 k_wakeUpDependents;
1756 g_popTriggerQueue;
1757 }
1758
1759 transition(NO_DR_B_D, All_acks_and_data_no_sharers, WB_E_W) {
1760 a_assertCacheData;
1761 //
1762 // Note that the DMA consistency model allows us to send the DMA device
1763 // a response as soon as we receive valid data and prior to receiving
1764 // all acks. However, to simplify the protocol we wait for all acks.
1765 //
1766 dt_sendDmaDataFromTbe;
1767 ly_queueMemoryWriteFromTBE;
1768 w_deallocateTBE;
1769 ppfd_possibleProbeFilterDeallocate;
1770 k_wakeUpDependents;
1771 g_popTriggerQueue;
1772 }
1773
1774 transition(NO_DW_B_W, All_acks_and_data_no_sharers, NO_DW_W) {
1775 ld_queueMemoryDmaWrite;
1776 g_popTriggerQueue;
1777 }
1778
1779 transition(NO_DW_W, Memory_Ack, E) {
1780 da_sendDmaAck;
1781 w_deallocateTBE;
1782 ppfd_possibleProbeFilterDeallocate;
1783 k_wakeUpDependents;
1784 l_popMemQueue;
1785 }
1786
1787 transition(O_B_W, Memory_Data, O_B) {
1788 d_sendData;
1789 w_deallocateTBE;
1790 l_popMemQueue;
1791 }
1792
1793 transition(NO_B_W, UnblockM, NO_W) {
1794 uo_updateOwnerIfPf;
1795 j_popIncomingUnblockQueue;
1796 }
1797
1798 transition(NO_B_W, UnblockS, NO_W) {
1799 us_updateSharerIfFBD;
1800 j_popIncomingUnblockQueue;
1801 }
1802
1803 transition(O_B_W, UnblockS, O_W) {
1804 us_updateSharerIfFBD;
1805 j_popIncomingUnblockQueue;
1806 }
1807
1808 transition(NO_W, Memory_Data, NO) {
1809 w_deallocateTBE;
1810 k_wakeUpDependents;
1811 l_popMemQueue;
1812 }
1813
1814 transition(O_W, Memory_Data, O) {
1815 w_deallocateTBE;
1816 k_wakeUpDependents;
1817 l_popMemQueue;
1818 }
1819
1820 // WB State Transistions
1821 transition(WB, Writeback_Dirty, WB_O_W) {
1822 rs_removeSharer;
1823 l_queueMemoryWBRequest;
1824 j_popIncomingUnblockQueue;
1825 }
1826
1827 transition(WB, Writeback_Exclusive_Dirty, WB_E_W) {
1828 rs_removeSharer;
1829 l_queueMemoryWBRequest;
1830 pfd_probeFilterDeallocate;
1831 j_popIncomingUnblockQueue;
1832 }
1833
1834 transition(WB_E_W, Memory_Ack, E) {
1835 k_wakeUpDependents;
1836 l_popMemQueue;
1837 }
1838
1839 transition(WB_O_W, Memory_Ack, O) {
1840 k_wakeUpDependents;
1841 l_popMemQueue;
1842 }
1843
1844 transition(WB, Writeback_Clean, O) {
1845 ll_checkIncomingWriteback;
1846 rs_removeSharer;
1847 k_wakeUpDependents;
1848 j_popIncomingUnblockQueue;
1849 }
1850
1851 transition(WB, Writeback_Exclusive_Clean, E) {
1852 ll_checkIncomingWriteback;
1853 rs_removeSharer;
1854 pfd_probeFilterDeallocate;
1855 k_wakeUpDependents;
1856 j_popIncomingUnblockQueue;
1857 }
1858
1859 transition(WB, Unblock, NX) {
1860 auno_assertUnblockerNotOwner;
1861 k_wakeUpDependents;
1862 j_popIncomingUnblockQueue;
1863 }
1864
1865 transition(NO_F, PUTF, WB) {
1866 a_sendWriteBackAck;
1867 i_popIncomingRequestQueue;
1868 }
1869
1870 //possible race between GETF and UnblockM -- not sure needed any more?
1871 transition(NO_F, UnblockM) {
1872 us_updateSharerIfFBD;
1873 uo_updateOwnerIfPf;
1874 j_popIncomingUnblockQueue;
1875 }
1876}
433 }
434 }
435 } else {
436 trigger(cache_request_to_event(in_msg.Type), in_msg.addr,
437 pf_entry, tbe);
438 }
439 }
440 }
441 }
442 }
443
444 in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir, rank=0) {
445 if (dmaRequestQueue_in.isReady(clockEdge())) {
446 peek(dmaRequestQueue_in, DMARequestMsg) {
447 PfEntry pf_entry := getProbeFilterEntry(in_msg.LineAddress);
448 TBE tbe := TBEs[in_msg.LineAddress];
449 if (in_msg.Type == DMARequestType:READ) {
450 trigger(Event:DMA_READ, in_msg.LineAddress, pf_entry, tbe);
451 } else if (in_msg.Type == DMARequestType:WRITE) {
452 trigger(Event:DMA_WRITE, in_msg.LineAddress, pf_entry, tbe);
453 } else {
454 error("Invalid message");
455 }
456 }
457 }
458 }
459
460 // Actions
461
462 action(r_setMRU, "\rr", desc="manually set the MRU bit for pf entry" ) {
463 if (probe_filter_enabled || full_bit_dir_enabled) {
464 assert(is_valid(cache_entry));
465 probeFilter.setMRU(address);
466 }
467 }
468
469 action(auno_assertUnblockerNotOwner, "auno", desc="assert unblocker not owner") {
470 if (probe_filter_enabled || full_bit_dir_enabled) {
471 assert(is_valid(cache_entry));
472 peek(unblockNetwork_in, ResponseMsg) {
473 assert(cache_entry.Owner != in_msg.Sender);
474 if (full_bit_dir_enabled) {
475 assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Sender)) == false);
476 }
477 }
478 }
479 }
480
481 action(uo_updateOwnerIfPf, "uo", desc="update owner") {
482 if (probe_filter_enabled || full_bit_dir_enabled) {
483 assert(is_valid(cache_entry));
484 peek(unblockNetwork_in, ResponseMsg) {
485 cache_entry.Owner := in_msg.Sender;
486 if (full_bit_dir_enabled) {
487 cache_entry.Sharers.clear();
488 cache_entry.Sharers.add(machineIDToNodeID(in_msg.Sender));
489 APPEND_TRANSITION_COMMENT(cache_entry.Sharers);
490 DPRINTF(RubySlicc, "Sharers = %d\n", cache_entry.Sharers);
491 }
492 }
493 }
494 }
495
496 action(us_updateSharerIfFBD, "us", desc="update sharer if full-bit directory") {
497 if (full_bit_dir_enabled) {
498 assert(probeFilter.isTagPresent(address));
499 peek(unblockNetwork_in, ResponseMsg) {
500 cache_entry.Sharers.add(machineIDToNodeID(in_msg.Sender));
501 }
502 }
503 }
504
505 action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") {
506 peek(requestQueue_in, RequestMsg) {
507 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
508 out_msg.addr := address;
509 out_msg.Type := CoherenceRequestType:WB_ACK;
510 out_msg.Requestor := in_msg.Requestor;
511 out_msg.Destination.add(in_msg.Requestor);
512 out_msg.MessageSize := MessageSizeType:Writeback_Control;
513 }
514 }
515 }
516
517 action(oc_sendBlockAck, "oc", desc="Send block ack to the owner") {
518 peek(requestQueue_in, RequestMsg) {
519 if (((probe_filter_enabled || full_bit_dir_enabled) && (in_msg.Requestor == cache_entry.Owner)) || machineCount(MachineType:L1Cache) == 1) {
520 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
521 out_msg.addr := address;
522 out_msg.Type := CoherenceRequestType:BLOCK_ACK;
523 out_msg.Requestor := in_msg.Requestor;
524 out_msg.Destination.add(in_msg.Requestor);
525 out_msg.MessageSize := MessageSizeType:Writeback_Control;
526 }
527 }
528 }
529 }
530
531 action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") {
532 peek(requestQueue_in, RequestMsg) {
533 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
534 out_msg.addr := address;
535 out_msg.Type := CoherenceRequestType:WB_NACK;
536 out_msg.Requestor := in_msg.Requestor;
537 out_msg.Destination.add(in_msg.Requestor);
538 out_msg.MessageSize := MessageSizeType:Writeback_Control;
539 }
540 }
541 }
542
543 action(pfa_probeFilterAllocate, "pfa", desc="Allocate ProbeFilterEntry") {
544 if (probe_filter_enabled || full_bit_dir_enabled) {
545 peek(requestQueue_in, RequestMsg) {
546 set_cache_entry(probeFilter.allocate(address, new PfEntry));
547 cache_entry.Owner := in_msg.Requestor;
548 cache_entry.Sharers.setSize(machineCount(MachineType:L1Cache));
549 }
550 }
551 }
552
553 action(pfd_probeFilterDeallocate, "pfd", desc="Deallocate ProbeFilterEntry") {
554 if (probe_filter_enabled || full_bit_dir_enabled) {
555 probeFilter.deallocate(address);
556 unset_cache_entry();
557 }
558 }
559
560 action(ppfd_possibleProbeFilterDeallocate, "ppfd", desc="Deallocate ProbeFilterEntry") {
561 if ((probe_filter_enabled || full_bit_dir_enabled) && is_valid(cache_entry)) {
562 probeFilter.deallocate(address);
563 unset_cache_entry();
564 }
565 }
566
567 action(v_allocateTBE, "v", desc="Allocate TBE") {
568 check_allocate(TBEs);
569 peek(requestQueue_in, RequestMsg) {
570 TBEs.allocate(address);
571 set_tbe(TBEs[address]);
572 tbe.PhysicalAddress := address;
573 tbe.ResponseType := CoherenceResponseType:NULL;
574 }
575 }
576
577 action(vd_allocateDmaRequestInTBE, "vd", desc="Record Data in TBE") {
578 check_allocate(TBEs);
579 peek(dmaRequestQueue_in, DMARequestMsg) {
580 TBEs.allocate(address);
581 set_tbe(TBEs[address]);
582 tbe.DmaDataBlk := in_msg.DataBlk;
583 tbe.PhysicalAddress := in_msg.PhysicalAddress;
584 tbe.Len := in_msg.Len;
585 tbe.DmaRequestor := in_msg.Requestor;
586 tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
587 //
588 // One ack for each last-level cache
589 //
590 tbe.NumPendingMsgs := machineCount(MachineType:L1Cache);
591 //
592 // Assume initially that the caches store a clean copy and that memory
593 // will provide the data
594 //
595 tbe.CacheDirty := false;
596 }
597 }
598
599 action(pa_setPendingMsgsToAll, "pa", desc="set pending msgs to all") {
600 assert(is_valid(tbe));
601 if (full_bit_dir_enabled) {
602 assert(is_valid(cache_entry));
603 tbe.NumPendingMsgs := cache_entry.Sharers.count();
604 } else {
605 tbe.NumPendingMsgs := machineCount(MachineType:L1Cache);
606 }
607 }
608
609 action(po_setPendingMsgsToOne, "po", desc="set pending msgs to one") {
610 assert(is_valid(tbe));
611 tbe.NumPendingMsgs := 1;
612 }
613
614 action(w_deallocateTBE, "w", desc="Deallocate TBE") {
615 TBEs.deallocate(address);
616 unset_tbe();
617 }
618
619 action(sa_setAcksToOne, "sa", desc="Forwarded request, set the ack amount to one") {
620 assert(is_valid(tbe));
621 peek(requestQueue_in, RequestMsg) {
622 if (full_bit_dir_enabled) {
623 assert(is_valid(cache_entry));
624 //
625 // If we are using the full-bit directory and no sharers exists beyond
626 // the requestor, then we must set the ack number to all, not one
627 //
628 fwd_set := cache_entry.Sharers;
629 fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
630 if (fwd_set.count() > 0) {
631 tbe.Acks := 1;
632 tbe.SilentAcks := machineCount(MachineType:L1Cache) - fwd_set.count();
633 tbe.SilentAcks := tbe.SilentAcks - 1;
634 } else {
635 tbe.Acks := machineCount(MachineType:L1Cache);
636 tbe.SilentAcks := 0;
637 }
638 } else {
639 tbe.Acks := 1;
640 }
641 }
642 }
643
644 action(saa_setAcksToAllIfPF, "saa", desc="Non-forwarded request, set the ack amount to all") {
645 assert(is_valid(tbe));
646 if (probe_filter_enabled || full_bit_dir_enabled) {
647 tbe.Acks := machineCount(MachineType:L1Cache);
648 tbe.SilentAcks := 0;
649 } else {
650 tbe.Acks := 1;
651 }
652 }
653
654 action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") {
655 peek(responseToDir_in, ResponseMsg) {
656 assert(is_valid(tbe));
657 assert(in_msg.Acks > 0);
658 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
659 //
660 // Note that cache data responses will have an ack count of 2. However,
661 // directory DMA requests must wait for acks from all LLC caches, so
662 // only decrement by 1.
663 //
664 if ((in_msg.Type == CoherenceResponseType:DATA_SHARED) ||
665 (in_msg.Type == CoherenceResponseType:DATA) ||
666 (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE)) {
667 tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1;
668 } else {
669 tbe.NumPendingMsgs := tbe.NumPendingMsgs - in_msg.Acks;
670 }
671 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
672 }
673 }
674
675 action(mu_decrementNumberOfUnblocks, "mu", desc="Decrement the number of messages for which we're waiting") {
676 peek(unblockNetwork_in, ResponseMsg) {
677 assert(is_valid(tbe));
678 assert(in_msg.Type == CoherenceResponseType:UNBLOCKS);
679 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
680 tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1;
681 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
682 }
683 }
684
685 action(n_popResponseQueue, "n", desc="Pop response queue") {
686 responseToDir_in.dequeue(clockEdge());
687 }
688
689 action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") {
690 assert(is_valid(tbe));
691 if (tbe.NumPendingMsgs == 0) {
692 enqueue(triggerQueue_out, TriggerMsg) {
693 out_msg.addr := address;
694 if (tbe.Sharers) {
695 if (tbe.Owned) {
696 out_msg.Type := TriggerType:ALL_ACKS_OWNER_EXISTS;
697 } else {
698 out_msg.Type := TriggerType:ALL_ACKS;
699 }
700 } else {
701 out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS;
702 }
703 }
704 }
705 }
706
707 action(os_checkForMergedGetSCompletion, "os", desc="Check for merged GETS completion") {
708 assert(is_valid(tbe));
709 if (tbe.NumPendingMsgs == 0) {
710 enqueue(triggerQueue_out, TriggerMsg) {
711 out_msg.addr := address;
712 out_msg.Type := TriggerType:ALL_UNBLOCKS;
713 }
714 }
715 }
716
717 action(sp_setPendingMsgsToMergedSharers, "sp", desc="Set pending messages to waiting sharers") {
718 assert(is_valid(tbe));
719 tbe.NumPendingMsgs := tbe.GetSRequestors.count();
720 }
721
722 action(spa_setPendingAcksToZeroIfPF, "spa", desc="if probe filter, no need to wait for acks") {
723 if (probe_filter_enabled || full_bit_dir_enabled) {
724 assert(is_valid(tbe));
725 tbe.NumPendingMsgs := 0;
726 }
727 }
728
729 action(sc_signalCompletionIfPF, "sc", desc="indicate that we should skip waiting for cpu acks") {
730 assert(is_valid(tbe));
731 if (tbe.NumPendingMsgs == 0) {
732 assert(probe_filter_enabled || full_bit_dir_enabled);
733 enqueue(triggerQueue_out, TriggerMsg) {
734 out_msg.addr := address;
735 out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS;
736 }
737 }
738 }
739
740 action(d_sendData, "d", desc="Send data to requestor") {
741 peek(memQueue_in, MemoryMsg) {
742 enqueue(responseNetwork_out, ResponseMsg, 1) {
743 assert(is_valid(tbe));
744 out_msg.addr := address;
745 out_msg.Type := tbe.ResponseType;
746 out_msg.Sender := machineID;
747 out_msg.Destination.add(in_msg.OriginalRequestorMachId);
748 out_msg.DataBlk := in_msg.DataBlk;
749 DPRINTF(RubySlicc, "%s\n", out_msg.DataBlk);
750 out_msg.Dirty := false; // By definition, the block is now clean
751 out_msg.Acks := tbe.Acks;
752 out_msg.SilentAcks := tbe.SilentAcks;
753 DPRINTF(RubySlicc, "%d\n", out_msg.Acks);
754 assert(out_msg.Acks > 0);
755 out_msg.MessageSize := MessageSizeType:Response_Data;
756 }
757 }
758 }
759
760 action(dr_sendDmaData, "dr", desc="Send Data to DMA controller from memory") {
761 peek(memQueue_in, MemoryMsg) {
762 enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) {
763 assert(is_valid(tbe));
764 out_msg.PhysicalAddress := address;
765 out_msg.LineAddress := address;
766 out_msg.Type := DMAResponseType:DATA;
767 //
768 // we send the entire data block and rely on the dma controller to
769 // split it up if need be
770 //
771 out_msg.DataBlk := in_msg.DataBlk;
772 out_msg.Destination.add(tbe.DmaRequestor);
773 out_msg.MessageSize := MessageSizeType:Response_Data;
774 }
775 }
776 }
777
778 action(dt_sendDmaDataFromTbe, "dt", desc="Send Data to DMA controller from tbe") {
779 peek(triggerQueue_in, TriggerMsg) {
780 enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) {
781 assert(is_valid(tbe));
782 out_msg.PhysicalAddress := address;
783 out_msg.LineAddress := address;
784 out_msg.Type := DMAResponseType:DATA;
785 //
786 // we send the entire data block and rely on the dma controller to
787 // split it up if need be
788 //
789 out_msg.DataBlk := tbe.DataBlk;
790 out_msg.Destination.add(tbe.DmaRequestor);
791 out_msg.MessageSize := MessageSizeType:Response_Data;
792 }
793 }
794 }
795
796 action(da_sendDmaAck, "da", desc="Send Ack to DMA controller") {
797 enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) {
798 assert(is_valid(tbe));
799 out_msg.PhysicalAddress := address;
800 out_msg.LineAddress := address;
801 out_msg.Type := DMAResponseType:ACK;
802 out_msg.Destination.add(tbe.DmaRequestor);
803 out_msg.MessageSize := MessageSizeType:Writeback_Control;
804 }
805 }
806
807 action(rx_recordExclusiveInTBE, "rx", desc="Record Exclusive in TBE") {
808 peek(requestQueue_in, RequestMsg) {
809 assert(is_valid(tbe));
810 tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
811 }
812 }
813
814 action(r_recordDataInTBE, "rt", desc="Record Data in TBE") {
815 peek(requestQueue_in, RequestMsg) {
816 assert(is_valid(tbe));
817 if (full_bit_dir_enabled) {
818 fwd_set := cache_entry.Sharers;
819 fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
820 if (fwd_set.count() > 0) {
821 tbe.ResponseType := CoherenceResponseType:DATA;
822 } else {
823 tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
824 }
825 } else {
826 tbe.ResponseType := CoherenceResponseType:DATA;
827 }
828 }
829 }
830
831 action(rs_recordGetSRequestor, "rs", desc="Record GETS requestor in TBE") {
832 peek(requestQueue_in, RequestMsg) {
833 assert(is_valid(tbe));
834 tbe.GetSRequestors.add(in_msg.Requestor);
835 }
836 }
837
838 action(r_setSharerBit, "r", desc="We saw other sharers") {
839 assert(is_valid(tbe));
840 tbe.Sharers := true;
841 }
842
843 action(so_setOwnerBit, "so", desc="We saw other sharers") {
844 assert(is_valid(tbe));
845 tbe.Sharers := true;
846 tbe.Owned := true;
847 }
848
849 action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") {
850 peek(requestQueue_in, RequestMsg) {
851 queueMemoryRead(in_msg.Requestor, address, to_memory_controller_latency);
852 }
853 }
854
855 action(qd_queueMemoryRequestFromDmaRead, "qd", desc="Queue off-chip fetch request") {
856 peek(dmaRequestQueue_in, DMARequestMsg) {
857 queueMemoryRead(in_msg.Requestor, address, to_memory_controller_latency);
858 }
859 }
860
861 action(fn_forwardRequestIfNecessary, "fn", desc="Forward requests if necessary") {
862 assert(is_valid(tbe));
863 if ((machineCount(MachineType:L1Cache) > 1) && (tbe.Acks <= 1)) {
864 if (full_bit_dir_enabled) {
865 assert(is_valid(cache_entry));
866 peek(requestQueue_in, RequestMsg) {
867 fwd_set := cache_entry.Sharers;
868 fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
869 if (fwd_set.count() > 0) {
870 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
871 out_msg.addr := address;
872 out_msg.Type := in_msg.Type;
873 out_msg.Requestor := in_msg.Requestor;
874 out_msg.Destination.setNetDest(MachineType:L1Cache, fwd_set);
875 out_msg.MessageSize := MessageSizeType:Multicast_Control;
876 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
877 out_msg.ForwardRequestTime := curCycle();
878 assert(tbe.SilentAcks > 0);
879 out_msg.SilentAcks := tbe.SilentAcks;
880 }
881 }
882 }
883 } else {
884 peek(requestQueue_in, RequestMsg) {
885 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
886 out_msg.addr := address;
887 out_msg.Type := in_msg.Type;
888 out_msg.Requestor := in_msg.Requestor;
889 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
890 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
891 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
892 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
893 out_msg.ForwardRequestTime := curCycle();
894 }
895 }
896 }
897 }
898 }
899
900 action(ia_invalidateAllRequest, "ia", desc="invalidate all copies") {
901 if (machineCount(MachineType:L1Cache) > 1) {
902 if (full_bit_dir_enabled) {
903 assert(cache_entry.Sharers.count() > 0);
904 peek(requestQueue_in, RequestMsg) {
905 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
906 out_msg.addr := address;
907 out_msg.Type := CoherenceRequestType:INV;
908 out_msg.Requestor := machineID;
909 out_msg.Destination.setNetDest(MachineType:L1Cache, cache_entry.Sharers);
910 out_msg.MessageSize := MessageSizeType:Multicast_Control;
911 }
912 }
913 } else {
914 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
915 out_msg.addr := address;
916 out_msg.Type := CoherenceRequestType:INV;
917 out_msg.Requestor := machineID;
918 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
919 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
920 }
921 }
922 }
923 }
924
925 action(io_invalidateOwnerRequest, "io", desc="invalidate all copies") {
926 if (machineCount(MachineType:L1Cache) > 1) {
927 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
928 assert(is_valid(cache_entry));
929 out_msg.addr := address;
930 out_msg.Type := CoherenceRequestType:INV;
931 out_msg.Requestor := machineID;
932 out_msg.Destination.add(cache_entry.Owner);
933 out_msg.MessageSize := MessageSizeType:Request_Control;
934 out_msg.DirectedProbe := true;
935 }
936 }
937 }
938
939 action(fb_forwardRequestBcast, "fb", desc="Forward requests to all nodes") {
940 if (machineCount(MachineType:L1Cache) > 1) {
941 peek(requestQueue_in, RequestMsg) {
942 if (full_bit_dir_enabled) {
943 fwd_set := cache_entry.Sharers;
944 fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
945 if (fwd_set.count() > 0) {
946 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
947 out_msg.addr := address;
948 out_msg.Type := in_msg.Type;
949 out_msg.Requestor := in_msg.Requestor;
950 out_msg.Destination.setNetDest(MachineType:L1Cache, fwd_set);
951 out_msg.MessageSize := MessageSizeType:Multicast_Control;
952 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
953 out_msg.ForwardRequestTime := curCycle();
954 out_msg.SilentAcks := machineCount(MachineType:L1Cache) - fwd_set.count();
955 out_msg.SilentAcks := out_msg.SilentAcks - 1;
956 }
957 }
958 } else {
959 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
960 out_msg.addr := address;
961 out_msg.Type := in_msg.Type;
962 out_msg.Requestor := in_msg.Requestor;
963 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
964 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
965 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
966 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
967 out_msg.ForwardRequestTime := curCycle();
968 }
969 }
970 }
971 } else {
972 peek(requestQueue_in, RequestMsg) {
973 enqueue(responseNetwork_out, ResponseMsg, 1) {
974 out_msg.addr := address;
975 out_msg.Type := CoherenceResponseType:ACK;
976 out_msg.Sender := machineID;
977 out_msg.Destination.add(in_msg.Requestor);
978 out_msg.Dirty := false; // By definition, the block is now clean
979 out_msg.Acks := 0;
980 out_msg.SilentAcks := 0;
981 DPRINTF(RubySlicc, "%d\n", out_msg.Acks);
982 out_msg.MessageSize := MessageSizeType:Response_Control;
983 }
984 }
985 }
986 }
987
988 action(fr_forwardMergeReadRequestsToOwner, "frr", desc="Forward coalesced read request to owner") {
989 assert(machineCount(MachineType:L1Cache) > 1);
990 //
991 // Fixme! The unblock network should not stall on the forward network. Add a trigger queue to
992 // decouple the two.
993 //
994 peek(unblockNetwork_in, ResponseMsg) {
995 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
996 assert(is_valid(tbe));
997 out_msg.addr := address;
998 out_msg.Type := CoherenceRequestType:MERGED_GETS;
999 out_msg.MergedRequestors := tbe.GetSRequestors;
1000 if (in_msg.Type == CoherenceResponseType:UNBLOCKS) {
1001 out_msg.Destination.add(in_msg.CurOwner);
1002 } else {
1003 out_msg.Destination.add(in_msg.Sender);
1004 }
1005 out_msg.MessageSize := MessageSizeType:Request_Control;
1006 out_msg.InitialRequestTime := zero_time();
1007 out_msg.ForwardRequestTime := curCycle();
1008 }
1009 }
1010 }
1011
1012 action(fc_forwardRequestConditionalOwner, "fc", desc="Forward request to one or more nodes") {
1013 assert(machineCount(MachineType:L1Cache) > 1);
1014 if (probe_filter_enabled || full_bit_dir_enabled) {
1015 peek(requestQueue_in, RequestMsg) {
1016 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1017 assert(is_valid(cache_entry));
1018 out_msg.addr := address;
1019 out_msg.Type := in_msg.Type;
1020 out_msg.Requestor := in_msg.Requestor;
1021 out_msg.Destination.add(cache_entry.Owner);
1022 out_msg.MessageSize := MessageSizeType:Request_Control;
1023 out_msg.DirectedProbe := true;
1024 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1025 out_msg.ForwardRequestTime := curCycle();
1026 }
1027 }
1028 } else {
1029 peek(requestQueue_in, RequestMsg) {
1030 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1031 out_msg.addr := address;
1032 out_msg.Type := in_msg.Type;
1033 out_msg.Requestor := in_msg.Requestor;
1034 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
1035 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
1036 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1037 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1038 out_msg.ForwardRequestTime := curCycle();
1039 }
1040 }
1041 }
1042 }
1043
1044 action(nofc_forwardRequestConditionalOwner, "nofc", desc="Forward request to one or more nodes if the requestor is not the owner") {
1045 if (machineCount(MachineType:L1Cache) > 1) {
1046
1047 if (probe_filter_enabled || full_bit_dir_enabled) {
1048 peek(requestQueue_in, RequestMsg) {
1049 if (in_msg.Requestor != cache_entry.Owner) {
1050 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1051 assert(is_valid(cache_entry));
1052 out_msg.addr := address;
1053 out_msg.Type := in_msg.Type;
1054 out_msg.Requestor := in_msg.Requestor;
1055 out_msg.Destination.add(cache_entry.Owner);
1056 out_msg.MessageSize := MessageSizeType:Request_Control;
1057 out_msg.DirectedProbe := true;
1058 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1059 out_msg.ForwardRequestTime := curCycle();
1060 }
1061 }
1062 }
1063 } else {
1064 peek(requestQueue_in, RequestMsg) {
1065 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1066 out_msg.addr := address;
1067 out_msg.Type := in_msg.Type;
1068 out_msg.Requestor := in_msg.Requestor;
1069 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
1070 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
1071 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1072 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1073 out_msg.ForwardRequestTime := curCycle();
1074 }
1075 }
1076 }
1077 }
1078 }
1079
1080 action(f_forwardWriteFromDma, "fw", desc="Forward requests") {
1081 assert(is_valid(tbe));
1082 if (tbe.NumPendingMsgs > 0) {
1083 peek(dmaRequestQueue_in, DMARequestMsg) {
1084 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1085 out_msg.addr := address;
1086 out_msg.Type := CoherenceRequestType:GETX;
1087 //
1088 // Send to all L1 caches, since the requestor is the memory controller
1089 // itself
1090 //
1091 out_msg.Requestor := machineID;
1092 out_msg.Destination.broadcast(MachineType:L1Cache);
1093 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1094 }
1095 }
1096 }
1097 }
1098
1099 action(f_forwardReadFromDma, "fr", desc="Forward requests") {
1100 assert(is_valid(tbe));
1101 if (tbe.NumPendingMsgs > 0) {
1102 peek(dmaRequestQueue_in, DMARequestMsg) {
1103 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1104 out_msg.addr := address;
1105 out_msg.Type := CoherenceRequestType:GETS;
1106 //
1107 // Send to all L1 caches, since the requestor is the memory controller
1108 // itself
1109 //
1110 out_msg.Requestor := machineID;
1111 out_msg.Destination.broadcast(MachineType:L1Cache);
1112 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1113 }
1114 }
1115 }
1116 }
1117
1118 action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") {
1119 requestQueue_in.dequeue(clockEdge());
1120 }
1121
1122 action(j_popIncomingUnblockQueue, "j", desc="Pop incoming unblock queue") {
1123 peek(unblockNetwork_in, ResponseMsg) {
1124 APPEND_TRANSITION_COMMENT(in_msg.Sender);
1125 }
1126 unblockNetwork_in.dequeue(clockEdge());
1127 }
1128
1129 action(k_wakeUpDependents, "k", desc="wake-up dependents") {
1130 wakeUpBuffers(address);
1131 }
1132
1133 action(l_popMemQueue, "q", desc="Pop off-chip request queue") {
1134 memQueue_in.dequeue(clockEdge());
1135 }
1136
1137 action(g_popTriggerQueue, "g", desc="Pop trigger queue") {
1138 triggerQueue_in.dequeue(clockEdge());
1139 }
1140
1141 action(p_popDmaRequestQueue, "pd", desc="pop dma request queue") {
1142 dmaRequestQueue_in.dequeue(clockEdge());
1143 }
1144
1145 action(zd_stallAndWaitDMARequest, "zd", desc="Stall and wait the dma request queue") {
1146 peek(dmaRequestQueue_in, DMARequestMsg) {
1147 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1148 }
1149 stall_and_wait(dmaRequestQueue_in, address);
1150 }
1151
1152 action(r_recordMemoryData, "rd", desc="record data from memory to TBE") {
1153 peek(memQueue_in, MemoryMsg) {
1154 assert(is_valid(tbe));
1155 if (tbe.CacheDirty == false) {
1156 tbe.DataBlk := in_msg.DataBlk;
1157 }
1158 }
1159 }
1160
1161 action(r_recordCacheData, "rc", desc="record data from cache response to TBE") {
1162 peek(responseToDir_in, ResponseMsg) {
1163 assert(is_valid(tbe));
1164 tbe.CacheDirty := true;
1165 tbe.DataBlk := in_msg.DataBlk;
1166 }
1167 }
1168
1169 action(a_assertCacheData, "ac", desc="Assert that a cache provided the data") {
1170 assert(is_valid(tbe));
1171 assert(tbe.CacheDirty);
1172 }
1173
1174 action(ano_assertNotOwner, "ano", desc="Assert that request is not current owner") {
1175 if (probe_filter_enabled || full_bit_dir_enabled) {
1176 peek(requestQueue_in, RequestMsg) {
1177 assert(is_valid(cache_entry));
1178 assert(cache_entry.Owner != in_msg.Requestor);
1179 }
1180 }
1181 }
1182
1183 action(ans_assertNotSharer, "ans", desc="Assert that request is not a current sharer") {
1184 if (full_bit_dir_enabled) {
1185 peek(requestQueue_in, RequestMsg) {
1186 assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Requestor)) == false);
1187 }
1188 }
1189 }
1190
1191 action(rs_removeSharer, "s", desc="remove current sharer") {
1192 if (full_bit_dir_enabled) {
1193 peek(unblockNetwork_in, ResponseMsg) {
1194 assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Sender)));
1195 cache_entry.Sharers.remove(machineIDToNodeID(in_msg.Sender));
1196 }
1197 }
1198 }
1199
1200 action(cs_clearSharers, "cs", desc="clear current sharers") {
1201 if (full_bit_dir_enabled) {
1202 peek(requestQueue_in, RequestMsg) {
1203 cache_entry.Sharers.clear();
1204 cache_entry.Sharers.add(machineIDToNodeID(in_msg.Requestor));
1205 }
1206 }
1207 }
1208
1209 action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") {
1210 peek(unblockNetwork_in, ResponseMsg) {
1211 queueMemoryWrite(in_msg.Sender, address, to_memory_controller_latency,
1212 in_msg.DataBlk);
1213 }
1214 }
1215
1216 action(ld_queueMemoryDmaWrite, "ld", desc="Write DMA data to memory") {
1217 assert(is_valid(tbe));
1218 queueMemoryWritePartial(tbe.DmaRequestor, tbe.PhysicalAddress,
1219 to_memory_controller_latency, tbe.DmaDataBlk,
1220 tbe.Len);
1221 }
1222
1223 action(ly_queueMemoryWriteFromTBE, "ly", desc="Write data to memory from TBE") {
1224 queueMemoryWrite(machineID, address, to_memory_controller_latency,
1225 tbe.DataBlk);
1226 }
1227
1228 action(ll_checkIncomingWriteback, "\l", desc="Check PUTX/PUTO response message") {
1229 peek(unblockNetwork_in, ResponseMsg) {
1230 assert(in_msg.Dirty == false);
1231 assert(in_msg.MessageSize == MessageSizeType:Writeback_Control);
1232 DPRINTF(RubySlicc, "%s\n", in_msg.DataBlk);
1233 }
1234 }
1235
1236 action(z_stallAndWaitRequest, "z", desc="Recycle the request queue") {
1237 peek(requestQueue_in, RequestMsg) {
1238 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1239 }
1240 stall_and_wait(requestQueue_in, address);
1241 }
1242
1243 // TRANSITIONS
1244
1245 // Transitions out of E state
1246 transition(E, GETX, NO_B_W) {
1247 pfa_probeFilterAllocate;
1248 v_allocateTBE;
1249 rx_recordExclusiveInTBE;
1250 saa_setAcksToAllIfPF;
1251 qf_queueMemoryFetchRequest;
1252 fn_forwardRequestIfNecessary;
1253 i_popIncomingRequestQueue;
1254 }
1255
1256 transition(E, GETF, NO_F_W) {
1257 pfa_probeFilterAllocate;
1258 v_allocateTBE;
1259 rx_recordExclusiveInTBE;
1260 saa_setAcksToAllIfPF;
1261 qf_queueMemoryFetchRequest;
1262 fn_forwardRequestIfNecessary;
1263 i_popIncomingRequestQueue;
1264 }
1265
1266 transition(E, GETS, NO_B_W) {
1267 pfa_probeFilterAllocate;
1268 v_allocateTBE;
1269 rx_recordExclusiveInTBE;
1270 saa_setAcksToAllIfPF;
1271 qf_queueMemoryFetchRequest;
1272 fn_forwardRequestIfNecessary;
1273 i_popIncomingRequestQueue;
1274 }
1275
1276 transition(E, DMA_READ, NO_DR_B_W) {
1277 vd_allocateDmaRequestInTBE;
1278 qd_queueMemoryRequestFromDmaRead;
1279 spa_setPendingAcksToZeroIfPF;
1280 f_forwardReadFromDma;
1281 p_popDmaRequestQueue;
1282 }
1283
1284 transition(E, DMA_WRITE, NO_DW_B_W) {
1285 vd_allocateDmaRequestInTBE;
1286 spa_setPendingAcksToZeroIfPF;
1287 sc_signalCompletionIfPF;
1288 f_forwardWriteFromDma;
1289 p_popDmaRequestQueue;
1290 }
1291
1292 // Transitions out of O state
1293 transition(O, GETX, NO_B_W) {
1294 r_setMRU;
1295 v_allocateTBE;
1296 r_recordDataInTBE;
1297 sa_setAcksToOne;
1298 qf_queueMemoryFetchRequest;
1299 fb_forwardRequestBcast;
1300 cs_clearSharers;
1301 i_popIncomingRequestQueue;
1302 }
1303
1304 transition(O, GETF, NO_F_W) {
1305 r_setMRU;
1306 v_allocateTBE;
1307 r_recordDataInTBE;
1308 sa_setAcksToOne;
1309 qf_queueMemoryFetchRequest;
1310 fb_forwardRequestBcast;
1311 cs_clearSharers;
1312 i_popIncomingRequestQueue;
1313 }
1314
1315 // This transition is dumb, if a shared copy exists on-chip, then that should
1316 // provide data, not slow off-chip dram. The problem is that the current
1317 // caches don't provide data in S state
1318 transition(O, GETS, O_B_W) {
1319 r_setMRU;
1320 v_allocateTBE;
1321 r_recordDataInTBE;
1322 saa_setAcksToAllIfPF;
1323 qf_queueMemoryFetchRequest;
1324 fn_forwardRequestIfNecessary;
1325 i_popIncomingRequestQueue;
1326 }
1327
1328 transition(O, DMA_READ, O_DR_B_W) {
1329 vd_allocateDmaRequestInTBE;
1330 spa_setPendingAcksToZeroIfPF;
1331 qd_queueMemoryRequestFromDmaRead;
1332 f_forwardReadFromDma;
1333 p_popDmaRequestQueue;
1334 }
1335
1336 transition(O, Pf_Replacement, O_R) {
1337 v_allocateTBE;
1338 pa_setPendingMsgsToAll;
1339 ia_invalidateAllRequest;
1340 pfd_probeFilterDeallocate;
1341 }
1342
1343 transition(S, Pf_Replacement, S_R) {
1344 v_allocateTBE;
1345 pa_setPendingMsgsToAll;
1346 ia_invalidateAllRequest;
1347 pfd_probeFilterDeallocate;
1348 }
1349
1350 transition(NO, Pf_Replacement, NO_R) {
1351 v_allocateTBE;
1352 po_setPendingMsgsToOne;
1353 io_invalidateOwnerRequest;
1354 pfd_probeFilterDeallocate;
1355 }
1356
1357 transition(NX, Pf_Replacement, NO_R) {
1358 v_allocateTBE;
1359 pa_setPendingMsgsToAll;
1360 ia_invalidateAllRequest;
1361 pfd_probeFilterDeallocate;
1362 }
1363
1364 transition({O, S, NO, NX}, DMA_WRITE, NO_DW_B_W) {
1365 vd_allocateDmaRequestInTBE;
1366 f_forwardWriteFromDma;
1367 p_popDmaRequestQueue;
1368 }
1369
1370 // Transitions out of NO state
1371 transition(NX, GETX, NO_B) {
1372 r_setMRU;
1373 fb_forwardRequestBcast;
1374 cs_clearSharers;
1375 i_popIncomingRequestQueue;
1376 }
1377
1378 transition(NX, GETF, NO_F) {
1379 r_setMRU;
1380 fb_forwardRequestBcast;
1381 cs_clearSharers;
1382 i_popIncomingRequestQueue;
1383 }
1384
1385 // Transitions out of NO state
1386 transition(NO, GETX, NO_B) {
1387 r_setMRU;
1388 ano_assertNotOwner;
1389 fc_forwardRequestConditionalOwner;
1390 cs_clearSharers;
1391 i_popIncomingRequestQueue;
1392 }
1393
1394 transition(NO, GETF, NO_F) {
1395 r_setMRU;
1396 //ano_assertNotOwner;
1397 nofc_forwardRequestConditionalOwner; //forward request if the requester is not the owner
1398 cs_clearSharers;
1399 oc_sendBlockAck; // send ack if the owner
1400 i_popIncomingRequestQueue;
1401 }
1402
1403 transition(S, GETX, NO_B) {
1404 r_setMRU;
1405 fb_forwardRequestBcast;
1406 cs_clearSharers;
1407 i_popIncomingRequestQueue;
1408 }
1409
1410 transition(S, GETF, NO_F) {
1411 r_setMRU;
1412 fb_forwardRequestBcast;
1413 cs_clearSharers;
1414 i_popIncomingRequestQueue;
1415 }
1416
1417 transition(S, GETS, NO_B) {
1418 r_setMRU;
1419 ano_assertNotOwner;
1420 fb_forwardRequestBcast;
1421 i_popIncomingRequestQueue;
1422 }
1423
1424 transition(NO, GETS, NO_B) {
1425 r_setMRU;
1426 ano_assertNotOwner;
1427 ans_assertNotSharer;
1428 fc_forwardRequestConditionalOwner;
1429 i_popIncomingRequestQueue;
1430 }
1431
1432 transition(NX, GETS, NO_B) {
1433 r_setMRU;
1434 ano_assertNotOwner;
1435 fc_forwardRequestConditionalOwner;
1436 i_popIncomingRequestQueue;
1437 }
1438
1439 transition({NO, NX, S}, PUT, WB) {
1440 //
1441 // note that the PUT requestor may not be the current owner if an invalidate
1442 // raced with PUT
1443 //
1444 a_sendWriteBackAck;
1445 i_popIncomingRequestQueue;
1446 }
1447
1448 transition({NO, NX, S}, DMA_READ, NO_DR_B_D) {
1449 vd_allocateDmaRequestInTBE;
1450 f_forwardReadFromDma;
1451 p_popDmaRequestQueue;
1452 }
1453
1454 // Nack PUT requests when races cause us to believe we own the data
1455 transition({O, E}, PUT) {
1456 b_sendWriteBackNack;
1457 i_popIncomingRequestQueue;
1458 }
1459
1460 // Blocked transient states
1461 transition({NO_B_X, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D,
1462 NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, NO_B_S_W,
1463 NO_W, O_W, WB, WB_E_W, WB_O_W, O_R, S_R, NO_R, NO_F_W},
1464 {GETS, GETX, GETF, PUT, Pf_Replacement}) {
1465 z_stallAndWaitRequest;
1466 }
1467
1468 transition(NO_F, {GETS, GETX, GETF, PUT, Pf_Replacement}){
1469 z_stallAndWaitRequest;
1470 }
1471
1472 transition(NO_B, {GETX, GETF}, NO_B_X) {
1473 z_stallAndWaitRequest;
1474 }
1475
1476 transition(NO_B, {PUT, Pf_Replacement}) {
1477 z_stallAndWaitRequest;
1478 }
1479
1480 transition(NO_B_S, {GETX, GETF, PUT, Pf_Replacement}) {
1481 z_stallAndWaitRequest;
1482 }
1483
1484 transition({NO_B_X, NO_B, NO_B_S, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D,
1485 NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, NO_B_S_W,
1486 NO_W, O_W, WB, WB_E_W, WB_O_W, O_R, S_R, NO_R, NO_F_W},
1487 {DMA_READ, DMA_WRITE}) {
1488 zd_stallAndWaitDMARequest;
1489 }
1490
1491 // merge GETS into one response
1492 transition(NO_B, GETS, NO_B_S) {
1493 v_allocateTBE;
1494 rs_recordGetSRequestor;
1495 i_popIncomingRequestQueue;
1496 }
1497
1498 transition(NO_B_S, GETS) {
1499 rs_recordGetSRequestor;
1500 i_popIncomingRequestQueue;
1501 }
1502
1503 // unblock responses
1504 transition({NO_B, NO_B_X}, UnblockS, NX) {
1505 us_updateSharerIfFBD;
1506 k_wakeUpDependents;
1507 j_popIncomingUnblockQueue;
1508 }
1509
1510 transition({NO_B, NO_B_X}, UnblockM, NO) {
1511 uo_updateOwnerIfPf;
1512 us_updateSharerIfFBD;
1513 k_wakeUpDependents;
1514 j_popIncomingUnblockQueue;
1515 }
1516
1517 transition(NO_B_S, UnblockS, NO_B_S_W) {
1518 us_updateSharerIfFBD;
1519 fr_forwardMergeReadRequestsToOwner;
1520 sp_setPendingMsgsToMergedSharers;
1521 j_popIncomingUnblockQueue;
1522 }
1523
1524 transition(NO_B_S, UnblockM, NO_B_S_W) {
1525 uo_updateOwnerIfPf;
1526 fr_forwardMergeReadRequestsToOwner;
1527 sp_setPendingMsgsToMergedSharers;
1528 j_popIncomingUnblockQueue;
1529 }
1530
1531 transition(NO_B_S_W, UnblockS) {
1532 us_updateSharerIfFBD;
1533 mu_decrementNumberOfUnblocks;
1534 os_checkForMergedGetSCompletion;
1535 j_popIncomingUnblockQueue;
1536 }
1537
1538 transition(NO_B_S_W, All_Unblocks, NX) {
1539 w_deallocateTBE;
1540 k_wakeUpDependents;
1541 g_popTriggerQueue;
1542 }
1543
1544 transition(O_B, UnblockS, O) {
1545 us_updateSharerIfFBD;
1546 k_wakeUpDependents;
1547 j_popIncomingUnblockQueue;
1548 }
1549
1550 transition(O_B, UnblockM, NO) {
1551 us_updateSharerIfFBD;
1552 uo_updateOwnerIfPf;
1553 k_wakeUpDependents;
1554 j_popIncomingUnblockQueue;
1555 }
1556
1557 transition(NO_B_W, Memory_Data, NO_B) {
1558 d_sendData;
1559 w_deallocateTBE;
1560 l_popMemQueue;
1561 }
1562
1563 transition(NO_F_W, Memory_Data, NO_F) {
1564 d_sendData;
1565 w_deallocateTBE;
1566 l_popMemQueue;
1567 }
1568
1569 transition(NO_DR_B_W, Memory_Data, NO_DR_B) {
1570 r_recordMemoryData;
1571 o_checkForCompletion;
1572 l_popMemQueue;
1573 }
1574
1575 transition(O_DR_B_W, Memory_Data, O_DR_B) {
1576 r_recordMemoryData;
1577 dr_sendDmaData;
1578 o_checkForCompletion;
1579 l_popMemQueue;
1580 }
1581
1582 transition({NO_DR_B, O_DR_B, NO_DR_B_D, NO_DW_B_W}, Ack) {
1583 m_decrementNumberOfMessages;
1584 o_checkForCompletion;
1585 n_popResponseQueue;
1586 }
1587
1588 transition({O_R, S_R, NO_R}, Ack) {
1589 m_decrementNumberOfMessages;
1590 o_checkForCompletion;
1591 n_popResponseQueue;
1592 }
1593
1594 transition(S_R, Data) {
1595 m_decrementNumberOfMessages;
1596 o_checkForCompletion;
1597 n_popResponseQueue;
1598 }
1599
1600 transition(NO_R, {Data, Exclusive_Data}) {
1601 r_recordCacheData;
1602 m_decrementNumberOfMessages;
1603 o_checkForCompletion;
1604 n_popResponseQueue;
1605 }
1606
1607 transition({O_R, S_R}, All_acks_and_data_no_sharers, E) {
1608 w_deallocateTBE;
1609 k_wakeUpDependents;
1610 g_popTriggerQueue;
1611 }
1612
1613 transition(NO_R, All_acks_and_data_no_sharers, WB_E_W) {
1614 ly_queueMemoryWriteFromTBE;
1615 w_deallocateTBE;
1616 k_wakeUpDependents;
1617 g_popTriggerQueue;
1618 }
1619
1620 transition({NO_DR_B_W, O_DR_B_W}, Ack) {
1621 m_decrementNumberOfMessages;
1622 n_popResponseQueue;
1623 }
1624
1625 transition(NO_DR_B_W, Shared_Ack) {
1626 m_decrementNumberOfMessages;
1627 r_setSharerBit;
1628 n_popResponseQueue;
1629 }
1630
1631 transition(O_DR_B, Shared_Ack) {
1632 m_decrementNumberOfMessages;
1633 r_setSharerBit;
1634 o_checkForCompletion;
1635 n_popResponseQueue;
1636 }
1637
1638 transition(O_DR_B_W, Shared_Ack) {
1639 m_decrementNumberOfMessages;
1640 r_setSharerBit;
1641 n_popResponseQueue;
1642 }
1643
1644 transition({NO_DR_B, NO_DR_B_D}, Shared_Ack) {
1645 m_decrementNumberOfMessages;
1646 r_setSharerBit;
1647 o_checkForCompletion;
1648 n_popResponseQueue;
1649 }
1650
1651 transition(NO_DR_B_W, Shared_Data) {
1652 r_recordCacheData;
1653 m_decrementNumberOfMessages;
1654 so_setOwnerBit;
1655 o_checkForCompletion;
1656 n_popResponseQueue;
1657 }
1658
1659 transition({NO_DR_B, NO_DR_B_D}, Shared_Data) {
1660 r_recordCacheData;
1661 m_decrementNumberOfMessages;
1662 so_setOwnerBit;
1663 o_checkForCompletion;
1664 n_popResponseQueue;
1665 }
1666
1667 transition(NO_DR_B_W, {Exclusive_Data, Data}) {
1668 r_recordCacheData;
1669 m_decrementNumberOfMessages;
1670 n_popResponseQueue;
1671 }
1672
1673 transition({NO_DR_B, NO_DR_B_D, NO_DW_B_W}, {Exclusive_Data, Data}) {
1674 r_recordCacheData;
1675 m_decrementNumberOfMessages;
1676 o_checkForCompletion;
1677 n_popResponseQueue;
1678 }
1679
1680 transition(NO_DR_B, All_acks_and_owner_data, WB_O_W) {
1681 //
1682 // Note that the DMA consistency model allows us to send the DMA device
1683 // a response as soon as we receive valid data and prior to receiving
1684 // all acks. However, to simplify the protocol we wait for all acks.
1685 //
1686 dt_sendDmaDataFromTbe;
1687 ly_queueMemoryWriteFromTBE;
1688 w_deallocateTBE;
1689 k_wakeUpDependents;
1690 g_popTriggerQueue;
1691 }
1692
1693 transition(NO_DR_B, All_acks_and_shared_data, S) {
1694 //
1695 // Note that the DMA consistency model allows us to send the DMA device
1696 // a response as soon as we receive valid data and prior to receiving
1697 // all acks. However, to simplify the protocol we wait for all acks.
1698 //
1699 dt_sendDmaDataFromTbe;
1700 w_deallocateTBE;
1701 k_wakeUpDependents;
1702 g_popTriggerQueue;
1703 }
1704
1705 transition(NO_DR_B_D, All_acks_and_owner_data, WB_O_W) {
1706 //
1707 // Note that the DMA consistency model allows us to send the DMA device
1708 // a response as soon as we receive valid data and prior to receiving
1709 // all acks. However, to simplify the protocol we wait for all acks.
1710 //
1711 dt_sendDmaDataFromTbe;
1712 ly_queueMemoryWriteFromTBE;
1713 w_deallocateTBE;
1714 k_wakeUpDependents;
1715 g_popTriggerQueue;
1716 }
1717
1718 transition(NO_DR_B_D, All_acks_and_shared_data, S) {
1719 //
1720 // Note that the DMA consistency model allows us to send the DMA device
1721 // a response as soon as we receive valid data and prior to receiving
1722 // all acks. However, to simplify the protocol we wait for all acks.
1723 //
1724 dt_sendDmaDataFromTbe;
1725 w_deallocateTBE;
1726 k_wakeUpDependents;
1727 g_popTriggerQueue;
1728 }
1729
1730 transition(O_DR_B, All_acks_and_owner_data, WB_O_W) {
1731 ly_queueMemoryWriteFromTBE;
1732 w_deallocateTBE;
1733 k_wakeUpDependents;
1734 g_popTriggerQueue;
1735 }
1736
1737 transition(O_DR_B, All_acks_and_data_no_sharers, WB_E_W) {
1738 ly_queueMemoryWriteFromTBE;
1739 w_deallocateTBE;
1740 pfd_probeFilterDeallocate;
1741 k_wakeUpDependents;
1742 g_popTriggerQueue;
1743 }
1744
1745 transition(NO_DR_B, All_acks_and_data_no_sharers, WB_E_W) {
1746 //
1747 // Note that the DMA consistency model allows us to send the DMA device
1748 // a response as soon as we receive valid data and prior to receiving
1749 // all acks. However, to simplify the protocol we wait for all acks.
1750 //
1751 dt_sendDmaDataFromTbe;
1752 ly_queueMemoryWriteFromTBE;
1753 w_deallocateTBE;
1754 ppfd_possibleProbeFilterDeallocate;
1755 k_wakeUpDependents;
1756 g_popTriggerQueue;
1757 }
1758
1759 transition(NO_DR_B_D, All_acks_and_data_no_sharers, WB_E_W) {
1760 a_assertCacheData;
1761 //
1762 // Note that the DMA consistency model allows us to send the DMA device
1763 // a response as soon as we receive valid data and prior to receiving
1764 // all acks. However, to simplify the protocol we wait for all acks.
1765 //
1766 dt_sendDmaDataFromTbe;
1767 ly_queueMemoryWriteFromTBE;
1768 w_deallocateTBE;
1769 ppfd_possibleProbeFilterDeallocate;
1770 k_wakeUpDependents;
1771 g_popTriggerQueue;
1772 }
1773
1774 transition(NO_DW_B_W, All_acks_and_data_no_sharers, NO_DW_W) {
1775 ld_queueMemoryDmaWrite;
1776 g_popTriggerQueue;
1777 }
1778
1779 transition(NO_DW_W, Memory_Ack, E) {
1780 da_sendDmaAck;
1781 w_deallocateTBE;
1782 ppfd_possibleProbeFilterDeallocate;
1783 k_wakeUpDependents;
1784 l_popMemQueue;
1785 }
1786
1787 transition(O_B_W, Memory_Data, O_B) {
1788 d_sendData;
1789 w_deallocateTBE;
1790 l_popMemQueue;
1791 }
1792
1793 transition(NO_B_W, UnblockM, NO_W) {
1794 uo_updateOwnerIfPf;
1795 j_popIncomingUnblockQueue;
1796 }
1797
1798 transition(NO_B_W, UnblockS, NO_W) {
1799 us_updateSharerIfFBD;
1800 j_popIncomingUnblockQueue;
1801 }
1802
1803 transition(O_B_W, UnblockS, O_W) {
1804 us_updateSharerIfFBD;
1805 j_popIncomingUnblockQueue;
1806 }
1807
1808 transition(NO_W, Memory_Data, NO) {
1809 w_deallocateTBE;
1810 k_wakeUpDependents;
1811 l_popMemQueue;
1812 }
1813
1814 transition(O_W, Memory_Data, O) {
1815 w_deallocateTBE;
1816 k_wakeUpDependents;
1817 l_popMemQueue;
1818 }
1819
1820 // WB State Transistions
1821 transition(WB, Writeback_Dirty, WB_O_W) {
1822 rs_removeSharer;
1823 l_queueMemoryWBRequest;
1824 j_popIncomingUnblockQueue;
1825 }
1826
1827 transition(WB, Writeback_Exclusive_Dirty, WB_E_W) {
1828 rs_removeSharer;
1829 l_queueMemoryWBRequest;
1830 pfd_probeFilterDeallocate;
1831 j_popIncomingUnblockQueue;
1832 }
1833
1834 transition(WB_E_W, Memory_Ack, E) {
1835 k_wakeUpDependents;
1836 l_popMemQueue;
1837 }
1838
1839 transition(WB_O_W, Memory_Ack, O) {
1840 k_wakeUpDependents;
1841 l_popMemQueue;
1842 }
1843
1844 transition(WB, Writeback_Clean, O) {
1845 ll_checkIncomingWriteback;
1846 rs_removeSharer;
1847 k_wakeUpDependents;
1848 j_popIncomingUnblockQueue;
1849 }
1850
1851 transition(WB, Writeback_Exclusive_Clean, E) {
1852 ll_checkIncomingWriteback;
1853 rs_removeSharer;
1854 pfd_probeFilterDeallocate;
1855 k_wakeUpDependents;
1856 j_popIncomingUnblockQueue;
1857 }
1858
1859 transition(WB, Unblock, NX) {
1860 auno_assertUnblockerNotOwner;
1861 k_wakeUpDependents;
1862 j_popIncomingUnblockQueue;
1863 }
1864
1865 transition(NO_F, PUTF, WB) {
1866 a_sendWriteBackAck;
1867 i_popIncomingRequestQueue;
1868 }
1869
1870 //possible race between GETF and UnblockM -- not sure needed any more?
1871 transition(NO_F, UnblockM) {
1872 us_updateSharerIfFBD;
1873 uo_updateOwnerIfPf;
1874 j_popIncomingUnblockQueue;
1875 }
1876}