summaryrefslogtreecommitdiff
path: root/src/mem/protocol/MOESI_AMD_Base-dir.sm
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/protocol/MOESI_AMD_Base-dir.sm')
-rw-r--r--src/mem/protocol/MOESI_AMD_Base-dir.sm1137
1 files changed, 0 insertions, 1137 deletions
diff --git a/src/mem/protocol/MOESI_AMD_Base-dir.sm b/src/mem/protocol/MOESI_AMD_Base-dir.sm
deleted file mode 100644
index 4cde5ad03..000000000
--- a/src/mem/protocol/MOESI_AMD_Base-dir.sm
+++ /dev/null
@@ -1,1137 +0,0 @@
-/*
- * Copyright (c) 2010-2015 Advanced Micro Devices, Inc.
- * All rights reserved.
- *
- * For use for simulation and test purposes only
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Lisa Hsu
- */
-
-machine(MachineType:Directory, "AMD Baseline protocol")
-: DirectoryMemory * directory;
- CacheMemory * L3CacheMemory;
- Cycles response_latency := 5;
- Cycles l3_hit_latency := 50;
- bool noTCCdir := "False";
- bool CPUonly := "False";
- int TCC_select_num_bits;
- bool useL3OnWT := "False";
- Cycles to_memory_controller_latency := 1;
-
- // From the Cores
- MessageBuffer * requestFromCores, network="From", virtual_network="0", vnet_type="request";
- MessageBuffer * responseFromCores, network="From", virtual_network="2", vnet_type="response";
- MessageBuffer * unblockFromCores, network="From", virtual_network="4", vnet_type="unblock";
-
- MessageBuffer * probeToCore, network="To", virtual_network="0", vnet_type="request";
- MessageBuffer * responseToCore, network="To", virtual_network="2", vnet_type="response";
-
- MessageBuffer * triggerQueue;
- MessageBuffer * L3triggerQueue;
- MessageBuffer * responseFromMemory;
-{
- // STATES
- state_declaration(State, desc="Directory states", default="Directory_State_U") {
- U, AccessPermission:Backing_Store, desc="unblocked";
- BL, AccessPermission:Busy, desc="got L3 WB request";
- // BL is Busy because it's possible for the data only to be in the network
- // in the WB, L3 has sent it and gone on with its business in possibly I
- // state.
- BS_M, AccessPermission:Backing_Store, desc="blocked waiting for memory";
- BM_M, AccessPermission:Backing_Store, desc="blocked waiting for memory";
- B_M, AccessPermission:Backing_Store, desc="blocked waiting for memory";
- BP, AccessPermission:Backing_Store, desc="blocked waiting for probes, no need for memory";
- BS_PM, AccessPermission:Backing_Store, desc="blocked waiting for probes and Memory";
- BM_PM, AccessPermission:Backing_Store, desc="blocked waiting for probes and Memory";
- B_PM, AccessPermission:Backing_Store, desc="blocked waiting for probes and Memory";
- BS_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
- BM_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
- B_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
- B, AccessPermission:Backing_Store, desc="sent response, Blocked til ack";
- }
-
- // Events
- enumeration(Event, desc="Directory events") {
- // CPU requests
- RdBlkS, desc="...";
- RdBlkM, desc="...";
- RdBlk, desc="...";
- CtoD, desc="...";
- WriteThrough, desc="WriteThrough Message";
- Atomic, desc="Atomic Message";
-
- // writebacks
- VicDirty, desc="...";
- VicClean, desc="...";
- CPUData, desc="WB data from CPU";
- StaleWB, desc="Notification that WB has been superceded by a probe";
-
- // probe responses
- CPUPrbResp, desc="Probe Response Msg";
-
- ProbeAcksComplete, desc="Probe Acks Complete";
-
- L3Hit, desc="Hit in L3 return data to core";
-
- // Memory Controller
- MemData, desc="Fetched data from memory arrives";
- WBAck, desc="Writeback Ack from memory arrives";
-
- CoreUnblock, desc="Core received data, unblock";
- UnblockWriteThrough, desc="Unblock because of writethrough request finishing";
-
- StaleVicDirty, desc="Core invalidated before VicDirty processed";
- }
-
- enumeration(RequestType, desc="To communicate stats from transitions to recordStats") {
- L3DataArrayRead, desc="Read the data array";
- L3DataArrayWrite, desc="Write the data array";
- L3TagArrayRead, desc="Read the data array";
- L3TagArrayWrite, desc="Write the data array";
- }
-
- // TYPES
-
- // DirectoryEntry
- structure(Entry, desc="...", interface="AbstractEntry") {
- State DirectoryState, desc="Directory state";
- DataBlock DataBlk, desc="data for the block";
- NetDest VicDirtyIgnore, desc="VicDirty coming from whom to ignore";
- }
-
- structure(CacheEntry, desc="...", interface="AbstractCacheEntry") {
- DataBlock DataBlk, desc="data for the block";
- MachineID LastSender, desc="Mach which this block came from";
- }
-
- structure(TBE, desc="...") {
- State TBEState, desc="Transient state";
- DataBlock DataBlk, desc="data for the block";
- bool Dirty, desc="Is the data dirty?";
- int NumPendingAcks, desc="num acks expected";
- MachineID OriginalRequestor, desc="Original Requestor";
- MachineID WTRequestor, desc="WT Requestor";
- bool Cached, desc="data hit in Cache";
- bool MemData, desc="Got MemData?",default="false";
- bool wtData, desc="Got write through data?",default="false";
- bool atomicData, desc="Got Atomic op?",default="false";
- Cycles InitialRequestTime, desc="...";
- Cycles ForwardRequestTime, desc="...";
- Cycles ProbeRequestStartTime, desc="...";
- MachineID LastSender, desc="Mach which this block came from";
- bool L3Hit, default="false", desc="Was this an L3 hit?";
- uint64_t probe_id, desc="probe id for lifetime profiling";
- WriteMask writeMask, desc="outstanding write through mask";
- }
-
- structure(TBETable, external="yes") {
- TBE lookup(Addr);
- void allocate(Addr);
- void deallocate(Addr);
- bool isPresent(Addr);
- }
-
- TBETable TBEs, template="<Directory_TBE>", constructor="m_number_of_TBEs";
-
- int TCC_select_low_bit, default="RubySystem::getBlockSizeBits()";
-
- Tick clockEdge();
- Tick cyclesToTicks(Cycles c);
-
- void set_tbe(TBE a);
- void unset_tbe();
- void wakeUpAllBuffers();
- void wakeUpBuffers(Addr a);
- Cycles curCycle();
-
- Entry getDirectoryEntry(Addr addr), return_by_pointer="yes" {
- Entry dir_entry := static_cast(Entry, "pointer", directory.lookup(addr));
-
- if (is_valid(dir_entry)) {
- return dir_entry;
- }
-
- dir_entry := static_cast(Entry, "pointer",
- directory.allocate(addr, new Entry));
- return dir_entry;
- }
-
- DataBlock getDataBlock(Addr addr), return_by_ref="yes" {
- TBE tbe := TBEs.lookup(addr);
- if (is_valid(tbe) && tbe.MemData) {
- DPRINTF(RubySlicc, "Returning DataBlk from TBE %s:%s\n", addr, tbe);
- return tbe.DataBlk;
- }
- DPRINTF(RubySlicc, "Returning DataBlk from Dir %s:%s\n", addr, getDirectoryEntry(addr));
- return getDirectoryEntry(addr).DataBlk;
- }
-
- State getState(TBE tbe, CacheEntry entry, Addr addr) {
- return getDirectoryEntry(addr).DirectoryState;
- }
-
- void setState(TBE tbe, CacheEntry entry, Addr addr, State state) {
- getDirectoryEntry(addr).DirectoryState := state;
- }
-
- void functionalRead(Addr addr, Packet *pkt) {
- TBE tbe := TBEs.lookup(addr);
- if(is_valid(tbe)) {
- testAndRead(addr, tbe.DataBlk, pkt);
- } else {
- functionalMemoryRead(pkt);
- }
- }
-
- int functionalWrite(Addr addr, Packet *pkt) {
- int num_functional_writes := 0;
-
- TBE tbe := TBEs.lookup(addr);
- if(is_valid(tbe)) {
- num_functional_writes := num_functional_writes +
- testAndWrite(addr, tbe.DataBlk, pkt);
- }
-
- num_functional_writes := num_functional_writes
- + functionalMemoryWrite(pkt);
- return num_functional_writes;
- }
-
- AccessPermission getAccessPermission(Addr addr) {
- // For this Directory, all permissions are just tracked in Directory, since
- // it's not possible to have something in TBE but not Dir, just keep track
- // of state all in one place.
- if (directory.isPresent(addr)) {
- return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
- }
-
- return AccessPermission:NotPresent;
- }
-
- void setAccessPermission(CacheEntry entry, Addr addr, State state) {
- getDirectoryEntry(addr).changePermission(Directory_State_to_permission(state));
- }
-
- void recordRequestType(RequestType request_type, Addr addr) {
- if (request_type == RequestType:L3DataArrayRead) {
- L3CacheMemory.recordRequestType(CacheRequestType:DataArrayRead, addr);
- } else if (request_type == RequestType:L3DataArrayWrite) {
- L3CacheMemory.recordRequestType(CacheRequestType:DataArrayWrite, addr);
- } else if (request_type == RequestType:L3TagArrayRead) {
- L3CacheMemory.recordRequestType(CacheRequestType:TagArrayRead, addr);
- } else if (request_type == RequestType:L3TagArrayWrite) {
- L3CacheMemory.recordRequestType(CacheRequestType:TagArrayWrite, addr);
- }
- }
-
- bool checkResourceAvailable(RequestType request_type, Addr addr) {
- if (request_type == RequestType:L3DataArrayRead) {
- return L3CacheMemory.checkResourceAvailable(CacheResourceType:DataArray, addr);
- } else if (request_type == RequestType:L3DataArrayWrite) {
- return L3CacheMemory.checkResourceAvailable(CacheResourceType:DataArray, addr);
- } else if (request_type == RequestType:L3TagArrayRead) {
- return L3CacheMemory.checkResourceAvailable(CacheResourceType:TagArray, addr);
- } else if (request_type == RequestType:L3TagArrayWrite) {
- return L3CacheMemory.checkResourceAvailable(CacheResourceType:TagArray, addr);
- } else {
- error("Invalid RequestType type in checkResourceAvailable");
- return true;
- }
- }
-
- // ** OUT_PORTS **
- out_port(probeNetwork_out, NBProbeRequestMsg, probeToCore);
- out_port(responseNetwork_out, ResponseMsg, responseToCore);
-
- out_port(triggerQueue_out, TriggerMsg, triggerQueue);
- out_port(L3TriggerQueue_out, TriggerMsg, L3triggerQueue);
-
- // ** IN_PORTS **
-
- // Trigger Queue
- in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=5) {
- if (triggerQueue_in.isReady(clockEdge())) {
- peek(triggerQueue_in, TriggerMsg) {
- TBE tbe := TBEs.lookup(in_msg.addr);
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
- if (in_msg.Type == TriggerType:AcksComplete) {
- trigger(Event:ProbeAcksComplete, in_msg.addr, entry, tbe);
- }else if (in_msg.Type == TriggerType:UnblockWriteThrough) {
- trigger(Event:UnblockWriteThrough, in_msg.addr, entry, tbe);
- } else {
- error("Unknown trigger msg");
- }
- }
- }
- }
-
- in_port(L3TriggerQueue_in, TriggerMsg, L3triggerQueue, rank=4) {
- if (L3TriggerQueue_in.isReady(clockEdge())) {
- peek(L3TriggerQueue_in, TriggerMsg) {
- TBE tbe := TBEs.lookup(in_msg.addr);
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
- if (in_msg.Type == TriggerType:L3Hit) {
- trigger(Event:L3Hit, in_msg.addr, entry, tbe);
- } else {
- error("Unknown trigger msg");
- }
- }
- }
- }
-
- // Unblock Network
- in_port(unblockNetwork_in, UnblockMsg, unblockFromCores, rank=3) {
- if (unblockNetwork_in.isReady(clockEdge())) {
- peek(unblockNetwork_in, UnblockMsg) {
- TBE tbe := TBEs.lookup(in_msg.addr);
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
- trigger(Event:CoreUnblock, in_msg.addr, entry, tbe);
- }
- }
- }
-
- // Core response network
- in_port(responseNetwork_in, ResponseMsg, responseFromCores, rank=2) {
- if (responseNetwork_in.isReady(clockEdge())) {
- peek(responseNetwork_in, ResponseMsg) {
- TBE tbe := TBEs.lookup(in_msg.addr);
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
- if (in_msg.Type == CoherenceResponseType:CPUPrbResp) {
- trigger(Event:CPUPrbResp, in_msg.addr, entry, tbe);
- } else if (in_msg.Type == CoherenceResponseType:CPUData) {
- trigger(Event:CPUData, in_msg.addr, entry, tbe);
- } else if (in_msg.Type == CoherenceResponseType:StaleNotif) {
- trigger(Event:StaleWB, in_msg.addr, entry, tbe);
- } else {
- error("Unexpected response type");
- }
- }
- }
- }
-
- // off-chip memory request/response is done
- in_port(memQueue_in, MemoryMsg, responseFromMemory, rank=1) {
- if (memQueue_in.isReady(clockEdge())) {
- peek(memQueue_in, MemoryMsg) {
- TBE tbe := TBEs.lookup(in_msg.addr);
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
- if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
- trigger(Event:MemData, in_msg.addr, entry, tbe);
- DPRINTF(RubySlicc, "%s\n", in_msg);
- } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
- trigger(Event:WBAck, in_msg.addr, entry, tbe); // ignore WBAcks, don't care about them.
- } else {
- DPRINTF(RubySlicc, "%s\n", in_msg.Type);
- error("Invalid message");
- }
- }
- }
- }
-
- in_port(requestNetwork_in, CPURequestMsg, requestFromCores, rank=0) {
- if (requestNetwork_in.isReady(clockEdge())) {
- peek(requestNetwork_in, CPURequestMsg) {
- TBE tbe := TBEs.lookup(in_msg.addr);
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
- if (in_msg.Type == CoherenceRequestType:RdBlk) {
- trigger(Event:RdBlk, in_msg.addr, entry, tbe);
- } else if (in_msg.Type == CoherenceRequestType:RdBlkS) {
- trigger(Event:RdBlkS, in_msg.addr, entry, tbe);
- } else if (in_msg.Type == CoherenceRequestType:RdBlkM) {
- trigger(Event:RdBlkM, in_msg.addr, entry, tbe);
- } else if (in_msg.Type == CoherenceRequestType:WriteThrough) {
- trigger(Event:WriteThrough, in_msg.addr, entry, tbe);
- } else if (in_msg.Type == CoherenceRequestType:Atomic) {
- trigger(Event:Atomic, in_msg.addr, entry, tbe);
- } else if (in_msg.Type == CoherenceRequestType:VicDirty) {
- if (getDirectoryEntry(in_msg.addr).VicDirtyIgnore.isElement(in_msg.Requestor)) {
- DPRINTF(RubySlicc, "Dropping VicDirty for address %s\n", in_msg.addr);
- trigger(Event:StaleVicDirty, in_msg.addr, entry, tbe);
- } else {
- DPRINTF(RubySlicc, "Got VicDirty from %s on %s\n", in_msg.Requestor, in_msg.addr);
- trigger(Event:VicDirty, in_msg.addr, entry, tbe);
- }
- } else if (in_msg.Type == CoherenceRequestType:VicClean) {
- if (getDirectoryEntry(in_msg.addr).VicDirtyIgnore.isElement(in_msg.Requestor)) {
- DPRINTF(RubySlicc, "Dropping VicClean for address %s\n", in_msg.addr);
- trigger(Event:StaleVicDirty, in_msg.addr, entry, tbe);
- } else {
- DPRINTF(RubySlicc, "Got VicClean from %s on %s\n", in_msg.Requestor, in_msg.addr);
- trigger(Event:VicClean, in_msg.addr, entry, tbe);
- }
- } else {
- error("Bad request message type");
- }
- }
- }
- }
-
- // Actions
- action(s_sendResponseS, "s", desc="send Shared response") {
- enqueue(responseNetwork_out, ResponseMsg, response_latency) {
- out_msg.addr := address;
- out_msg.Type := CoherenceResponseType:NBSysResp;
- if (tbe.L3Hit) {
- out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
- } else {
- out_msg.Sender := machineID;
- }
- out_msg.Destination.add(tbe.OriginalRequestor);
- out_msg.DataBlk := tbe.DataBlk;
- out_msg.MessageSize := MessageSizeType:Response_Data;
- out_msg.Dirty := false;
- out_msg.State := CoherenceState:Shared;
- out_msg.InitialRequestTime := tbe.InitialRequestTime;
- out_msg.ForwardRequestTime := tbe.ForwardRequestTime;
- out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
- out_msg.OriginalResponder := tbe.LastSender;
- out_msg.L3Hit := tbe.L3Hit;
- DPRINTF(RubySlicc, "%s\n", out_msg);
- }
- }
-
- action(es_sendResponseES, "es", desc="send Exclusive or Shared response") {
- enqueue(responseNetwork_out, ResponseMsg, response_latency) {
- out_msg.addr := address;
- out_msg.Type := CoherenceResponseType:NBSysResp;
- if (tbe.L3Hit) {
- out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
- } else {
- out_msg.Sender := machineID;
- }
- out_msg.Destination.add(tbe.OriginalRequestor);
- out_msg.DataBlk := tbe.DataBlk;
- out_msg.MessageSize := MessageSizeType:Response_Data;
- out_msg.Dirty := tbe.Dirty;
- if (tbe.Cached) {
- out_msg.State := CoherenceState:Shared;
- } else {
- out_msg.State := CoherenceState:Exclusive;
- }
- out_msg.InitialRequestTime := tbe.InitialRequestTime;
- out_msg.ForwardRequestTime := tbe.ForwardRequestTime;
- out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
- out_msg.OriginalResponder := tbe.LastSender;
- out_msg.L3Hit := tbe.L3Hit;
- DPRINTF(RubySlicc, "%s\n", out_msg);
- }
- }
-
- action(m_sendResponseM, "m", desc="send Modified response") {
- if (tbe.wtData) {
- enqueue(triggerQueue_out, TriggerMsg, 1) {
- out_msg.addr := address;
- out_msg.Type := TriggerType:UnblockWriteThrough;
- }
- }else{
- enqueue(responseNetwork_out, ResponseMsg, response_latency) {
- out_msg.addr := address;
- out_msg.Type := CoherenceResponseType:NBSysResp;
- if (tbe.L3Hit) {
- out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
- } else {
- out_msg.Sender := machineID;
- }
- out_msg.Destination.add(tbe.OriginalRequestor);
- out_msg.DataBlk := tbe.DataBlk;
- out_msg.MessageSize := MessageSizeType:Response_Data;
- out_msg.Dirty := tbe.Dirty;
- out_msg.State := CoherenceState:Modified;
- out_msg.CtoD := false;
- out_msg.InitialRequestTime := tbe.InitialRequestTime;
- out_msg.ForwardRequestTime := tbe.ForwardRequestTime;
- out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
- out_msg.OriginalResponder := tbe.LastSender;
- if(tbe.atomicData){
- out_msg.WTRequestor := tbe.WTRequestor;
- }
- out_msg.L3Hit := tbe.L3Hit;
- DPRINTF(RubySlicc, "%s\n", out_msg);
- }
- if (tbe.atomicData) {
- enqueue(triggerQueue_out, TriggerMsg, 1) {
- out_msg.addr := address;
- out_msg.Type := TriggerType:UnblockWriteThrough;
- }
- }
- }
- }
-
- action(c_sendResponseCtoD, "c", desc="send CtoD Ack") {
- enqueue(responseNetwork_out, ResponseMsg, response_latency) {
- out_msg.addr := address;
- out_msg.Type := CoherenceResponseType:NBSysResp;
- out_msg.Sender := machineID;
- out_msg.Destination.add(tbe.OriginalRequestor);
- out_msg.MessageSize := MessageSizeType:Response_Control;
- out_msg.Dirty := false;
- out_msg.State := CoherenceState:Modified;
- out_msg.CtoD := true;
- out_msg.InitialRequestTime := tbe.InitialRequestTime;
- out_msg.ForwardRequestTime := curCycle();
- out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
- DPRINTF(RubySlicc, "%s\n", out_msg);
- }
- }
-
- action(w_sendResponseWBAck, "w", desc="send WB Ack") {
- peek(requestNetwork_in, CPURequestMsg) {
- enqueue(responseNetwork_out, ResponseMsg, 1) {
- out_msg.addr := address;
- out_msg.Type := CoherenceResponseType:NBSysWBAck;
- out_msg.Destination.add(in_msg.Requestor);
- out_msg.WTRequestor := in_msg.WTRequestor;
- out_msg.Sender := machineID;
- out_msg.MessageSize := MessageSizeType:Writeback_Control;
- out_msg.InitialRequestTime := in_msg.InitialRequestTime;
- out_msg.ForwardRequestTime := curCycle();
- out_msg.ProbeRequestStartTime := curCycle();
- }
- }
- }
-
- action(l_queueMemWBReq, "lq", desc="Write WB data to memory") {
- peek(responseNetwork_in, ResponseMsg) {
- queueMemoryWrite(machineID, address, to_memory_controller_latency,
- in_msg.DataBlk);
- }
- }
-
- action(l_queueMemRdReq, "lr", desc="Read data from memory") {
- peek(requestNetwork_in, CPURequestMsg) {
- if (L3CacheMemory.isTagPresent(address)) {
- enqueue(L3TriggerQueue_out, TriggerMsg, l3_hit_latency) {
- out_msg.addr := address;
- out_msg.Type := TriggerType:L3Hit;
- DPRINTF(RubySlicc, "%s\n", out_msg);
- }
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
- if (tbe.Dirty == false) {
- tbe.DataBlk := entry.DataBlk;
- }
- tbe.LastSender := entry.LastSender;
- tbe.L3Hit := true;
- tbe.MemData := true;
- L3CacheMemory.deallocate(address);
- } else {
- queueMemoryRead(machineID, address, to_memory_controller_latency);
- }
- }
- }
-
- action(dc_probeInvCoreData, "dc", desc="probe inv cores, return data") {
- peek(requestNetwork_in, CPURequestMsg) {
- enqueue(probeNetwork_out, NBProbeRequestMsg, response_latency) {
- out_msg.addr := address;
- out_msg.Type := ProbeRequestType:PrbInv;
- out_msg.ReturnData := true;
- out_msg.MessageSize := MessageSizeType:Control;
- out_msg.Destination.broadcast(MachineType:CorePair); // won't be realistic for multisocket
-
- // add relevant TCC node to list. This replaces all TCPs and SQCs
- if (((in_msg.Type == CoherenceRequestType:WriteThrough ||
- in_msg.Type == CoherenceRequestType:Atomic) &&
- in_msg.NoWriteConflict) ||
- CPUonly) {
- } else if (noTCCdir) {
- out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC,
- TCC_select_low_bit, TCC_select_num_bits));
- } else {
- out_msg.Destination.add(mapAddressToRange(address,
- MachineType:TCCdir,
- TCC_select_low_bit, TCC_select_num_bits));
- }
- out_msg.Destination.remove(in_msg.Requestor);
- tbe.NumPendingAcks := out_msg.Destination.count();
- if (tbe.NumPendingAcks == 0) {
- enqueue(triggerQueue_out, TriggerMsg, 1) {
- out_msg.addr := address;
- out_msg.Type := TriggerType:AcksComplete;
- }
- }
- DPRINTF(RubySlicc, "%s\n", out_msg);
- APPEND_TRANSITION_COMMENT(" dc: Acks remaining: ");
- APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
- tbe.ProbeRequestStartTime := curCycle();
- }
- }
- }
-
- action(sc_probeShrCoreData, "sc", desc="probe shared cores, return data") {
- peek(requestNetwork_in, CPURequestMsg) { // not the right network?
- enqueue(probeNetwork_out, NBProbeRequestMsg, response_latency) {
- out_msg.addr := address;
- out_msg.Type := ProbeRequestType:PrbDowngrade;
- out_msg.ReturnData := true;
- out_msg.MessageSize := MessageSizeType:Control;
- out_msg.Destination.broadcast(MachineType:CorePair); // won't be realistic for multisocket
- // add relevant TCC node to the list. This replaces all TCPs and SQCs
- if (noTCCdir || CPUonly) {
- //Don't need to notify TCC about reads
- } else {
- out_msg.Destination.add(mapAddressToRange(address,
- MachineType:TCCdir,
- TCC_select_low_bit, TCC_select_num_bits));
- tbe.NumPendingAcks := tbe.NumPendingAcks + 1;
- }
- if (noTCCdir && !CPUonly) {
- out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC,
- TCC_select_low_bit, TCC_select_num_bits));
- }
- out_msg.Destination.remove(in_msg.Requestor);
- tbe.NumPendingAcks := out_msg.Destination.count();
- if (tbe.NumPendingAcks == 0) {
- enqueue(triggerQueue_out, TriggerMsg, 1) {
- out_msg.addr := address;
- out_msg.Type := TriggerType:AcksComplete;
- }
- }
- DPRINTF(RubySlicc, "%s\n", (out_msg));
- APPEND_TRANSITION_COMMENT(" sc: Acks remaining: ");
- APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
- tbe.ProbeRequestStartTime := curCycle();
- }
- }
- }
-
- action(ic_probeInvCore, "ic", desc="probe invalidate core, no return data needed") {
- peek(requestNetwork_in, CPURequestMsg) { // not the right network?
- enqueue(probeNetwork_out, NBProbeRequestMsg, response_latency) {
- out_msg.addr := address;
- out_msg.Type := ProbeRequestType:PrbInv;
- out_msg.ReturnData := false;
- out_msg.MessageSize := MessageSizeType:Control;
- out_msg.Destination.broadcast(MachineType:CorePair); // won't be realistic for multisocket
-
- // add relevant TCC node to the list. This replaces all TCPs and SQCs
- if (noTCCdir && !CPUonly) {
- out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC,
- TCC_select_low_bit, TCC_select_num_bits));
- } else {
- if (!noTCCdir) {
- out_msg.Destination.add(mapAddressToRange(address,
- MachineType:TCCdir,
- TCC_select_low_bit,
- TCC_select_num_bits));
- }
- }
- out_msg.Destination.remove(in_msg.Requestor);
- tbe.NumPendingAcks := out_msg.Destination.count();
- if (tbe.NumPendingAcks == 0) {
- enqueue(triggerQueue_out, TriggerMsg, 1) {
- out_msg.addr := address;
- out_msg.Type := TriggerType:AcksComplete;
- }
- }
- APPEND_TRANSITION_COMMENT(" ic: Acks remaining: ");
- APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
- DPRINTF(RubySlicc, "%s\n", out_msg);
- tbe.ProbeRequestStartTime := curCycle();
- }
- }
- }
-
- action(d_writeDataToMemory, "d", desc="Write data to memory") {
- peek(responseNetwork_in, ResponseMsg) {
- getDirectoryEntry(address).DataBlk := in_msg.DataBlk;
- if (tbe.Dirty == false) {
- // have to update the TBE, too, because of how this
- // directory deals with functional writes
- tbe.DataBlk := in_msg.DataBlk;
- }
- }
- }
-
- action(t_allocateTBE, "t", desc="allocate TBE Entry") {
- check_allocate(TBEs);
- peek(requestNetwork_in, CPURequestMsg) {
- TBEs.allocate(address);
- set_tbe(TBEs.lookup(address));
- if (in_msg.Type == CoherenceRequestType:WriteThrough) {
- tbe.writeMask.clear();
- tbe.writeMask.orMask(in_msg.writeMask);
- tbe.wtData := true;
- tbe.WTRequestor := in_msg.WTRequestor;
- tbe.LastSender := in_msg.Requestor;
- }
- if (in_msg.Type == CoherenceRequestType:Atomic) {
- tbe.writeMask.clear();
- tbe.writeMask.orMask(in_msg.writeMask);
- tbe.atomicData := true;
- tbe.WTRequestor := in_msg.WTRequestor;
- tbe.LastSender := in_msg.Requestor;
- }
- tbe.DataBlk := getDirectoryEntry(address).DataBlk; // Data only for WBs
- tbe.Dirty := false;
- if (in_msg.Type == CoherenceRequestType:WriteThrough) {
- tbe.DataBlk.copyPartial(in_msg.DataBlk,in_msg.writeMask);
- tbe.Dirty := true;
- }
- tbe.OriginalRequestor := in_msg.Requestor;
- tbe.NumPendingAcks := 0;
- tbe.Cached := in_msg.ForceShared;
- tbe.InitialRequestTime := in_msg.InitialRequestTime;
- }
- }
-
- action(dt_deallocateTBE, "dt", desc="deallocate TBE Entry") {
- if (tbe.Dirty == false) {
- getDirectoryEntry(address).DataBlk := tbe.DataBlk;
- }
- TBEs.deallocate(address);
- unset_tbe();
- }
-
- action(wd_writeBackData, "wd", desc="Write back data if needed") {
- if (tbe.wtData) {
- getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, tbe.writeMask);
- } else if (tbe.atomicData) {
- tbe.DataBlk.atomicPartial(getDirectoryEntry(address).DataBlk,tbe.writeMask);
- getDirectoryEntry(address).DataBlk := tbe.DataBlk;
- } else if (tbe.Dirty == false) {
- getDirectoryEntry(address).DataBlk := tbe.DataBlk;
- }
- }
-
- action(mt_writeMemDataToTBE, "mt", desc="write Mem data to TBE") {
- peek(memQueue_in, MemoryMsg) {
- if (tbe.wtData == true) {
- // do nothing
- } else if (tbe.Dirty == false) {
- tbe.DataBlk := getDirectoryEntry(address).DataBlk;
- }
- tbe.MemData := true;
- }
- }
-
- action(y_writeProbeDataToTBE, "y", desc="write Probe Data to TBE") {
- peek(responseNetwork_in, ResponseMsg) {
- if (in_msg.Dirty) {
- if (tbe.wtData) {
- DataBlock tmp := in_msg.DataBlk;
- tmp.copyPartial(tbe.DataBlk,tbe.writeMask);
- tbe.DataBlk := tmp;
- tbe.writeMask.fillMask();
- } else if (tbe.Dirty) {
- if(tbe.atomicData == false && tbe.wtData == false) {
- DPRINTF(RubySlicc, "Got double data for %s from %s\n", address, in_msg.Sender);
- assert(tbe.DataBlk == in_msg.DataBlk); // in case of double data
- }
- } else {
- tbe.DataBlk := in_msg.DataBlk;
- tbe.Dirty := in_msg.Dirty;
- tbe.LastSender := in_msg.Sender;
- }
- }
- if (in_msg.Hit) {
- tbe.Cached := true;
- }
- }
- }
-
- action(mwc_markSinkWriteCancel, "mwc", desc="Mark to sink impending VicDirty") {
- peek(responseNetwork_in, ResponseMsg) {
- getDirectoryEntry(address).VicDirtyIgnore.add(in_msg.Sender);
- APPEND_TRANSITION_COMMENT(" setting bit to sink VicDirty ");
- }
- }
-
- action(x_decrementAcks, "x", desc="decrement Acks pending") {
- tbe.NumPendingAcks := tbe.NumPendingAcks - 1;
- APPEND_TRANSITION_COMMENT(" Acks remaining: ");
- APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
- }
-
- action(o_checkForCompletion, "o", desc="check for ack completion") {
- if (tbe.NumPendingAcks == 0) {
- enqueue(triggerQueue_out, TriggerMsg, 1) {
- out_msg.addr := address;
- out_msg.Type := TriggerType:AcksComplete;
- }
- }
- APPEND_TRANSITION_COMMENT(" Check: Acks remaining: ");
- APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
- }
-
- action(rv_removeVicDirtyIgnore, "rv", desc="Remove ignored core") {
- peek(requestNetwork_in, CPURequestMsg) {
- getDirectoryEntry(address).VicDirtyIgnore.remove(in_msg.Requestor);
- }
- }
-
- action(al_allocateL3Block, "al", desc="allocate the L3 block on WB") {
- peek(responseNetwork_in, ResponseMsg) {
- if (L3CacheMemory.isTagPresent(address)) {
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
- APPEND_TRANSITION_COMMENT(" al wrote data to L3 (hit) ");
- entry.DataBlk := in_msg.DataBlk;
- entry.LastSender := in_msg.Sender;
- } else {
- if (L3CacheMemory.cacheAvail(address) == false) {
- Addr victim := L3CacheMemory.cacheProbe(address);
- CacheEntry victim_entry := static_cast(CacheEntry, "pointer",
- L3CacheMemory.lookup(victim));
- queueMemoryWrite(machineID, victim, to_memory_controller_latency,
- victim_entry.DataBlk);
- L3CacheMemory.deallocate(victim);
- }
- assert(L3CacheMemory.cacheAvail(address));
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.allocate(address, new CacheEntry));
- APPEND_TRANSITION_COMMENT(" al wrote data to L3 ");
- entry.DataBlk := in_msg.DataBlk;
-
- entry.LastSender := in_msg.Sender;
- }
- }
- }
-
- action(alwt_allocateL3BlockOnWT, "alwt", desc="allocate the L3 block on WT") {
- if ((tbe.wtData || tbe.atomicData) && useL3OnWT) {
- if (L3CacheMemory.isTagPresent(address)) {
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
- APPEND_TRANSITION_COMMENT(" al wrote data to L3 (hit) ");
- entry.DataBlk := tbe.DataBlk;
- entry.LastSender := tbe.LastSender;
- } else {
- if (L3CacheMemory.cacheAvail(address) == false) {
- Addr victim := L3CacheMemory.cacheProbe(address);
- CacheEntry victim_entry := static_cast(CacheEntry, "pointer",
- L3CacheMemory.lookup(victim));
- queueMemoryWrite(machineID, victim, to_memory_controller_latency,
- victim_entry.DataBlk);
- L3CacheMemory.deallocate(victim);
- }
- assert(L3CacheMemory.cacheAvail(address));
- CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.allocate(address, new CacheEntry));
- APPEND_TRANSITION_COMMENT(" al wrote data to L3 ");
- entry.DataBlk := tbe.DataBlk;
- entry.LastSender := tbe.LastSender;
- }
- }
- }
-
- action(sf_setForwardReqTime, "sf", desc="...") {
- tbe.ForwardRequestTime := curCycle();
- }
-
- action(dl_deallocateL3, "dl", desc="deallocate the L3 block") {
- L3CacheMemory.deallocate(address);
- }
-
- action(p_popRequestQueue, "p", desc="pop request queue") {
- requestNetwork_in.dequeue(clockEdge());
- }
-
- action(pr_popResponseQueue, "pr", desc="pop response queue") {
- responseNetwork_in.dequeue(clockEdge());
- }
-
- action(pm_popMemQueue, "pm", desc="pop mem queue") {
- memQueue_in.dequeue(clockEdge());
- }
-
- action(pt_popTriggerQueue, "pt", desc="pop trigger queue") {
- triggerQueue_in.dequeue(clockEdge());
- }
-
- action(ptl_popTriggerQueue, "ptl", desc="pop L3 trigger queue") {
- L3TriggerQueue_in.dequeue(clockEdge());
- }
-
- action(pu_popUnblockQueue, "pu", desc="pop unblock queue") {
- unblockNetwork_in.dequeue(clockEdge());
- }
-
- action(zz_recycleRequestQueue, "zz", desc="recycle request queue") {
- requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
- }
-
- action(yy_recycleResponseQueue, "yy", desc="recycle response queue") {
- responseNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
- }
-
- action(st_stallAndWaitRequest, "st", desc="Stall and wait on the address") {
- stall_and_wait(requestNetwork_in, address);
- }
-
- action(wa_wakeUpDependents, "wa", desc="Wake up any requests waiting for this address") {
- wakeUpBuffers(address);
- }
-
- action(wa_wakeUpAllDependents, "waa", desc="Wake up any requests waiting for this region") {
- wakeUpAllBuffers();
- }
-
- action(z_stall, "z", desc="...") {
- }
-
- // TRANSITIONS
- transition({BL, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B}, {RdBlkS, RdBlkM, RdBlk, CtoD}) {
- st_stallAndWaitRequest;
- }
-
- // It may be possible to save multiple invalidations here!
- transition({BL, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B}, {Atomic, WriteThrough}) {
- st_stallAndWaitRequest;
- }
-
-
- // transitions from U
- transition(U, {RdBlkS}, BS_PM) {L3TagArrayRead} {
- t_allocateTBE;
- l_queueMemRdReq;
- sc_probeShrCoreData;
- p_popRequestQueue;
- }
-
- transition(U, WriteThrough, BM_PM) {L3TagArrayRead, L3TagArrayWrite} {
- t_allocateTBE;
- w_sendResponseWBAck;
- l_queueMemRdReq;
- dc_probeInvCoreData;
- p_popRequestQueue;
- }
-
- transition(U, Atomic, BM_PM) {L3TagArrayRead, L3TagArrayWrite} {
- t_allocateTBE;
- l_queueMemRdReq;
- dc_probeInvCoreData;
- p_popRequestQueue;
- }
-
- transition(U, {RdBlkM}, BM_PM) {L3TagArrayRead} {
- t_allocateTBE;
- l_queueMemRdReq;
- dc_probeInvCoreData;
- p_popRequestQueue;
- }
-
- transition(U, RdBlk, B_PM) {L3TagArrayRead}{
- t_allocateTBE;
- l_queueMemRdReq;
- sc_probeShrCoreData;
- p_popRequestQueue;
- }
-
- transition(U, CtoD, BP) {L3TagArrayRead} {
- t_allocateTBE;
- ic_probeInvCore;
- p_popRequestQueue;
- }
-
- transition(U, VicDirty, BL) {L3TagArrayRead} {
- t_allocateTBE;
- w_sendResponseWBAck;
- p_popRequestQueue;
- }
-
- transition(U, VicClean, BL) {L3TagArrayRead} {
- t_allocateTBE;
- w_sendResponseWBAck;
- p_popRequestQueue;
- }
-
- transition(BL, {VicDirty, VicClean}) {
- zz_recycleRequestQueue;
- }
-
- transition(BL, CPUData, U) {L3TagArrayWrite, L3DataArrayWrite} {
- d_writeDataToMemory;
- al_allocateL3Block;
- wa_wakeUpDependents;
- dt_deallocateTBE;
- pr_popResponseQueue;
- }
-
- transition(BL, StaleWB, U) {L3TagArrayWrite} {
- dt_deallocateTBE;
- wa_wakeUpAllDependents;
- pr_popResponseQueue;
- }
-
- transition({B, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm}, {VicDirty, VicClean}) {
- z_stall;
- }
-
- transition({U, BL, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B}, WBAck) {
- pm_popMemQueue;
- }
-
- transition({U, BL, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B}, StaleVicDirty) {
- rv_removeVicDirtyIgnore;
- w_sendResponseWBAck;
- p_popRequestQueue;
- }
-
- transition({B}, CoreUnblock, U) {
- wa_wakeUpDependents;
- pu_popUnblockQueue;
- }
-
- transition(B, UnblockWriteThrough, U) {
- wa_wakeUpDependents;
- pt_popTriggerQueue;
- }
-
- transition(BS_PM, MemData, BS_Pm) {} {
- mt_writeMemDataToTBE;
- pm_popMemQueue;
- }
-
- transition(BM_PM, MemData, BM_Pm){} {
- mt_writeMemDataToTBE;
- pm_popMemQueue;
- }
-
- transition(B_PM, MemData, B_Pm){} {
- mt_writeMemDataToTBE;
- pm_popMemQueue;
- }
-
- transition(BS_PM, L3Hit, BS_Pm) {} {
- ptl_popTriggerQueue;
- }
-
- transition(BM_PM, L3Hit, BM_Pm) {} {
- ptl_popTriggerQueue;
- }
-
- transition(B_PM, L3Hit, B_Pm) {} {
- ptl_popTriggerQueue;
- }
-
- transition(BS_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} {
- mt_writeMemDataToTBE;
- s_sendResponseS;
- wd_writeBackData;
- alwt_allocateL3BlockOnWT;
- dt_deallocateTBE;
- pm_popMemQueue;
- }
-
- transition(BM_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} {
- mt_writeMemDataToTBE;
- m_sendResponseM;
- wd_writeBackData;
- alwt_allocateL3BlockOnWT;
- dt_deallocateTBE;
- pm_popMemQueue;
- }
-
- transition(B_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} {
- mt_writeMemDataToTBE;
- es_sendResponseES;
- wd_writeBackData;
- alwt_allocateL3BlockOnWT;
- dt_deallocateTBE;
- pm_popMemQueue;
- }
-
- transition(BS_M, L3Hit, B) {L3TagArrayWrite, L3DataArrayWrite} {
- s_sendResponseS;
- wd_writeBackData;
- alwt_allocateL3BlockOnWT;
- dt_deallocateTBE;
- ptl_popTriggerQueue;
- }
-
- transition(BM_M, L3Hit, B) {L3DataArrayWrite, L3TagArrayWrite} {
- m_sendResponseM;
- wd_writeBackData;
- alwt_allocateL3BlockOnWT;
- dt_deallocateTBE;
- ptl_popTriggerQueue;
- }
-
- transition(B_M, L3Hit, B) {L3DataArrayWrite, L3TagArrayWrite} {
- es_sendResponseES;
- wd_writeBackData;
- alwt_allocateL3BlockOnWT;
- dt_deallocateTBE;
- ptl_popTriggerQueue;
- }
-
- transition({BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, BP}, CPUPrbResp) {
- y_writeProbeDataToTBE;
- x_decrementAcks;
- o_checkForCompletion;
- pr_popResponseQueue;
- }
-
- transition(BS_PM, ProbeAcksComplete, BS_M) {} {
- sf_setForwardReqTime;
- pt_popTriggerQueue;
- }
-
- transition(BM_PM, ProbeAcksComplete, BM_M) {} {
- sf_setForwardReqTime;
- pt_popTriggerQueue;
- }
-
- transition(B_PM, ProbeAcksComplete, B_M){} {
- sf_setForwardReqTime;
- pt_popTriggerQueue;
- }
-
- transition(BS_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} {
- sf_setForwardReqTime;
- s_sendResponseS;
- wd_writeBackData;
- alwt_allocateL3BlockOnWT;
- dt_deallocateTBE;
- pt_popTriggerQueue;
- }
-
- transition(BM_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} {
- sf_setForwardReqTime;
- m_sendResponseM;
- wd_writeBackData;
- alwt_allocateL3BlockOnWT;
- dt_deallocateTBE;
- pt_popTriggerQueue;
- }
-
- transition(B_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} {
- sf_setForwardReqTime;
- es_sendResponseES;
- wd_writeBackData;
- alwt_allocateL3BlockOnWT;
- dt_deallocateTBE;
- pt_popTriggerQueue;
- }
-
- transition(BP, ProbeAcksComplete, B){L3TagArrayWrite, L3TagArrayWrite} {
- sf_setForwardReqTime;
- c_sendResponseCtoD;
- wd_writeBackData;
- alwt_allocateL3BlockOnWT;
- dt_deallocateTBE;
- pt_popTriggerQueue;
- }
-}