This commit is contained in:
Derek Hower
2009-08-05 14:23:32 -05:00
53 changed files with 1716 additions and 1613 deletions

View File

@@ -93,6 +93,8 @@ bool Map<KEY_TYPE, VALUE_TYPE>::exist(const KEY_TYPE& key) const
template <class KEY_TYPE, class VALUE_TYPE>
VALUE_TYPE& Map<KEY_TYPE, VALUE_TYPE>::lookup(const KEY_TYPE& key) const
{
if (!exist(key))
cerr << *this << " is looking for " << key << endl;
assert(exist(key));
return m_map[key];
}

View File

@@ -1,5 +1,8 @@
machine(L1Cache, "MI Example L1 Cache"): LATENCY_CACHE_RESPONSE_LATENCY LATENCY_ISSUE_LATENCY {
machine(L1Cache, "MI Example L1 Cache")
: int cache_response_latency,
int issue_latency
{
// NETWORK BUFFERS
MessageBuffer requestFromCache, network="To", virtual_network="0", ordered="true";
@@ -188,8 +191,8 @@ machine(L1Cache, "MI Example L1 Cache"): LATENCY_CACHE_RESPONSE_LATENCY LATENCY
// ACTIONS
action(a_issueRequest, "a", desc="Issue a request") {
enqueue(requestNetwork_out, RequestMsg, latency="ISSUE_LATENCY") {
out_msg.Address := address;
enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:GETX;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_Address_to_Directory(address));
@@ -198,7 +201,7 @@ machine(L1Cache, "MI Example L1 Cache"): LATENCY_CACHE_RESPONSE_LATENCY LATENCY
}
action(b_issuePUT, "b", desc="Issue a PUT request") {
enqueue(requestNetwork_out, RequestMsg, latency="ISSUE_LATENCY") {
enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:PUTX;
out_msg.Requestor := machineID;
@@ -211,7 +214,7 @@ machine(L1Cache, "MI Example L1 Cache"): LATENCY_CACHE_RESPONSE_LATENCY LATENCY
action(e_sendData, "e", desc="Send data from cache to requestor") {
peek(forwardRequestNetwork_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="CACHE_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
@@ -224,7 +227,7 @@ machine(L1Cache, "MI Example L1 Cache"): LATENCY_CACHE_RESPONSE_LATENCY LATENCY
action(ee_sendDataFromTBE, "\e", desc="Send data from TBE to requestor") {
peek(forwardRequestNetwork_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="CACHE_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;

View File

@@ -1,5 +1,9 @@
machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_DIRECTORY_LATENCY LATENCY_MEMORY_LATENCY {
machine(Directory, "Directory protocol")
: int directory_latency,
int dma_select_low_bit,
int dma_select_num_bits
{
MessageBuffer forwardFromDir, network="To", virtual_network="2", ordered="false";
MessageBuffer responseFromDir, network="To", virtual_network="1", ordered="false";
@@ -65,9 +69,9 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
// TBE entries for DMA requests
structure(TBE, desc="TBE entries for outstanding DMA requests") {
Address PhysicalAddress, desc="physical address";
State TBEState, desc="Transient State";
DataBlock DataBlk, desc="Data to be written (DMA write only)";
int Offset, desc="...";
int Len, desc="...";
}
@@ -180,7 +184,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") {
peek(requestQueue_in, RequestMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:WB_ACK;
out_msg.Requestor := in_msg.Requestor;
@@ -192,7 +196,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
action(l_sendWriteBackAck, "la", desc="Send writeback ack to requestor") {
peek(memQueue_in, MemoryMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency="TO_MEM_CTRL_LATENCY") {
enqueue(forwardNetwork_out, RequestMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:WB_ACK;
out_msg.Requestor := in_msg.OriginalRequestorMachId;
@@ -204,7 +208,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") {
peek(requestQueue_in, RequestMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:WB_NACK;
out_msg.Requestor := in_msg.Requestor;
@@ -218,29 +222,9 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
directory[address].Owner.clear();
}
// action(d_sendData, "d", desc="Send data to requestor") {
// peek(requestQueue_in, RequestMsg) {
// enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") {
// out_msg.Address := address;
//
// if (in_msg.Type == CoherenceRequestType:GETS && directory[address].Sharers.count() == 0) {
// // out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE_CLEAN;
// out_msg.Type := CoherenceResponseType:DATA;
// } else {
// out_msg.Type := CoherenceResponseType:DATA;
// }
//
// out_msg.Sender := machineID;
// out_msg.Destination.add(in_msg.Requestor);
// out_msg.DataBlk := directory[in_msg.Address].DataBlk;
// out_msg.MessageSize := MessageSizeType:Response_Data;
// }
// }
// }
action(d_sendData, "d", desc="Send data to requestor") {
peek(memQueue_in, MemoryMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="TO_MEM_CTRL_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
@@ -251,26 +235,15 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
}
}
// action(dr_sendDMAData, "dr", desc="Send Data to DMA controller from directory") {
// peek(dmaRequestQueue_in, DMARequestMsg) {
// enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") {
// out_msg.PhysicalAddress := address;
// out_msg.Type := DMAResponseType:DATA;
// out_msg.DataBlk := directory[in_msg.PhysicalAddress].DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be
// out_msg.Destination.add(map_Address_to_DMA(address));
// out_msg.MessageSize := MessageSizeType:Response_Data;
// }
// }
// }
action(dr_sendDMAData, "dr", desc="Send Data to DMA controller from directory") {
peek(memQueue_in, MemoryMsg) {
enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") {
enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") {
out_msg.PhysicalAddress := address;
out_msg.LineAddress := address;
out_msg.Type := DMAResponseType:DATA;
out_msg.DataBlk := in_msg.DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be
out_msg.Destination.add(map_Address_to_DMA(address));
out_msg.Destination.add(mapAddressToRange(address, MachineType:DMA,
dma_select_low_bit, dma_select_num_bits));
out_msg.MessageSize := MessageSizeType:Response_Data;
}
}
@@ -280,23 +253,25 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
action(drp_sendDMAData, "drp", desc="Send Data to DMA controller from incoming PUTX") {
peek(requestQueue_in, RequestMsg) {
enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") {
enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") {
out_msg.PhysicalAddress := address;
out_msg.LineAddress := address;
out_msg.Type := DMAResponseType:DATA;
out_msg.DataBlk := in_msg.DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be
out_msg.Destination.add(map_Address_to_DMA(address));
out_msg.Destination.add(mapAddressToRange(address, MachineType:DMA,
dma_select_low_bit, dma_select_num_bits));
out_msg.MessageSize := MessageSizeType:Response_Data;
}
}
}
action(da_sendDMAAck, "da", desc="Send Ack to DMA controller") {
enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") {
enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") {
out_msg.PhysicalAddress := address;
out_msg.LineAddress := address;
out_msg.Type := DMAResponseType:ACK;
out_msg.Destination.add(map_Address_to_DMA(address));
out_msg.Destination.add(mapAddressToRange(address, MachineType:DMA,
dma_select_low_bit, dma_select_num_bits));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
@@ -318,7 +293,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
APPEND_TRANSITION_COMMENT(directory[in_msg.Address].Owner);
APPEND_TRANSITION_COMMENT("Req: ");
APPEND_TRANSITION_COMMENT(in_msg.Requestor);
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
out_msg.Address := address;
out_msg.Type := in_msg.Type;
out_msg.Requestor := in_msg.Requestor;
@@ -330,7 +305,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
action(inv_sendCacheInvalidate, "inv", desc="Invalidate a cache block") {
peek(dmaRequestQueue_in, DMARequestMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:INV;
out_msg.Requestor := machineID;
@@ -359,14 +334,14 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
}
action(dwt_writeDMADataFromTBE, "dwt", desc="DMA Write data to memory from TBE") {
directory[address].DataBlk.copyPartial(TBEs[address].DataBlk, TBEs[address].Offset, TBEs[address].Len);
directory[address].DataBlk.copyPartial(TBEs[address].DataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len);
}
action(v_allocateTBE, "v", desc="Allocate TBE") {
peek(dmaRequestQueue_in, DMARequestMsg) {
TBEs.allocate(address);
TBEs[address].DataBlk := in_msg.DataBlk;
TBEs[address].Offset := in_msg.Offset;
TBEs[address].PhysicalAddress := in_msg.PhysicalAddress;
TBEs[address].Len := in_msg.Len;
}
}
@@ -389,7 +364,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") {
peek(requestQueue_in, RequestMsg) {
enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_READ;
out_msg.Sender := machineID;
@@ -403,7 +378,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
action(qf_queueMemoryFetchRequestDMA, "qfd", desc="Queue off-chip fetch request") {
peek(dmaRequestQueue_in, DMARequestMsg) {
enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_READ;
out_msg.Sender := machineID;
@@ -414,29 +389,15 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
}
}
}
// action(qw_queueMemoryWBRequest, "qw", desc="Queue off-chip writeback request") {
// peek(dmaRequestQueue_in, DMARequestMsg) {
// enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
// out_msg.Address := address;
// out_msg.Type := MemoryRequestType:MEMORY_WB;
// out_msg.OriginalRequestorMachId := machineID;
// out_msg.DataBlk := in_msg.DataBlk;
// out_msg.MessageSize := in_msg.MessageSize;
// DEBUG_EXPR(out_msg);
// }
// }
// }
action(qw_queueMemoryWBRequest_partial, "qwp", desc="Queue off-chip writeback request") {
peek(dmaRequestQueue_in, DMARequestMsg) {
enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
//out_msg.OriginalRequestorMachId := machineID;
//out_msg.DataBlk := in_msg.DataBlk;
out_msg.DataBlk.copyPartial(in_msg.DataBlk, in_msg.Offset, in_msg.Len);
out_msg.DataBlk.copyPartial(in_msg.DataBlk, addressOffset(in_msg.PhysicalAddress), in_msg.Len);
out_msg.MessageSize := in_msg.MessageSize;
//out_msg.Prefetch := in_msg.Prefetch;
@@ -447,12 +408,12 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
action(qw_queueMemoryWBRequest_partialTBE, "qwt", desc="Queue off-chip writeback request") {
peek(requestQueue_in, RequestMsg) {
enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
//out_msg.DataBlk := in_msg.DataBlk;
out_msg.DataBlk.copyPartial(TBEs[address].DataBlk, TBEs[address].Offset, TBEs[address].Len);
out_msg.DataBlk.copyPartial(TBEs[address].DataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len);
out_msg.MessageSize := in_msg.MessageSize;
//out_msg.Prefetch := in_msg.Prefetch;
@@ -465,7 +426,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") {
peek(requestQueue_in, RequestMsg) {
enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.OriginalRequestorMachId := in_msg.Requestor;

View File

@@ -1,5 +1,7 @@
machine(DMA, "DMA Controller") {
machine(DMA, "DMA Controller")
: int request_latency
{
MessageBuffer responseFromDir, network="From", virtual_network="4", ordered="true", no_vector="true";
MessageBuffer reqToDirectory, network="To", virtual_network="5", ordered="false", no_vector="true";
@@ -35,12 +37,12 @@ machine(DMA, "DMA Controller") {
out_port(reqToDirectory_out, DMARequestMsg, reqToDirectory, desc="...");
in_port(dmaRequestQueue_in, DMARequestMsg, mandatoryQueue, desc="...") {
in_port(dmaRequestQueue_in, SequencerMsg, mandatoryQueue, desc="...") {
if (dmaRequestQueue_in.isReady()) {
peek(dmaRequestQueue_in, DMARequestMsg) {
if (in_msg.Type == DMARequestType:READ ) {
peek(dmaRequestQueue_in, SequencerMsg) {
if (in_msg.Type == SequencerRequestType:LD ) {
trigger(Event:ReadRequest, in_msg.LineAddress);
} else if (in_msg.Type == DMARequestType:WRITE) {
} else if (in_msg.Type == SequencerRequestType:ST) {
trigger(Event:WriteRequest, in_msg.LineAddress);
} else {
error("Invalid request type");
@@ -64,9 +66,9 @@ machine(DMA, "DMA Controller") {
}
action(s_sendReadRequest, "s", desc="Send a DMA read request to memory") {
peek(dmaRequestQueue_in, DMARequestMsg) {
enqueue(reqToDirectory_out, DMARequestMsg) {
out_msg.PhysicalAddress := address;
peek(dmaRequestQueue_in, SequencerMsg) {
enqueue(reqToDirectory_out, DMARequestMsg, latency=request_latency) {
out_msg.PhysicalAddress := in_msg.PhysicalAddress;
out_msg.LineAddress := in_msg.LineAddress;
out_msg.Type := DMARequestType:READ;
out_msg.DataBlk := in_msg.DataBlk;
@@ -78,9 +80,9 @@ machine(DMA, "DMA Controller") {
}
action(s_sendWriteRequest, "\s", desc="Send a DMA write request to memory") {
peek(dmaRequestQueue_in, DMARequestMsg) {
enqueue(reqToDirectory_out, DMARequestMsg) {
out_msg.PhysicalAddress := address;
peek(dmaRequestQueue_in, SequencerMsg) {
enqueue(reqToDirectory_out, DMARequestMsg, latency=request_latency) {
out_msg.PhysicalAddress := in_msg.PhysicalAddress;
out_msg.LineAddress := in_msg.LineAddress;
out_msg.Type := DMARequestType:WRITE;
out_msg.DataBlk := in_msg.DataBlk;

View File

@@ -107,7 +107,6 @@ structure(DMARequestMsg, desc="...", interface="NetworkMessage") {
Address LineAddress, desc="Line address for this request";
NetDest Destination, desc="Destination";
DataBlock DataBlk, desc="DataBlk attached to this request";
int Offset, desc="The offset into the datablock";
int Len, desc="The length of the request";
MessageSizeType MessageSize, desc="size category of the message";
}

View File

@@ -32,7 +32,11 @@
*
*/
machine(L1Cache, "Directory protocol") {
machine(L1Cache, "Directory protocol")
: int request_latency,
int l2_select_low_bit,
int l2_select_num_bits
{
// NODE L1 CACHE
// From this node's L1 cache TO the network
@@ -125,7 +129,7 @@ machine(L1Cache, "Directory protocol") {
external_type(CacheMemory) {
bool cacheAvail(Address);
Address cacheProbe(Address);
void allocate(Address);
void allocate(Address, Entry);
void deallocate(Address);
Entry lookup(Address);
void changePermission(Address, AccessPermission);
@@ -141,11 +145,11 @@ machine(L1Cache, "Directory protocol") {
MessageBuffer mandatoryQueue, ordered="false", abstract_chip_ptr="true";
Sequencer sequencer, abstract_chip_ptr="true", constructor_hack="i";
Sequencer sequencer, factory='RubySystem::getSequencer(m_cfg["sequencer"])';
TBETable TBEs, template_hack="<L1Cache_TBE>";
CacheMemory L1IcacheMemory, template_hack="<L1Cache_Entry>", constructor_hack='L1_CACHE_NUM_SETS_BITS,L1_CACHE_ASSOC,MachineType_L1Cache,int_to_string(i)+"_L1I"', abstract_chip_ptr="true";
CacheMemory L1DcacheMemory, template_hack="<L1Cache_Entry>", constructor_hack='L1_CACHE_NUM_SETS_BITS,L1_CACHE_ASSOC,MachineType_L1Cache,int_to_string(i)+"_L1D"', abstract_chip_ptr="true";
CacheMemory L1IcacheMemory, factory='RubySystem::getCache(m_cfg["icache"])';
CacheMemory L1DcacheMemory, factory='RubySystem::getCache(m_cfg["dcache"])';
TimerTable useTimerTable;
Entry getCacheEntry(Address addr), return_by_ref="yes" {
@@ -305,7 +309,7 @@ machine(L1Cache, "Directory protocol") {
assert(in_msg.Destination.isElement(machineID));
DEBUG_EXPR("MRM_DEBUG: L1 received");
DEBUG_EXPR(in_msg.Type);
if (in_msg.Type == CoherenceRequestType:GETX) {
if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestType:DMA_READ || in_msg.Type == CoherenceRequestType:DMA_WRITE) {
if (in_msg.Requestor == machineID && in_msg.RequestorMachine == MachineType:L1Cache) {
trigger(Event:Own_GETX, in_msg.Address);
} else {
@@ -357,40 +361,40 @@ machine(L1Cache, "Directory protocol") {
// ** INSTRUCTION ACCESS ***
// Check to see if it is in the OTHER L1
if (L1DcacheMemory.isTagPresent(in_msg.Address)) {
if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) {
// The block is in the wrong L1, put the request on the queue to the shared L2
trigger(Event:L1_Replacement, in_msg.Address);
trigger(Event:L1_Replacement, in_msg.LineAddress);
}
if (L1IcacheMemory.isTagPresent(in_msg.Address)) {
if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) {
// The tag matches for the L1, so the L1 asks the L2 for it.
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress);
} else {
if (L1IcacheMemory.cacheAvail(in_msg.Address)) {
if (L1IcacheMemory.cacheAvail(in_msg.LineAddress)) {
// L1 does't have the line, but we have space for it in the L1 so let's see if the L2 has it
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress);
} else {
// No room in the L1, so we need to make room in the L1
trigger(Event:L1_Replacement, L1IcacheMemory.cacheProbe(in_msg.Address));
trigger(Event:L1_Replacement, L1IcacheMemory.cacheProbe(in_msg.LineAddress));
}
}
} else {
// *** DATA ACCESS ***
// Check to see if it is in the OTHER L1
if (L1IcacheMemory.isTagPresent(in_msg.Address)) {
if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) {
// The block is in the wrong L1, put the request on the queue to the shared L2
trigger(Event:L1_Replacement, in_msg.Address);
trigger(Event:L1_Replacement, in_msg.LineAddress);
}
if (L1DcacheMemory.isTagPresent(in_msg.Address)) {
if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) {
// The tag matches for the L1, so the L1 ask the L2 for it
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress);
} else {
if (L1DcacheMemory.cacheAvail(in_msg.Address)) {
if (L1DcacheMemory.cacheAvail(in_msg.LineAddress)) {
// L1 does't have the line, but we have space for it in the L1 let's see if the L2 has it
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress);
} else {
// No room in the L1, so we need to make room in the L1
trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.Address));
trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.LineAddress));
}
}
}
@@ -403,11 +407,12 @@ machine(L1Cache, "Directory protocol") {
action(a_issueGETS, "a", desc="Issue GETS") {
peek(mandatoryQueue_in, CacheMsg) {
enqueue(requestNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") {
enqueue(requestNetwork_out, RequestMsg, latency= request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:GETS;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.AccessMode := in_msg.AccessMode;
out_msg.Prefetch := in_msg.Prefetch;
@@ -417,11 +422,12 @@ machine(L1Cache, "Directory protocol") {
action(b_issueGETX, "b", desc="Issue GETX") {
peek(mandatoryQueue_in, CacheMsg) {
enqueue(requestNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") {
enqueue(requestNetwork_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:GETX;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.AccessMode := in_msg.AccessMode;
out_msg.Prefetch := in_msg.Prefetch;
@@ -430,34 +436,37 @@ machine(L1Cache, "Directory protocol") {
}
action(d_issuePUTX, "d", desc="Issue PUTX") {
// enqueue(writebackNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") {
enqueue(requestNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") {
// enqueue(writebackNetwork_out, RequestMsg, latency=request_latency) {
enqueue(requestNetwork_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:PUTX;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
action(dd_issuePUTO, "\d", desc="Issue PUTO") {
// enqueue(writebackNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") {
enqueue(requestNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") {
// enqueue(writebackNetwork_out, RequestMsg, latency=request_latency) {
enqueue(requestNetwork_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:PUTO;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
action(dd_issuePUTS, "\ds", desc="Issue PUTS") {
// enqueue(writebackNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") {
enqueue(requestNetwork_out, RequestMsg, latency="L1_REQUEST_LATENCY") {
// enqueue(writebackNetwork_out, RequestMsg, latency=request_latency) {
enqueue(requestNetwork_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:PUTS;
out_msg.Requestor := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
@@ -465,11 +474,12 @@ machine(L1Cache, "Directory protocol") {
action(e_sendData, "e", desc="Send data from cache to requestor") {
peek(requestNetwork_in, RequestMsg) {
if (in_msg.RequestorMachine == MachineType:L2Cache) {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(in_msg.Address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.DataBlk := getCacheEntry(address).DataBlk;
// out_msg.Dirty := getCacheEntry(address).Dirty;
out_msg.Dirty := false;
@@ -480,7 +490,7 @@ machine(L1Cache, "Directory protocol") {
DEBUG_EXPR(in_msg.Address);
}
else {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
@@ -497,11 +507,12 @@ machine(L1Cache, "Directory protocol") {
}
action(e_sendDataToL2, "ee", desc="Send data from cache to requestor") {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.DataBlk := getCacheEntry(address).DataBlk;
out_msg.Dirty := getCacheEntry(address).Dirty;
out_msg.Acks := 0; // irrelevant
@@ -513,12 +524,13 @@ machine(L1Cache, "Directory protocol") {
action(ee_sendDataExclusive, "\e", desc="Send data from cache to requestor, don't keep a shared copy") {
peek(requestNetwork_in, RequestMsg) {
if (in_msg.RequestorMachine == MachineType:L2Cache) {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:L1Cache;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(in_msg.Address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.DataBlk := getCacheEntry(address).DataBlk;
out_msg.Dirty := getCacheEntry(address).Dirty;
out_msg.Acks := in_msg.Acks;
@@ -527,7 +539,7 @@ machine(L1Cache, "Directory protocol") {
DEBUG_EXPR("Sending exclusive data to L2");
}
else {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
@@ -546,7 +558,7 @@ machine(L1Cache, "Directory protocol") {
action(f_sendAck, "f", desc="Send ack from cache to requestor") {
peek(requestNetwork_in, RequestMsg) {
if (in_msg.RequestorMachine == MachineType:L1Cache) {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:ACK;
out_msg.Sender := machineID;
@@ -557,12 +569,13 @@ machine(L1Cache, "Directory protocol") {
}
}
else {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:ACK;
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:L1Cache;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(in_msg.Address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.Acks := 0 - 1; // -1
out_msg.MessageSize := MessageSizeType:Response_Control;
}
@@ -571,21 +584,23 @@ machine(L1Cache, "Directory protocol") {
}
action(g_sendUnblock, "g", desc="Send unblock to memory") {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:UNBLOCK;
out_msg.Sender := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
}
}
action(gg_sendUnblockExclusive, "\g", desc="Send unblock exclusive to memory") {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE;
out_msg.Sender := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
}
}
@@ -627,7 +642,6 @@ machine(L1Cache, "Directory protocol") {
action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") {
peek(responseToL1Cache_in, ResponseMsg) {
DEBUG_EXPR("MRM_DEBUG: L1 decrementNumberOfMessages");
DEBUG_EXPR(id);
DEBUG_EXPR(in_msg.Acks);
TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - in_msg.Acks;
}
@@ -660,7 +674,7 @@ machine(L1Cache, "Directory protocol") {
action(q_sendDataFromTBEToCache, "q", desc="Send data from TBE to cache") {
peek(requestNetwork_in, RequestMsg) {
if (in_msg.RequestorMachine == MachineType:L1Cache) {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
@@ -673,11 +687,12 @@ machine(L1Cache, "Directory protocol") {
}
}
else {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address,machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.DataBlk := TBEs[address].DataBlk;
// out_msg.Dirty := TBEs[address].Dirty;
out_msg.Dirty := false;
@@ -691,7 +706,7 @@ machine(L1Cache, "Directory protocol") {
action(q_sendExclusiveDataFromTBEToCache, "qq", desc="Send data from TBE to cache") {
peek(requestNetwork_in, RequestMsg) {
if (in_msg.RequestorMachine == MachineType:L1Cache) {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
@@ -703,11 +718,12 @@ machine(L1Cache, "Directory protocol") {
}
}
else {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address,machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.DataBlk := TBEs[address].DataBlk;
out_msg.Dirty := TBEs[address].Dirty;
out_msg.Acks := in_msg.Acks;
@@ -720,11 +736,12 @@ machine(L1Cache, "Directory protocol") {
// L2 will usually request data for a writeback
action(qq_sendWBDataFromTBEToL2, "\q", desc="Send data from TBE to L2") {
enqueue(responseNetwork_out, ResponseMsg, latency="L1_REQUEST_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:L1Cache;
out_msg.Destination.add(map_L1CacheMachId_to_L2Cache(address, machineID));
out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
l2_select_low_bit, l2_select_num_bits));
out_msg.Dirty := TBEs[address].Dirty;
if (TBEs[address].Dirty) {
out_msg.Type := CoherenceResponseType:WRITEBACK_DIRTY_DATA;
@@ -770,13 +787,13 @@ machine(L1Cache, "Directory protocol") {
action(ii_allocateL1DCacheBlock, "\i", desc="Set L1 D-cache tag equal to tag of block B.") {
if (L1DcacheMemory.isTagPresent(address) == false) {
L1DcacheMemory.allocate(address);
L1DcacheMemory.allocate(address, new Entry);
}
}
action(jj_allocateL1ICacheBlock, "\j", desc="Set L1 I-cache tag equal to tag of block B.") {
if (L1IcacheMemory.isTagPresent(address) == false) {
L1IcacheMemory.allocate(address);
L1IcacheMemory.allocate(address, new Entry);
}
}
@@ -784,7 +801,7 @@ machine(L1Cache, "Directory protocol") {
action(uu_profileMiss, "\u", desc="Profile the demand miss") {
peek(mandatoryQueue_in, CacheMsg) {
profile_miss(in_msg, id);
// profile_miss(in_msg);
}
}

View File

@@ -32,7 +32,10 @@
*
*/
machine(L2Cache, "Token protocol") {
machine(L2Cache, "Token protocol")
: int response_latency,
int request_latency
{
// L2 BANK QUEUES
// From local bank of L2 cache TO the network
@@ -208,7 +211,7 @@ machine(L2Cache, "Token protocol") {
external_type(CacheMemory) {
bool cacheAvail(Address);
Address cacheProbe(Address);
void allocate(Address);
void allocate(Address, Entry);
void deallocate(Address);
Entry lookup(Address);
void changePermission(Address, AccessPermission);
@@ -225,13 +228,15 @@ machine(L2Cache, "Token protocol") {
TBETable L2_TBEs, template_hack="<L2Cache_TBE>";
CacheMemory L2cacheMemory, template_hack="<L2Cache_Entry>", constructor_hack='L2_CACHE_NUM_SETS_BITS,L2_CACHE_ASSOC,MachineType_L2Cache,int_to_string(i)+"_L2"';
CacheMemory L2cacheMemory, factory='RubySystem::getCache(m_cfg["cache"])';
PerfectCacheMemory localDirectory, template_hack="<L2Cache_DirEntry>";
Entry getL2CacheEntry(Address addr), return_by_ref="yes" {
if (L2cacheMemory.isTagPresent(addr)) {
return L2cacheMemory[addr];
} else {
return L2cacheMemory[addr];
}
}
@@ -579,7 +584,7 @@ machine(L2Cache, "Token protocol") {
in_port(requestNetwork_in, RequestMsg, GlobalRequestToL2Cache) {
if (requestNetwork_in.isReady()) {
peek(requestNetwork_in, RequestMsg) {
if (in_msg.Type == CoherenceRequestType:GETX) {
if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestType:DMA_READ || in_msg.Type == CoherenceRequestType:DMA_WRITE) {
if (in_msg.Requestor == machineID) {
trigger(Event:Own_GETX, in_msg.Address);
} else {
@@ -675,7 +680,7 @@ machine(L2Cache, "Token protocol") {
action(a_issueGETS, "a", desc="issue local request globally") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue(globalRequestNetwork_out, RequestMsg, latency="L2_REQUEST_LATENCY") {
enqueue(globalRequestNetwork_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:GETS;
out_msg.RequestorMachine := MachineType:L2Cache;
@@ -688,7 +693,7 @@ machine(L2Cache, "Token protocol") {
action(a_issueGETX, "\a", desc="issue local request globally") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue(globalRequestNetwork_out, RequestMsg, latency="L2_REQUEST_LATENCY") {
enqueue(globalRequestNetwork_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:GETX;
out_msg.RequestorMachine := MachineType:L2Cache;
@@ -700,7 +705,7 @@ machine(L2Cache, "Token protocol") {
}
action(b_issuePUTX, "b", desc="Issue PUTX") {
enqueue(globalRequestNetwork_out, RequestMsg, latency="L2_REQUEST_LATENCY") {
enqueue(globalRequestNetwork_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:PUTX;
out_msg.RequestorMachine := MachineType:L2Cache;
@@ -711,7 +716,7 @@ machine(L2Cache, "Token protocol") {
}
action(b_issuePUTO, "\b", desc="Issue PUTO") {
enqueue(globalRequestNetwork_out, RequestMsg, latency="L2_REQUEST_LATENCY") {
enqueue(globalRequestNetwork_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:PUTO;
out_msg.Requestor := machineID;
@@ -723,7 +728,7 @@ machine(L2Cache, "Token protocol") {
/* PUTO, but local sharers exist */
action(b_issuePUTO_ls, "\bb", desc="Issue PUTO") {
enqueue(globalRequestNetwork_out, RequestMsg, latency="L2_REQUEST_LATENCY") {
enqueue(globalRequestNetwork_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:PUTO_SHARERS;
out_msg.Requestor := machineID;
@@ -734,7 +739,7 @@ machine(L2Cache, "Token protocol") {
}
action(c_sendDataFromTBEToL1GETS, "c", desc="Send data from TBE to L1 requestors in TBE") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
@@ -750,7 +755,7 @@ machine(L2Cache, "Token protocol") {
}
action(c_sendDataFromTBEToL1GETX, "\c", desc="Send data from TBE to L1 requestors in TBE") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
@@ -766,7 +771,7 @@ machine(L2Cache, "Token protocol") {
}
action(c_sendExclusiveDataFromTBEToL1GETS, "\cc", desc="Send data from TBE to L1 requestors in TBE") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
@@ -779,7 +784,7 @@ machine(L2Cache, "Token protocol") {
}
action(c_sendDataFromTBEToFwdGETX, "cc", desc="Send data from TBE to external GETX") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
@@ -793,7 +798,7 @@ machine(L2Cache, "Token protocol") {
}
action(c_sendDataFromTBEToFwdGETS, "ccc", desc="Send data from TBE to external GETX") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
@@ -810,7 +815,7 @@ machine(L2Cache, "Token protocol") {
}
action(c_sendExclusiveDataFromTBEToFwdGETS, "\ccc", desc="Send data from TBE to external GETX") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
@@ -827,7 +832,7 @@ machine(L2Cache, "Token protocol") {
action(d_sendDataToL1GETS, "d", desc="Send data directly to L1 requestor") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
@@ -845,7 +850,7 @@ machine(L2Cache, "Token protocol") {
action(d_sendDataToL1GETX, "\d", desc="Send data and a token from TBE to L1 requestor") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
@@ -863,7 +868,7 @@ machine(L2Cache, "Token protocol") {
action(dd_sendDataToFwdGETX, "dd", desc="send data") {
peek(requestNetwork_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
@@ -882,7 +887,7 @@ machine(L2Cache, "Token protocol") {
action(dd_sendDataToFwdGETS, "\dd", desc="send data") {
peek(requestNetwork_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA;
out_msg.Sender := machineID;
@@ -900,7 +905,7 @@ machine(L2Cache, "Token protocol") {
action(dd_sendExclusiveDataToFwdGETS, "\d\d", desc="send data") {
peek(requestNetwork_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.Sender := machineID;
@@ -913,7 +918,7 @@ machine(L2Cache, "Token protocol") {
}
action(e_sendAck, "e", desc="Send ack with the tokens we've collected thus far.") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:ACK;
out_msg.Sender := machineID;
@@ -927,7 +932,7 @@ machine(L2Cache, "Token protocol") {
action(e_sendAckToL1Requestor, "\e", desc="Send ack with the tokens we've collected thus far.") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:ACK;
out_msg.Sender := machineID;
@@ -940,7 +945,7 @@ machine(L2Cache, "Token protocol") {
}
action(e_sendAckToL1RequestorFromTBE, "eee", desc="Send ack with the tokens we've collected thus far.") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:ACK;
out_msg.Sender := machineID;
@@ -955,14 +960,13 @@ machine(L2Cache, "Token protocol") {
L2_TBEs[address].NumIntPendingAcks := countLocalSharers(address);
DEBUG_EXPR(address);
DEBUG_EXPR(getLocalSharers(address));
DEBUG_EXPR(id);
DEBUG_EXPR(L2_TBEs[address].NumIntPendingAcks);
if (isLocalOwnerValid(address)) {
L2_TBEs[address].NumIntPendingAcks := L2_TBEs[address].NumIntPendingAcks + 1;
DEBUG_EXPR(getLocalOwner(address));
}
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:INV;
out_msg.Requestor := machineID;
@@ -982,7 +986,7 @@ machine(L2Cache, "Token protocol") {
L2_TBEs[address].NumIntPendingAcks := countLocalSharers(address);
if (countLocalSharers(address) > 0) {
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:INV;
out_msg.Requestor := machineID;
@@ -1013,7 +1017,7 @@ machine(L2Cache, "Token protocol") {
L2_TBEs[address].NumIntPendingAcks := countLocalSharers(address);
}
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:INV;
out_msg.Requestor := in_msg.Requestor;
@@ -1038,7 +1042,7 @@ machine(L2Cache, "Token protocol") {
L2_TBEs[address].NumIntPendingAcks := countLocalSharers(address);
}
}
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:INV;
out_msg.Requestor := L2_TBEs[address].L1_GetX_ID;
@@ -1051,7 +1055,7 @@ machine(L2Cache, "Token protocol") {
action(f_sendUnblock, "f", desc="Send unblock to global directory") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:UNBLOCK;
out_msg.Destination.add(map_Address_to_Directory(address));
@@ -1063,7 +1067,7 @@ machine(L2Cache, "Token protocol") {
action(f_sendExclusiveUnblock, "\f", desc="Send unblock to global directory") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE;
out_msg.Destination.add(map_Address_to_Directory(address));
@@ -1140,7 +1144,7 @@ machine(L2Cache, "Token protocol") {
action(j_forwardGlobalRequestToLocalOwner, "j", desc="Forward external request to local owner") {
peek(requestNetwork_in, RequestMsg) {
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := in_msg.Address;
out_msg.Type := in_msg.Type;
out_msg.Requestor := machineID;
@@ -1156,7 +1160,7 @@ machine(L2Cache, "Token protocol") {
action(k_forwardLocalGETSToLocalSharer, "k", desc="Forward local request to local sharer/owner") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := in_msg.Address;
out_msg.Type := CoherenceRequestType:GETS;
out_msg.Requestor := in_msg.Requestor;
@@ -1169,7 +1173,7 @@ machine(L2Cache, "Token protocol") {
}
action(k_forwardLocalGETXToLocalOwner, "\k", desc="Forward local request to local owner") {
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:GETX;
out_msg.Requestor := L2_TBEs[address].L1_GetX_ID;
@@ -1183,7 +1187,7 @@ machine(L2Cache, "Token protocol") {
// same as previous except that it assumes to TBE is present to get number of acks
action(kk_forwardLocalGETXToLocalExclusive, "kk", desc="Forward local request to local owner") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := in_msg.Address;
out_msg.Type := CoherenceRequestType:GETX;
out_msg.Requestor := in_msg.Requestor;
@@ -1197,7 +1201,7 @@ machine(L2Cache, "Token protocol") {
action(kk_forwardLocalGETSToLocalOwner, "\kk", desc="Forward local request to local owner") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := in_msg.Address;
out_msg.Type := CoherenceRequestType:GETS;
out_msg.Requestor := in_msg.Requestor;
@@ -1211,7 +1215,7 @@ machine(L2Cache, "Token protocol") {
action(l_writebackAckNeedData, "l", desc="Send writeback ack to L1 requesting data") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := in_msg.Address;
// out_msg.Type := CoherenceResponseType:WRITEBACK_SEND_DATA;
out_msg.Type := CoherenceRequestType:WB_ACK_DATA;
@@ -1225,7 +1229,7 @@ machine(L2Cache, "Token protocol") {
action(l_writebackAckDropData, "\l", desc="Send writeback ack to L1 indicating to drop data") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := in_msg.Address;
// out_msg.Type := CoherenceResponseType:WRITEBACK_ACK;
out_msg.Type := CoherenceRequestType:WB_ACK;
@@ -1239,7 +1243,7 @@ machine(L2Cache, "Token protocol") {
action(ll_writebackNack, "\ll", desc="Send writeback nack to L1") {
peek(L1requestNetwork_in, RequestMsg) {
enqueue( localRequestNetwork_out, RequestMsg, latency="L2_RESPONSE_LATENCY" ) {
enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
out_msg.Address := in_msg.Address;
out_msg.Type := CoherenceRequestType:WB_NACK;
out_msg.Requestor := machineID;
@@ -1305,7 +1309,7 @@ machine(L2Cache, "Token protocol") {
action( qq_sendDataFromTBEToMemory, "qq", desc="Send data from TBE to directory") {
enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:L2Cache;
@@ -1372,7 +1376,7 @@ machine(L2Cache, "Token protocol") {
}
action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") {
L2cacheMemory.allocate(address);
L2cacheMemory.allocate(address, new Entry);
}
action(rr_deallocateL2CacheBlock, "\r", desc="Deallocate L2 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") {
@@ -1389,7 +1393,7 @@ machine(L2Cache, "Token protocol") {
action(uu_profileMiss, "\u", desc="Profile the demand miss") {
peek(L1requestNetwork_in, RequestMsg) {
// AccessModeType not implemented
profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize), in_msg.Prefetch, machineIDToNodeID(in_msg.Requestor));
// profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize), in_msg.Prefetch, machineIDToNodeID(in_msg.Requestor));
}
}

View File

@@ -31,13 +31,15 @@
* $Id$
*/
machine(Directory, "Directory protocol") {
machine(Directory, "Directory protocol")
: int directory_latency
{
// ** IN QUEUES **
MessageBuffer foo1, network="From", virtual_network="0", ordered="false"; // a mod-L2 bank -> this Dir
MessageBuffer requestToDir, network="From", virtual_network="1", ordered="false"; // a mod-L2 bank -> this Dir
MessageBuffer responseToDir, network="From", virtual_network="2", ordered="false"; // a mod-L2 bank -> this Dir
MessageBuffer goo1, network="To", virtual_network="0", ordered="false";
MessageBuffer forwardFromDir, network="To", virtual_network="1", ordered="false";
MessageBuffer responseFromDir, network="To", virtual_network="2", ordered="false"; // Dir -> mod-L2 bank
@@ -56,11 +58,16 @@ machine(Directory, "Directory protocol") {
OO, desc="Blocked, was in owned";
MO, desc="Blocked, going to owner or maybe modified";
MM, desc="Blocked, going to modified";
MM_DMA, desc="Blocked, going to I";
MI, desc="Blocked on a writeback";
MIS, desc="Blocked on a writeback, but don't remove from sharers when received";
OS, desc="Blocked on a writeback";
OSS, desc="Blocked on a writeback, but don't remove from sharers when received";
XI_M, desc="In a stable state, going to I, waiting for the memory controller";
XI_U, desc="In a stable state, going to I, waiting for an unblock";
OI_D, desc="In O, going to I, waiting for data";
}
// Events
@@ -75,6 +82,11 @@ machine(Directory, "Directory protocol") {
Exclusive_Unblock, desc="The processor become the exclusive owner (E or M) of the line";
Clean_Writeback, desc="The final message as part of a PutX/PutS, no data";
Dirty_Writeback, desc="The final message as part of a PutX/PutS, contains data";
Memory_Data, desc="Fetched data from memory arrives";
Memory_Ack, desc="Writeback Ack from memory arrives";
DMA_READ, desc="DMA Read";
DMA_WRITE, desc="DMA Write";
Data, desc="Data to directory";
}
// TYPES
@@ -88,15 +100,36 @@ machine(Directory, "Directory protocol") {
int WaitingUnblocks, desc="Number of acks we're waiting for";
}
structure(TBE, desc="...") {
Address address, desc="Address for this entry";
int Len, desc="Length of request";
DataBlock DataBlk, desc="DataBlk";
MachineID Requestor, desc="original requestor";
}
external_type(DirectoryMemory) {
Entry lookup(Address);
bool isPresent(Address);
}
external_type(TBETable) {
TBE lookup(Address);
void allocate(Address);
void deallocate(Address);
bool isPresent(Address);
}
// to simulate detailed DRAM
external_type(MemoryControl, inport="yes", outport="yes") {
}
// ** OBJECTS **
DirectoryMemory directory, constructor_hack="i";
DirectoryMemory directory, factory='RubySystem::getDirectory(m_cfg["directory_name"])';
MemoryControl memBuffer, factory='RubySystem::getMemoryControl(m_cfg["memory_controller_name"])';
TBETable TBEs, template_hack="<Directory_TBE>";
State getState(Address addr) {
return directory[addr].DirectoryState;
@@ -164,6 +197,7 @@ machine(Directory, "Directory protocol") {
out_port(responseNetwork_out, ResponseMsg, responseFromDir);
// out_port(requestQueue_out, ResponseMsg, requestFromDir); // For recycling requests
out_port(goo1_out, ResponseMsg, goo1);
out_port(memQueue_out, MemoryMsg, memBuffer);
// ** IN_PORTS **
@@ -188,6 +222,8 @@ machine(Directory, "Directory protocol") {
trigger(Event:Dirty_Writeback, in_msg.Address);
} else if (in_msg.Type == CoherenceResponseType:WRITEBACK_CLEAN_ACK) {
trigger(Event:Clean_Writeback, in_msg.Address);
} else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
trigger(Event:Data, in_msg.Address);
} else {
error("Invalid message");
}
@@ -208,6 +244,10 @@ machine(Directory, "Directory protocol") {
trigger(Event:PUTO, in_msg.Address);
} else if (in_msg.Type == CoherenceRequestType:PUTO_SHARERS) {
trigger(Event:PUTO_SHARERS, in_msg.Address);
} else if (in_msg.Type == CoherenceRequestType:DMA_READ) {
trigger(Event:DMA_READ, in_msg.Address);
} else if (in_msg.Type == CoherenceRequestType:DMA_WRITE) {
trigger(Event:DMA_WRITE, in_msg.Address);
} else {
error("Invalid message");
}
@@ -215,11 +255,27 @@ machine(Directory, "Directory protocol") {
}
}
// off-chip memory request/response is done
in_port(memQueue_in, MemoryMsg, memBuffer) {
if (memQueue_in.isReady()) {
peek(memQueue_in, MemoryMsg) {
if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
trigger(Event:Memory_Data, in_msg.Address);
} else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
trigger(Event:Memory_Ack, in_msg.Address);
} else {
DEBUG_EXPR(in_msg.Type);
error("Invalid message");
}
}
}
}
// Actions
action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") {
peek(requestQueue_in, RequestMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:WB_ACK;
out_msg.Requestor := in_msg.Requestor;
@@ -231,7 +287,7 @@ machine(Directory, "Directory protocol") {
action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") {
peek(requestQueue_in, RequestMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:WB_NACK;
out_msg.Requestor := in_msg.Requestor;
@@ -254,27 +310,22 @@ machine(Directory, "Directory protocol") {
directory[address].Sharers.clear();
}
action(d_sendData, "d", desc="Send data to requestor") {
peek(requestQueue_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") {
// enqueue(responseNetwork_out, ResponseMsg, latency="L2_RESPONSE_LATENCY") {
action(d_sendDataMsg, "d", desc="Send data to requestor") {
peek(memQueue_in, MemoryMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="1") {
out_msg.Address := address;
if (in_msg.Type == CoherenceRequestType:GETS && directory[address].Sharers.count() == 0) {
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:Directory;
out_msg.Destination.add(in_msg.OriginalRequestorMachId);
//out_msg.DataBlk := directory[in_msg.Address].DataBlk;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Dirty := false; // By definition, the block is now clean
out_msg.Acks := in_msg.Acks;
if (in_msg.ReadX) {
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
} else {
out_msg.Type := CoherenceResponseType:DATA;
}
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:Directory;
out_msg.Destination.add(in_msg.Requestor);
out_msg.DataBlk := directory[in_msg.Address].DataBlk;
out_msg.Dirty := false; // By definition, the block is now clean
out_msg.Acks := directory[address].Sharers.count();
if (directory[address].Sharers.isElement(in_msg.Requestor)) {
out_msg.Acks := out_msg.Acks - 1;
}
out_msg.MessageSize := MessageSizeType:Response_Data;
}
}
@@ -289,7 +340,7 @@ machine(Directory, "Directory protocol") {
action(f_forwardRequest, "f", desc="Forward request to owner") {
peek(requestQueue_in, RequestMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
out_msg.Address := address;
out_msg.Type := in_msg.Type;
out_msg.Requestor := in_msg.Requestor;
@@ -303,11 +354,27 @@ machine(Directory, "Directory protocol") {
}
}
action(f_forwardRequestDirIsRequestor, "\f", desc="Forward request to owner") {
peek(requestQueue_in, RequestMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
out_msg.Address := address;
out_msg.Type := in_msg.Type;
out_msg.Requestor := machineID;
out_msg.Destination.addNetDest(directory[in_msg.Address].Owner);
out_msg.Acks := directory[address].Sharers.count();
if (directory[address].Sharers.isElement(in_msg.Requestor)) {
out_msg.Acks := out_msg.Acks - 1;
}
out_msg.MessageSize := MessageSizeType:Forwarded_Control;
}
}
}
action(g_sendInvalidations, "g", desc="Send invalidations to sharers, not including the requester") {
peek(requestQueue_in, RequestMsg) {
if ((directory[in_msg.Address].Sharers.count() > 1) ||
((directory[in_msg.Address].Sharers.count() > 0) && (directory[in_msg.Address].Sharers.isElement(in_msg.Requestor) == false))) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:INV;
out_msg.Requestor := in_msg.Requestor;
@@ -338,7 +405,7 @@ machine(Directory, "Directory protocol") {
}
}
action(ll_checkDataInMemory, "\l", desc="Check PUTX/PUTO data is same as in the memory") {
action(ll_checkDataInMemory, "\ld", desc="Check PUTX/PUTO data is same as in the memory") {
peek(unblockNetwork_in, ResponseMsg) {
assert(in_msg.Dirty == false);
assert(in_msg.MessageSize == MessageSizeType:Writeback_Control);
@@ -366,6 +433,70 @@ machine(Directory, "Directory protocol") {
assert(directory[address].WaitingUnblocks >= 0);
}
action(q_popMemQueue, "q", desc="Pop off-chip request queue") {
memQueue_in.dequeue();
}
action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") {
peek(requestQueue_in, RequestMsg) {
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_READ;
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.DataBlk := directory[in_msg.Address].DataBlk;
out_msg.MessageSize := in_msg.MessageSize;
//out_msg.Prefetch := false;
// These are not used by memory but are passed back here with the read data:
out_msg.ReadX := (in_msg.Type == CoherenceRequestType:GETS && directory[address].Sharers.count() == 0);
out_msg.Acks := directory[address].Sharers.count();
if (directory[address].Sharers.isElement(in_msg.Requestor)) {
out_msg.Acks := out_msg.Acks - 1;
}
DEBUG_EXPR(out_msg);
}
}
}
action(qw_queueMemoryWBRequest, "qw", desc="Queue off-chip writeback request") {
peek(unblockNetwork_in, ResponseMsg) {
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.Sender := machineID;
if (TBEs.isPresent(address)) {
out_msg.OriginalRequestorMachId := TBEs[address].Requestor;
}
out_msg.DataBlk := in_msg.DataBlk;
out_msg.MessageSize := in_msg.MessageSize;
//out_msg.Prefetch := false;
// Not used:
out_msg.ReadX := false;
out_msg.Acks := directory[address].Sharers.count(); // for dma requests
DEBUG_EXPR(out_msg);
}
}
}
action(qw_queueMemoryWBRequest2, "/qw", desc="Queue off-chip writeback request") {
peek(requestQueue_in, RequestMsg) {
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.MessageSize := in_msg.MessageSize;
//out_msg.Prefetch := false;
// Not used:
out_msg.ReadX := false;
out_msg.Acks := directory[address].Sharers.count(); // for dma requests
DEBUG_EXPR(out_msg);
}
}
}
// action(z_stall, "z", desc="Cannot be handled right now.") {
// Special name recognized as do nothing case
// }
@@ -374,26 +505,106 @@ machine(Directory, "Directory protocol") {
requestQueue_in.recycle();
}
action(a_sendDMAAck, "\a", desc="Send DMA Ack that write completed, along with Inv Ack count") {
peek(memQueue_in, MemoryMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="1") {
out_msg.Address := address;
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:Directory;
out_msg.Destination.add(in_msg.OriginalRequestorMachId);
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Acks := in_msg.Acks;
out_msg.Type := CoherenceResponseType:DMA_ACK;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
}
action(l_writeDMADataToMemory, "\l", desc="Write data from a DMA_WRITE to memory") {
peek(requestQueue_in, RequestMsg) {
directory[address].DataBlk.copyPartial(in_msg.DataBlk, addressOffset(in_msg.Address), in_msg.Len);
}
}
action(l_writeDMADataToMemoryFromTBE, "\ll", desc="Write data from a DMA_WRITE to memory") {
directory[address].DataBlk.copyPartial(TBEs[address].DataBlk, addressOffset(address), TBEs[address].Len);
}
action(v_allocateTBE, "v", desc="Allocate TBE entry") {
peek (requestQueue_in, RequestMsg) {
TBEs.allocate(address);
TBEs[address].Len := in_msg.Len;
TBEs[address].DataBlk := in_msg.DataBlk;
TBEs[address].Requestor := in_msg.Requestor;
}
}
action(w_deallocateTBE, "w", desc="Deallocate TBE entry") {
TBEs.deallocate(address);
}
// TRANSITIONS
transition(I, GETX, MM) {
d_sendData;
qf_queueMemoryFetchRequest;
i_popIncomingRequestQueue;
}
transition(I, DMA_READ, XI_M) {
qf_queueMemoryFetchRequest;
i_popIncomingRequestQueue;
}
transition(I, DMA_WRITE, XI_M) {
qw_queueMemoryWBRequest2;
l_writeDMADataToMemory;
i_popIncomingRequestQueue;
}
transition(XI_M, Memory_Data, XI_U) {
d_sendDataMsg; // ack count may be zero
q_popMemQueue;
}
transition(XI_M, Memory_Ack, XI_U) {
a_sendDMAAck; // ack count may be zero
q_popMemQueue;
}
transition(XI_U, Exclusive_Unblock, I) {
cc_clearSharers;
c_clearOwner;
j_popIncomingUnblockQueue;
}
transition(S, GETX, MM) {
d_sendData;
qf_queueMemoryFetchRequest;
g_sendInvalidations;
i_popIncomingRequestQueue;
}
transition(S, DMA_READ, XI_M) {
qf_queueMemoryFetchRequest;
g_sendInvalidations; // the DMA will collect the invalidations then send an Unblock Exclusive
i_popIncomingRequestQueue;
}
transition(S, DMA_WRITE, XI_M) {
qw_queueMemoryWBRequest2;
l_writeDMADataToMemory;
g_sendInvalidations; // the DMA will collect invalidations
i_popIncomingRequestQueue;
}
transition(I, GETS, IS) {
d_sendData;
qf_queueMemoryFetchRequest;
i_popIncomingRequestQueue;
}
transition({S, SS}, GETS, SS) {
d_sendData;
qf_queueMemoryFetchRequest;
n_incrementOutstanding;
i_popIncomingRequestQueue;
}
@@ -414,6 +625,27 @@ machine(Directory, "Directory protocol") {
i_popIncomingRequestQueue;
}
transition(O, DMA_READ, XI_U) {
f_forwardRequest; // this will cause the data to go to DMA directly
g_sendInvalidations; // this will cause acks to be sent to the DMA
i_popIncomingRequestQueue;
}
transition({O,M}, DMA_WRITE, OI_D) {
f_forwardRequestDirIsRequestor; // need the modified data before we can proceed
g_sendInvalidations; // these go to the DMA Controller
v_allocateTBE;
i_popIncomingRequestQueue;
}
transition(OI_D, Data, XI_M) {
qw_queueMemoryWBRequest;
l_writeDataToMemory;
l_writeDMADataToMemoryFromTBE;
w_deallocateTBE;
j_popIncomingUnblockQueue;
}
transition({O, OO}, GETS, OO) {
f_forwardRequest;
n_incrementOutstanding;
@@ -425,6 +657,12 @@ machine(Directory, "Directory protocol") {
i_popIncomingRequestQueue;
}
// no exclusive unblock will show up to the directory
transition(M, DMA_READ, XI_U) {
f_forwardRequest; // this will cause the data to go to DMA directly
i_popIncomingRequestQueue;
}
transition(M, GETS, MO) {
f_forwardRequest;
i_popIncomingRequestQueue;
@@ -457,7 +695,7 @@ machine(Directory, "Directory protocol") {
}
transition({MM, MO, MI, MIS, OS, OSS}, {GETS, GETX, PUTO, PUTO_SHARERS, PUTX}) {
transition({MM, MO, MI, MIS, OS, OSS}, {GETS, GETX, PUTO, PUTO_SHARERS, PUTX, DMA_READ}) {
zz_recycleRequest;
}
@@ -472,7 +710,7 @@ machine(Directory, "Directory protocol") {
j_popIncomingUnblockQueue;
}
transition({IS, SS, OO}, {GETX, PUTO, PUTO_SHARERS, PUTX}) {
transition({IS, SS, OO}, {GETX, PUTO, PUTO_SHARERS, PUTX, DMA_READ}) {
zz_recycleRequest;
}
@@ -519,12 +757,14 @@ machine(Directory, "Directory protocol") {
c_clearOwner;
cc_clearSharers;
l_writeDataToMemory;
qw_queueMemoryWBRequest;
j_popIncomingUnblockQueue;
}
transition(MIS, Dirty_Writeback, S) {
c_moveOwnerToSharer;
l_writeDataToMemory;
qw_queueMemoryWBRequest;
j_popIncomingUnblockQueue;
}
@@ -536,12 +776,14 @@ machine(Directory, "Directory protocol") {
transition(OS, Dirty_Writeback, S) {
c_clearOwner;
l_writeDataToMemory;
qw_queueMemoryWBRequest;
j_popIncomingUnblockQueue;
}
transition(OSS, Dirty_Writeback, S) {
c_moveOwnerToSharer;
l_writeDataToMemory;
qw_queueMemoryWBRequest;
j_popIncomingUnblockQueue;
}
@@ -570,4 +812,15 @@ machine(Directory, "Directory protocol") {
transition({OS, OSS}, Unblock, O) {
j_popIncomingUnblockQueue;
}
transition({I, S, O, M, IS, SS, OO, MO, MM, MI, MIS, OS, OSS}, Memory_Data) {
d_sendDataMsg;
q_popMemQueue;
}
transition({I, S, O, M, IS, SS, OO, MO, MM, MI, MIS, OS, OSS}, Memory_Ack) {
//a_sendAck;
q_popMemQueue;
}
}

View File

@@ -0,0 +1,267 @@
machine(DMA, "DMA Controller")
: int request_latency,
int response_latency
{
MessageBuffer goo1, network="From", virtual_network="0", ordered="false";
MessageBuffer goo2, network="From", virtual_network="1", ordered="false";
MessageBuffer responseFromDir, network="From", virtual_network="2", ordered="false";
MessageBuffer foo1, network="To", virtual_network="0", ordered="false";
MessageBuffer reqToDir, network="To", virtual_network="1", ordered="false";
MessageBuffer respToDir, network="To", virtual_network="2", ordered="false";
enumeration(State, desc="DMA states", default="DMA_State_READY") {
READY, desc="Ready to accept a new request";
BUSY_RD, desc="Busy: currently processing a request";
BUSY_WR, desc="Busy: currently processing a request";
}
enumeration(Event, desc="DMA events") {
ReadRequest, desc="A new read request";
WriteRequest, desc="A new write request";
Data, desc="Data from a DMA memory read";
DMA_Ack, desc="DMA write to memory completed";
Inv_Ack, desc="Invalidation Ack from a sharer";
All_Acks, desc="All acks received";
}
structure(TBE, desc="...") {
Address address, desc="Physical address";
int NumAcks, default="0", desc="Number of Acks pending";
DataBlock DataBlk, desc="Data";
}
external_type(DMASequencer) {
void ackCallback();
void dataCallback(DataBlock);
}
external_type(TBETable) {
TBE lookup(Address);
void allocate(Address);
void deallocate(Address);
bool isPresent(Address);
}
MessageBuffer mandatoryQueue, ordered="false";
MessageBuffer triggerQueue, ordered="true";
DMASequencer dma_sequencer, factory='RubySystem::getDMASequencer(m_cfg["dma_sequencer"])';
TBETable TBEs, template_hack="<DMA_TBE>";
State cur_state;
State getState(Address addr) {
return cur_state;
}
void setState(Address addr, State state) {
cur_state := state;
}
out_port(reqToDirectory_out, RequestMsg, reqToDir, desc="...");
out_port(respToDirectory_out, ResponseMsg, respToDir, desc="...");
out_port(foo1_out, ResponseMsg, foo1, desc="...");
out_port(triggerQueue_out, TriggerMsg, triggerQueue, desc="...");
in_port(goo1_in, RequestMsg, goo1) {
if (goo1_in.isReady()) {
peek(goo1_in, RequestMsg) {
assert(false);
}
}
}
in_port(goo2_in, RequestMsg, goo2) {
if (goo2_in.isReady()) {
peek(goo2_in, RequestMsg) {
assert(false);
}
}
}
in_port(dmaRequestQueue_in, SequencerMsg, mandatoryQueue, desc="...") {
if (dmaRequestQueue_in.isReady()) {
peek(dmaRequestQueue_in, SequencerMsg) {
if (in_msg.Type == SequencerRequestType:LD ) {
trigger(Event:ReadRequest, in_msg.PhysicalAddress);
} else if (in_msg.Type == SequencerRequestType:ST) {
trigger(Event:WriteRequest, in_msg.PhysicalAddress);
} else {
error("Invalid request type");
}
}
}
}
in_port(dmaResponseQueue_in, ResponseMsg, responseFromDir, desc="...") {
if (dmaResponseQueue_in.isReady()) {
peek( dmaResponseQueue_in, ResponseMsg) {
if (in_msg.Type == CoherenceResponseType:DMA_ACK) {
trigger(Event:DMA_Ack, in_msg.Address);
} else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
trigger(Event:Data, in_msg.Address);
} else if (in_msg.Type == CoherenceResponseType:ACK) {
trigger(Event:Inv_Ack, in_msg.Address);
} else {
error("Invalid response type");
}
}
}
}
// Trigger Queue
in_port(triggerQueue_in, TriggerMsg, triggerQueue) {
if (triggerQueue_in.isReady()) {
peek(triggerQueue_in, TriggerMsg) {
if (in_msg.Type == TriggerType:ALL_ACKS) {
trigger(Event:All_Acks, in_msg.Address);
} else {
error("Unexpected message");
}
}
}
}
action(s_sendReadRequest, "s", desc="Send a DMA read request to memory") {
peek(dmaRequestQueue_in, SequencerMsg) {
enqueue(reqToDirectory_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:DMA_READ;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
out_msg.Destination.add(map_Address_to_Directory(address));
out_msg.Requestor := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
}
action(s_sendWriteRequest, "\s", desc="Send a DMA write request to memory") {
peek(dmaRequestQueue_in, SequencerMsg) {
enqueue(reqToDirectory_out, RequestMsg, latency=request_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:DMA_WRITE;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
out_msg.Destination.add(map_Address_to_Directory(address));
out_msg.Requestor := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
}
action(a_ackCallback, "a", desc="Notify dma controller that write request completed") {
dma_sequencer.ackCallback();
}
action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") {
if (TBEs[address].NumAcks == 0) {
enqueue(triggerQueue_out, TriggerMsg) {
out_msg.Address := address;
out_msg.Type := TriggerType:ALL_ACKS;
}
}
}
action(u_updateAckCount, "u", desc="Update ack count") {
peek(dmaResponseQueue_in, ResponseMsg) {
TBEs[address].NumAcks := TBEs[address].NumAcks - in_msg.Acks;
}
}
action( u_sendExclusiveUnblockToDir, "\u", desc="send exclusive unblock to directory") {
enqueue(respToDirectory_out, ResponseMsg, latency=response_latency) {
out_msg.Address := address;
out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE;
out_msg.Destination.add(map_Address_to_Directory(address));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
action(p_popRequestQueue, "p", desc="Pop request queue") {
dmaRequestQueue_in.dequeue();
}
action(p_popResponseQueue, "\p", desc="Pop request queue") {
dmaResponseQueue_in.dequeue();
}
action(p_popTriggerQueue, "pp", desc="Pop trigger queue") {
triggerQueue_in.dequeue();
}
action(t_updateTBEData, "t", desc="Update TBE Data") {
peek(dmaResponseQueue_in, ResponseMsg) {
TBEs[address].DataBlk := in_msg.DataBlk;
}
}
action(d_dataCallbackFromTBE, "/d", desc="data callback with data from TBE") {
dma_sequencer.dataCallback(TBEs[address].DataBlk);
}
action(v_allocateTBE, "v", desc="Allocate TBE entry") {
TBEs.allocate(address);
}
action(w_deallocateTBE, "w", desc="Deallocate TBE entry") {
TBEs.deallocate(address);
}
action(z_stall, "z", desc="dma is busy..stall") {
// do nothing
}
transition(READY, ReadRequest, BUSY_RD) {
s_sendReadRequest;
v_allocateTBE;
p_popRequestQueue;
}
transition(BUSY_RD, Inv_Ack) {
u_updateAckCount;
o_checkForCompletion;
p_popResponseQueue;
}
transition(BUSY_RD, Data) {
t_updateTBEData;
u_updateAckCount;
o_checkForCompletion;
p_popResponseQueue;
}
transition(BUSY_RD, All_Acks, READY) {
d_dataCallbackFromTBE;
u_sendExclusiveUnblockToDir;
w_deallocateTBE;
p_popTriggerQueue;
}
transition(READY, WriteRequest, BUSY_WR) {
s_sendWriteRequest;
v_allocateTBE;
p_popRequestQueue;
}
transition(BUSY_WR, Inv_Ack) {
u_updateAckCount;
o_checkForCompletion;
p_popResponseQueue;
}
transition(BUSY_WR, DMA_Ack) {
u_updateAckCount; // actually increases
o_checkForCompletion;
p_popResponseQueue;
}
transition(BUSY_WR, All_Acks, READY) {
a_ackCallback;
u_sendExclusiveUnblockToDir;
w_deallocateTBE;
p_popTriggerQueue;
}
}

View File

@@ -44,6 +44,9 @@ enumeration(CoherenceRequestType, desc="...") {
WB_ACK_DATA, desc="Writeback ack";
WB_NACK, desc="Writeback neg. ack";
INV, desc="Invalidation";
DMA_READ, desc="DMA Read";
DMA_WRITE, desc="DMA Write";
}
// CoherenceResponseType
@@ -56,6 +59,8 @@ enumeration(CoherenceResponseType, desc="...") {
WRITEBACK_CLEAN_DATA, desc="Clean writeback (contains data)";
WRITEBACK_CLEAN_ACK, desc="Clean writeback (contains no data)";
WRITEBACK_DIRTY_DATA, desc="Dirty writeback (contains data)";
DMA_ACK, desc="Ack that a DMA write completed";
}
// TriggerType
@@ -72,10 +77,12 @@ structure(TriggerMsg, desc="...", interface="Message") {
// RequestMsg (and also forwarded requests)
structure(RequestMsg, desc="...", interface="NetworkMessage") {
Address Address, desc="Physical address for this request";
int Len, desc="Length of Request";
CoherenceRequestType Type, desc="Type of request (GetS, GetX, PutX, etc)";
MachineID Requestor, desc="Node who initiated the request";
MachineType RequestorMachine, desc="type of component";
NetDest Destination, desc="Multicast destination mask";
DataBlock DataBlk, desc="data for the cache line (DMA WRITE request)";
int Acks, desc="How many acks to expect";
MessageSizeType MessageSize, desc="size category of the message";
AccessModeType AccessMode, desc="user/supervisor access type";
@@ -95,32 +102,4 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") {
MessageSizeType MessageSize, desc="size category of the message";
}
GenericRequestType convertToGenericType(CoherenceRequestType type) {
if(type == CoherenceRequestType:PUTX) {
return GenericRequestType:PUTX;
} else if(type == CoherenceRequestType:GETS) {
return GenericRequestType:GETS;
} else if(type == CoherenceRequestType:GETX) {
return GenericRequestType:GETX;
} else if(type == CoherenceRequestType:PUTS) {
return GenericRequestType:PUTS;
} else if(type == CoherenceRequestType:PUTX) {
return GenericRequestType:PUTS;
} else if(type == CoherenceRequestType:PUTO) {
return GenericRequestType:PUTO;
} else if(type == CoherenceRequestType:PUTO_SHARERS) {
return GenericRequestType:PUTO;
} else if(type == CoherenceRequestType:INV) {
return GenericRequestType:INV;
} else if(type == CoherenceRequestType:WB_ACK) {
return GenericRequestType:WB_ACK;
} else if(type == CoherenceRequestType:WB_ACK_DATA) {
return GenericRequestType:WB_ACK;
} else if(type == CoherenceRequestType:WB_NACK) {
return GenericRequestType:NACK;
} else {
DEBUG_EXPR(type);
error("invalid CoherenceRequestType");
}
}

View File

@@ -1,5 +1,6 @@
MOESI_CMP_directory-msg.sm
MOESI_CMP_directory-L2cache.sm
MOESI_CMP_directory-L1cache.sm
MOESI_CMP_directory-dma.sm
MOESI_CMP_directory-dir.sm
standard_CMP-protocol.sm

View File

@@ -1,652 +0,0 @@
/*
* Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* 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;
* neither the name of the copyright holders 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
* OWNER 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.
*/
/*
* $Id$
*/
machine(Directory, "Directory protocol") {
// ** IN QUEUES **
MessageBuffer foo1, network="From", virtual_network="0", ordered="false"; // a mod-L2 bank -> this Dir
MessageBuffer requestToDir, network="From", virtual_network="1", ordered="false"; // a mod-L2 bank -> this Dir
MessageBuffer responseToDir, network="From", virtual_network="2", ordered="false"; // a mod-L2 bank -> this Dir
MessageBuffer goo1, network="To", virtual_network="0", ordered="false";
MessageBuffer forwardFromDir, network="To", virtual_network="1", ordered="false";
MessageBuffer responseFromDir, network="To", virtual_network="2", ordered="false"; // Dir -> mod-L2 bank
// STATES
enumeration(State, desc="Directory states", default="Directory_State_I") {
// Base states
I, desc="Invalid";
S, desc="Shared";
O, desc="Owner";
M, desc="Modified";
IS, desc="Blocked, was in idle";
SS, desc="Blocked, was in shared";
OO, desc="Blocked, was in owned";
MO, desc="Blocked, going to owner or maybe modified";
MM, desc="Blocked, going to modified";
MI, desc="Blocked on a writeback";
MIS, desc="Blocked on a writeback, but don't remove from sharers when received";
OS, desc="Blocked on a writeback";
OSS, desc="Blocked on a writeback, but don't remove from sharers when received";
}
// Events
enumeration(Event, desc="Directory events") {
GETX, desc="A GETX arrives";
GETS, desc="A GETS arrives";
PUTX, desc="A PUTX arrives";
PUTO, desc="A PUTO arrives";
PUTO_SHARERS, desc="A PUTO arrives, but don't remove from sharers list";
Unblock, desc="An unblock message arrives";
Last_Unblock, desc="An unblock message arrives, we're not waiting for any additional unblocks";
Exclusive_Unblock, desc="The processor become the exclusive owner (E or M) of the line";
Clean_Writeback, desc="The final message as part of a PutX/PutS, no data";
Dirty_Writeback, desc="The final message as part of a PutX/PutS, contains data";
Memory_Data, desc="Fetched data from memory arrives";
Memory_Ack, desc="Writeback Ack from memory arrives";
}
// TYPES
// DirectoryEntry
structure(Entry, desc="...") {
State DirectoryState, desc="Directory state";
DataBlock DataBlk, desc="data for the block";
NetDest Sharers, desc="Sharers for this block";
NetDest Owner, desc="Owner of this block";
int WaitingUnblocks, desc="Number of acks we're waiting for";
}
external_type(DirectoryMemory) {
Entry lookup(Address);
bool isPresent(Address);
}
// to simulate detailed DRAM
external_type(MemoryControl, inport="yes", outport="yes") {
}
// ** OBJECTS **
DirectoryMemory directory, constructor_hack="i";
MemoryControl memBuffer, constructor_hack="i";
State getState(Address addr) {
return directory[addr].DirectoryState;
}
void setState(Address addr, State state) {
if (directory.isPresent(addr)) {
if (state == State:I) {
assert(directory[addr].Owner.count() == 0);
assert(directory[addr].Sharers.count() == 0);
}
if (state == State:S) {
assert(directory[addr].Owner.count() == 0);
}
if (state == State:O) {
assert(directory[addr].Owner.count() == 1);
assert(directory[addr].Sharers.isSuperset(directory[addr].Owner) == false);
}
if (state == State:M) {
assert(directory[addr].Owner.count() == 1);
assert(directory[addr].Sharers.count() == 0);
}
if ((state != State:SS) && (state != State:OO)) {
assert(directory[addr].WaitingUnblocks == 0);
}
if ( (directory[addr].DirectoryState != State:I) && (state == State:I) ) {
directory[addr].DirectoryState := state;
// disable coherence checker
// sequencer.checkCoherence(addr);
}
else {
directory[addr].DirectoryState := state;
}
}
}
// if no sharers, then directory can be considered both a sharer and exclusive w.r.t. coherence checking
bool isBlockShared(Address addr) {
if (directory.isPresent(addr)) {
if (directory[addr].DirectoryState == State:I) {
return true;
}
}
return false;
}
bool isBlockExclusive(Address addr) {
if (directory.isPresent(addr)) {
if (directory[addr].DirectoryState == State:I) {
return true;
}
}
return false;
}
// ** OUT_PORTS **
out_port(forwardNetwork_out, RequestMsg, forwardFromDir);
out_port(responseNetwork_out, ResponseMsg, responseFromDir);
// out_port(requestQueue_out, ResponseMsg, requestFromDir); // For recycling requests
out_port(goo1_out, ResponseMsg, goo1);
out_port(memQueue_out, MemoryMsg, memBuffer);
// ** IN_PORTS **
in_port(foo1_in, ResponseMsg, foo1) {
}
// in_port(unblockNetwork_in, ResponseMsg, unblockToDir) {
// if (unblockNetwork_in.isReady()) {
in_port(unblockNetwork_in, ResponseMsg, responseToDir) {
if (unblockNetwork_in.isReady()) {
peek(unblockNetwork_in, ResponseMsg) {
if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
if (directory[in_msg.Address].WaitingUnblocks == 1) {
trigger(Event:Last_Unblock, in_msg.Address);
} else {
trigger(Event:Unblock, in_msg.Address);
}
} else if (in_msg.Type == CoherenceResponseType:UNBLOCK_EXCLUSIVE) {
trigger(Event:Exclusive_Unblock, in_msg.Address);
} else if (in_msg.Type == CoherenceResponseType:WRITEBACK_DIRTY_DATA) {
trigger(Event:Dirty_Writeback, in_msg.Address);
} else if (in_msg.Type == CoherenceResponseType:WRITEBACK_CLEAN_ACK) {
trigger(Event:Clean_Writeback, in_msg.Address);
} else {
error("Invalid message");
}
}
}
}
in_port(requestQueue_in, RequestMsg, requestToDir) {
if (requestQueue_in.isReady()) {
peek(requestQueue_in, RequestMsg) {
if (in_msg.Type == CoherenceRequestType:GETS) {
trigger(Event:GETS, in_msg.Address);
} else if (in_msg.Type == CoherenceRequestType:GETX) {
trigger(Event:GETX, in_msg.Address);
} else if (in_msg.Type == CoherenceRequestType:PUTX) {
trigger(Event:PUTX, in_msg.Address);
} else if (in_msg.Type == CoherenceRequestType:PUTO) {
trigger(Event:PUTO, in_msg.Address);
} else if (in_msg.Type == CoherenceRequestType:PUTO_SHARERS) {
trigger(Event:PUTO_SHARERS, in_msg.Address);
} else {
error("Invalid message");
}
}
}
}
// off-chip memory request/response is done
in_port(memQueue_in, MemoryMsg, memBuffer) {
if (memQueue_in.isReady()) {
peek(memQueue_in, MemoryMsg) {
if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
trigger(Event:Memory_Data, in_msg.Address);
} else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
trigger(Event:Memory_Ack, in_msg.Address);
} else {
DEBUG_EXPR(in_msg.Type);
error("Invalid message");
}
}
}
}
// Actions
action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") {
peek(requestQueue_in, RequestMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:WB_ACK;
out_msg.Requestor := in_msg.Requestor;
out_msg.Destination.add(in_msg.Requestor);
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
}
action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") {
peek(requestQueue_in, RequestMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:WB_NACK;
out_msg.Requestor := in_msg.Requestor;
out_msg.Destination.add(in_msg.Requestor);
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
}
action(c_clearOwner, "c", desc="Clear the owner field") {
directory[address].Owner.clear();
}
action(c_moveOwnerToSharer, "cc", desc="Move owner to sharers") {
directory[address].Sharers.addNetDest(directory[address].Owner);
directory[address].Owner.clear();
}
action(cc_clearSharers, "\c", desc="Clear the sharers field") {
directory[address].Sharers.clear();
}
action(d_sendDataMsg, "d", desc="Send data to requestor") {
peek(memQueue_in, MemoryMsg) {
enqueue(responseNetwork_out, ResponseMsg, latency="1") {
out_msg.Address := address;
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:Directory;
out_msg.Destination.add(in_msg.OriginalRequestorMachId);
//out_msg.DataBlk := directory[in_msg.Address].DataBlk;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Dirty := false; // By definition, the block is now clean
out_msg.Acks := in_msg.Acks;
if (in_msg.ReadX) {
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
} else {
out_msg.Type := CoherenceResponseType:DATA;
}
out_msg.MessageSize := MessageSizeType:Response_Data;
}
}
}
action(e_ownerIsUnblocker, "e", desc="The owner is now the unblocker") {
peek(unblockNetwork_in, ResponseMsg) {
directory[address].Owner.clear();
directory[address].Owner.add(in_msg.Sender);
}
}
action(f_forwardRequest, "f", desc="Forward request to owner") {
peek(requestQueue_in, RequestMsg) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
out_msg.Address := address;
out_msg.Type := in_msg.Type;
out_msg.Requestor := in_msg.Requestor;
out_msg.Destination.addNetDest(directory[in_msg.Address].Owner);
out_msg.Acks := directory[address].Sharers.count();
if (directory[address].Sharers.isElement(in_msg.Requestor)) {
out_msg.Acks := out_msg.Acks - 1;
}
out_msg.MessageSize := MessageSizeType:Forwarded_Control;
}
}
}
action(g_sendInvalidations, "g", desc="Send invalidations to sharers, not including the requester") {
peek(requestQueue_in, RequestMsg) {
if ((directory[in_msg.Address].Sharers.count() > 1) ||
((directory[in_msg.Address].Sharers.count() > 0) && (directory[in_msg.Address].Sharers.isElement(in_msg.Requestor) == false))) {
enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
out_msg.Address := address;
out_msg.Type := CoherenceRequestType:INV;
out_msg.Requestor := in_msg.Requestor;
// out_msg.Destination := directory[in_msg.Address].Sharers;
out_msg.Destination.addNetDest(directory[in_msg.Address].Sharers);
out_msg.Destination.remove(in_msg.Requestor);
out_msg.MessageSize := MessageSizeType:Invalidate_Control;
}
}
}
}
action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") {
requestQueue_in.dequeue();
}
action(j_popIncomingUnblockQueue, "j", desc="Pop incoming unblock queue") {
unblockNetwork_in.dequeue();
}
action(l_writeDataToMemory, "l", desc="Write PUTX/PUTO data to memory") {
peek(unblockNetwork_in, ResponseMsg) {
assert(in_msg.Dirty);
assert(in_msg.MessageSize == MessageSizeType:Writeback_Data);
directory[in_msg.Address].DataBlk := in_msg.DataBlk;
DEBUG_EXPR(in_msg.Address);
DEBUG_EXPR(in_msg.DataBlk);
}
}
action(ll_checkDataInMemory, "\l", desc="Check PUTX/PUTO data is same as in the memory") {
peek(unblockNetwork_in, ResponseMsg) {
assert(in_msg.Dirty == false);
assert(in_msg.MessageSize == MessageSizeType:Writeback_Control);
// NOTE: The following check would not be valid in a real
// implementation. We include the data in the "dataless"
// message so we can assert the clean data matches the datablock
// in memory
assert(directory[in_msg.Address].DataBlk == in_msg.DataBlk);
}
}
action(m_addUnlockerToSharers, "m", desc="Add the unlocker to the sharer list") {
peek(unblockNetwork_in, ResponseMsg) {
directory[address].Sharers.add(in_msg.Sender);
}
}
action(n_incrementOutstanding, "n", desc="Increment outstanding requests") {
directory[address].WaitingUnblocks := directory[address].WaitingUnblocks + 1;
}
action(o_decrementOutstanding, "o", desc="Decrement outstanding requests") {
directory[address].WaitingUnblocks := directory[address].WaitingUnblocks - 1;
assert(directory[address].WaitingUnblocks >= 0);
}
action(q_popMemQueue, "q", desc="Pop off-chip request queue") {
memQueue_in.dequeue();
}
action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") {
peek(requestQueue_in, RequestMsg) {
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_READ;
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.DataBlk := directory[in_msg.Address].DataBlk;
out_msg.MessageSize := in_msg.MessageSize;
//out_msg.Prefetch := false;
// These are not used by memory but are passed back here with the read data:
out_msg.ReadX := (in_msg.Type == CoherenceRequestType:GETS && directory[address].Sharers.count() == 0);
out_msg.Acks := directory[address].Sharers.count();
if (directory[address].Sharers.isElement(in_msg.Requestor)) {
out_msg.Acks := out_msg.Acks - 1;
}
DEBUG_EXPR(out_msg);
}
}
}
action(qw_queueMemoryWBRequest, "qw", desc="Queue off-chip writeback request") {
peek(unblockNetwork_in, ResponseMsg) {
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.Sender := machineID;
//out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.MessageSize := in_msg.MessageSize;
//out_msg.Prefetch := false;
// Not used:
out_msg.ReadX := false;
out_msg.Acks := 0;
DEBUG_EXPR(out_msg);
}
}
}
// action(z_stall, "z", desc="Cannot be handled right now.") {
// Special name recognized as do nothing case
// }
action(zz_recycleRequest, "\z", desc="Recycle the request queue") {
requestQueue_in.recycle();
}
// TRANSITIONS
transition(I, GETX, MM) {
qf_queueMemoryFetchRequest;
i_popIncomingRequestQueue;
}
transition(S, GETX, MM) {
qf_queueMemoryFetchRequest;
g_sendInvalidations;
i_popIncomingRequestQueue;
}
transition(I, GETS, IS) {
qf_queueMemoryFetchRequest;
i_popIncomingRequestQueue;
}
transition({S, SS}, GETS, SS) {
qf_queueMemoryFetchRequest;
n_incrementOutstanding;
i_popIncomingRequestQueue;
}
transition({I, S}, PUTO) {
b_sendWriteBackNack;
i_popIncomingRequestQueue;
}
transition({I, S, O}, PUTX) {
b_sendWriteBackNack;
i_popIncomingRequestQueue;
}
transition(O, GETX, MM) {
f_forwardRequest;
g_sendInvalidations;
i_popIncomingRequestQueue;
}
transition({O, OO}, GETS, OO) {
f_forwardRequest;
n_incrementOutstanding;
i_popIncomingRequestQueue;
}
transition(M, GETX, MM) {
f_forwardRequest;
i_popIncomingRequestQueue;
}
transition(M, GETS, MO) {
f_forwardRequest;
i_popIncomingRequestQueue;
}
transition(M, PUTX, MI) {
a_sendWriteBackAck;
i_popIncomingRequestQueue;
}
// happens if M->O transition happens on-chip
transition(M, PUTO, MI) {
a_sendWriteBackAck;
i_popIncomingRequestQueue;
}
transition(M, PUTO_SHARERS, MIS) {
a_sendWriteBackAck;
i_popIncomingRequestQueue;
}
transition(O, PUTO, OS) {
a_sendWriteBackAck;
i_popIncomingRequestQueue;
}
transition(O, PUTO_SHARERS, OSS) {
a_sendWriteBackAck;
i_popIncomingRequestQueue;
}
transition({MM, MO, MI, MIS, OS, OSS}, {GETS, GETX, PUTO, PUTO_SHARERS, PUTX}) {
zz_recycleRequest;
}
transition({MM, MO}, Exclusive_Unblock, M) {
cc_clearSharers;
e_ownerIsUnblocker;
j_popIncomingUnblockQueue;
}
transition(MO, Unblock, O) {
m_addUnlockerToSharers;
j_popIncomingUnblockQueue;
}
transition({IS, SS, OO}, {GETX, PUTO, PUTO_SHARERS, PUTX}) {
zz_recycleRequest;
}
transition(IS, GETS) {
zz_recycleRequest;
}
transition(IS, Unblock, S) {
m_addUnlockerToSharers;
j_popIncomingUnblockQueue;
}
transition(IS, Exclusive_Unblock, M) {
cc_clearSharers;
e_ownerIsUnblocker;
j_popIncomingUnblockQueue;
}
transition(SS, Unblock) {
m_addUnlockerToSharers;
o_decrementOutstanding;
j_popIncomingUnblockQueue;
}
transition(SS, Last_Unblock, S) {
m_addUnlockerToSharers;
o_decrementOutstanding;
j_popIncomingUnblockQueue;
}
transition(OO, Unblock) {
m_addUnlockerToSharers;
o_decrementOutstanding;
j_popIncomingUnblockQueue;
}
transition(OO, Last_Unblock, O) {
m_addUnlockerToSharers;
o_decrementOutstanding;
j_popIncomingUnblockQueue;
}
transition(MI, Dirty_Writeback, I) {
c_clearOwner;
cc_clearSharers;
l_writeDataToMemory;
qw_queueMemoryWBRequest;
j_popIncomingUnblockQueue;
}
transition(MIS, Dirty_Writeback, S) {
c_moveOwnerToSharer;
l_writeDataToMemory;
qw_queueMemoryWBRequest;
j_popIncomingUnblockQueue;
}
transition(MIS, Clean_Writeback, S) {
c_moveOwnerToSharer;
j_popIncomingUnblockQueue;
}
transition(OS, Dirty_Writeback, S) {
c_clearOwner;
l_writeDataToMemory;
qw_queueMemoryWBRequest;
j_popIncomingUnblockQueue;
}
transition(OSS, Dirty_Writeback, S) {
c_moveOwnerToSharer;
l_writeDataToMemory;
qw_queueMemoryWBRequest;
j_popIncomingUnblockQueue;
}
transition(OSS, Clean_Writeback, S) {
c_moveOwnerToSharer;
j_popIncomingUnblockQueue;
}
transition(MI, Clean_Writeback, I) {
c_clearOwner;
cc_clearSharers;
ll_checkDataInMemory;
j_popIncomingUnblockQueue;
}
transition(OS, Clean_Writeback, S) {
c_clearOwner;
ll_checkDataInMemory;
j_popIncomingUnblockQueue;
}
transition({MI, MIS}, Unblock, M) {
j_popIncomingUnblockQueue;
}
transition({OS, OSS}, Unblock, O) {
j_popIncomingUnblockQueue;
}
transition({I, S, O, M, IS, SS, OO, MO, MM, MI, MIS, OS, OSS}, Memory_Data) {
d_sendDataMsg;
q_popMemQueue;
}
transition({I, S, O, M, IS, SS, OO, MO, MM, MI, MIS, OS, OSS}, Memory_Ack) {
//a_sendAck;
q_popMemQueue;
}
}

View File

@@ -1,5 +0,0 @@
MOESI_CMP_directory-msg.sm
MOESI_CMP_directory-L2cache.sm
MOESI_CMP_directory-L1cache.sm
MOESI_CMP_directory_m-dir.sm
standard_CMP-protocol.sm

View File

@@ -30,14 +30,11 @@
// Mapping functions
// NodeID map_address_to_node(Address addr);
MachineID mapAddressToRange(Address addr, MachineType type, int low, int high);
MachineID map_Address_to_DMA(Address addr);
MachineID map_Address_to_Directory(Address addr);
NodeID map_Address_to_DirectoryNode(Address addr);
MachineID map_Address_to_CentralArbiterNode(Address addr);
NodeID oldmap_L1RubyNode_to_L2Cache(Address addr, NodeID L1RubyNode);
MachineID map_L1CacheMachId_to_L2Cache(Address addr, MachineID L1CacheMachId);
MachineID map_L2ChipId_to_L2Cache(Address addr, NodeID L2ChipId);
// MachineID map_L1RubyNode_to_Arb(NodeID L1RubyNode);
MachineID getL1MachineID(NodeID L1RubyNode);
NodeID getChipID(MachineID L2machID);

View File

@@ -39,7 +39,10 @@ external_type(string, primitive="yes");
external_type(uint64, primitive="yes");
external_type(Time, primitive="yes", default="0");
external_type(Address);
external_type(DataBlock, desc="..."){
void clear();
void copyPartial(DataBlock, int, int);
}
// Declarations of external types that are common to all protocols
@@ -131,12 +134,12 @@ enumeration(CacheRequestType, desc="...", default="CacheRequestType_NULL") {
IO, desc="I/O";
REPLACEMENT, desc="Replacement";
COMMIT, desc="Commit version";
LD_XACT, desc="Transactional Load";
LDX_XACT, desc="Transactional Load-Intend-To-Modify";
ST_XACT, desc="Transactional Store";
BEGIN_XACT, desc="Begin Transaction";
COMMIT_XACT, desc="Commit Transaction";
ABORT_XACT, desc="Abort Transaction";
NULL, desc="Invalid request type";
}
enumeration(SequencerRequestType, desc="...", default="SequencerRequestType_NULL") {
LD, desc="Load";
ST, desc="Store";
NULL, desc="Invalid request type";
}
@@ -167,7 +170,9 @@ enumeration(GenericRequestType, desc="...", default="GenericRequestType_NULL") {
ST_XACT, desc="Transactional Store";
BEGIN_XACT, desc="Begin Transaction";
COMMIT_XACT, desc="Commit Transaction";
ABORT_XACT, desc="Abort Transaction";
ABORT_XACT, desc="Abort Transaction";
DMA_READ, desc="DMA READ";
DMA_WRITE, desc="DMA WRITE";
NULL, desc="null request type";
}
@@ -232,6 +237,18 @@ structure(CacheMsg, desc="...", interface="Message") {
PrefetchBit Prefetch, desc="Is this a prefetch request";
}
// CacheMsg
structure(SequencerMsg, desc="...", interface="Message") {
Address LineAddress, desc="Line address for this request";
Address PhysicalAddress, desc="Physical address for this request";
SequencerRequestType Type, desc="Type of request (LD, ST, etc)";
Address ProgramCounter, desc="Program counter of the instruction that caused the miss";
AccessModeType AccessMode, desc="user/supervisor access type";
DataBlock DataBlk, desc="Data";
int Len, desc="size in bytes of access";
PrefetchBit Prefetch, desc="Is this a prefetch request";
}
// MaskPredictorType
enumeration(MaskPredictorType, "MaskPredictorType_Undefined", desc="...") {
Undefined, desc="Undefined";

View File

@@ -34,7 +34,7 @@ void profileCacheCLBsize(int size, int numStaleI);
void profileMemoryCLBsize(int size, int numStaleI);
// used by 2level exclusive cache protocols
void profile_miss(CacheMsg msg, NodeID id);
void profile_miss(CacheMsg msg);
// used by non-fast path protocols
void profile_L1Cache_miss(CacheMsg msg, NodeID l1cacheID);

View File

@@ -29,11 +29,6 @@
// External Types
external_type(DataBlock, desc="..."){
void clear();
void copyPartial(DataBlock, int, int);
}
external_type(MessageBuffer, buffer="yes", inport="yes", outport="yes");
external_type(OutPort, primitive="yes");

View File

@@ -57,5 +57,5 @@ int N_tokens();
bool distributedPersistentEnabled();
Address setOffset(Address addr, int offset);
Address makeLineAddress(Address addr);
int addressOffset(Address addr);

View File

@@ -61,7 +61,7 @@ def slicc_generator(target, source, env, for_signature):
if not isdir(hdir):
os.mkdir(hdir)
do_html = "no_html"
do_html = "html"
cmdline = [ slicc_bin, pdir, hdir, protocol, do_html ]
cmdline += [ str(s) for s in source[2:] ]
cmdline = ' '.join(cmdline)

View File

@@ -8,20 +8,27 @@
require "cfg.rb"
RubySystem.reset
# default values
num_cores = 2
L1_CACHE_SIZE_KB = 32
L1_CACHE_ASSOC = 8
L1_CACHE_LATENCY = 1
l1_cache_size_kb = 32
l1_cache_assoc = 8
l1_cache_latency = 1
num_memories = 2
memory_size_mb = 1024
NUM_DMA = 1
num_dma = 1
protocol = "MI_example"
# check for overrides
for i in 0..$*.size-1 do
if $*[i] == "-p"
if $*[i] == "-c"
protocol = $*[i+1]
i = i+1
elsif $*[i] == "-p"
num_cores = $*[i+1].to_i
i = i+1
elsif $*[i] == "-m"
@@ -36,13 +43,17 @@ end
net_ports = Array.new
iface_ports = Array.new
assert(protocol == "MI_example", __FILE__ + " cannot be used with protocol " + protocol)
require protocol+".rb"
num_cores.times { |n|
cache = SetAssociativeCache.new("l1u_"+n.to_s, L1_CACHE_SIZE_KB, L1_CACHE_LATENCY, L1_CACHE_ASSOC, "PSEUDO_LRU")
cache = SetAssociativeCache.new("l1u_"+n.to_s, l1_cache_size_kb, l1_cache_latency, l1_cache_assoc, "PSEUDO_LRU")
sequencer = Sequencer.new("Sequencer_"+n.to_s, cache, cache)
iface_ports << sequencer
net_ports << MI_example_CacheController.new("L1CacheController_"+n.to_s,
"L1Cache",
[cache],
cache,
sequencer)
}
num_memories.times { |n|
@@ -52,10 +63,10 @@ num_memories.times { |n|
"Directory",
directory, memory_control)
}
NUM_DMA.times { |n|
num_dma.times { |n|
dma_sequencer = DMASequencer.new("DMASequencer_"+n.to_s)
iface_ports << dma_sequencer
net_ports << DMAController.new("DMAController_"+n.to_s, "DMA", dma_sequencer)
net_ports << MI_example_DMAController.new("DMAController_"+n.to_s, "DMA", dma_sequencer)
}
topology = CrossbarTopology.new("theTopology", net_ports)

View File

@@ -0,0 +1,39 @@
require "util.rb"
class MI_example_CacheController < L1CacheController
attr :cache
def initialize(obj_name, mach_type, cache, sequencer)
super(obj_name, mach_type, [cache], sequencer)
@cache = cache
end
def argv()
vec = super()
vec += " cache " + @cache.obj_name
vec += " issue_latency "+issue_latency.to_s
vec += " cache_response_latency "+cache_response_latency.to_s
end
end
class MI_example_DirectoryController < DirectoryController
def initialize(obj_name, mach_type, directory, memory_control)
super(obj_name, mach_type, directory, memory_control)
end
def argv()
vec = super()
vec += " directory_latency "+directory_latency.to_s
vec += " dma_select_low_bit "+log_int(RubySystem.block_size_bytes).to_s
vec += " dma_select_num_bits "+log_int(NetPort.totalOfType("DMA")).to_s
end
end
class MI_example_DMAController < DMAController
def initialize(obj_name, mach_type, dma_sequencer)
super(obj_name, mach_type, dma_sequencer)
end
def argv()
vec = super
vec += " request_latency "+request_latency.to_s
end
end

View File

@@ -0,0 +1,69 @@
require "cfg.rb"
require "util.rb"
class MOESI_CMP_directory_L1CacheController < L1CacheController
attr :icache, :dcache
attr :num_l2_controllers
def initialize(obj_name, mach_type, icache, dcache, sequencer, num_l2_controllers)
super(obj_name, mach_type, [icache, dcache], sequencer)
@icache = icache
@dcache = dcache
@num_l2_controllers = num_l2_controllers
end
def argv()
num_select_bits = log_int(num_l2_controllers)
num_block_bits = log_int(RubySystem.block_size_bytes)
l2_select_low_bit = num_block_bits
vec = super()
vec += " icache " + @icache.obj_name
vec += " dcache " + @dcache.obj_name
vec += " request_latency "+request_latency().to_s
vec += " l2_select_low_bit " + l2_select_low_bit.to_s
vec += " l2_select_num_bits " + num_select_bits.to_s
return vec
end
end
class MOESI_CMP_directory_L2CacheController < CacheController
attr :cache
def initialize(obj_name, mach_type, cache)
super(obj_name, mach_type, [cache])
@cache = cache
end
def argv()
vec = super()
vec += " cache " + @cache.obj_name
vec += " request_latency "+request_latency().to_s
vec += " response_latency "+response_latency().to_s
return vec
end
end
class MOESI_CMP_directory_DirectoryController < DirectoryController
def initialize(obj_name, mach_type, directory, memory_control)
super(obj_name, mach_type, directory, memory_control)
end
def argv()
vec = super()
vec += " directory_latency "+directory_latency.to_s
return vec
end
end
class MOESI_CMP_directory_DMAController < DMAController
def initialize(obj_name, mach_type, dma_sequencer)
super(obj_name, mach_type, dma_sequencer)
end
def argv()
vec = super
vec += " request_latency "+request_latency.to_s
vec += " response_latency "+response_latency.to_s
return vec
end
end

View File

@@ -0,0 +1,100 @@
#!/usr/bin/ruby
#
# Creates a homogeneous CMP system with a single unified cache per
# core and a crossbar network. Uses the default parameters listed
# below, which can be overridden using command line args.
#
require "cfg.rb"
RubySystem.reset
# default values
num_cores = 2
l1_icache_size_kb = 32
l1_icache_assoc = 8
l1_icache_latency = 1
l1_dcache_size_kb = 32
l1_dcache_assoc = 8
l1_dcache_latency = 1
l2_cache_size_kb = 2048 # total size (sum of all banks)
l2_cache_assoc = 16
l2_cache_latency = 12
num_l2_banks = num_cores
num_memories = 1
memory_size_mb = 1024
num_dma = 1
protocol = "MOESI_CMP_directory"
# check for overrides
for i in 0..$*.size-1 do
if $*[i] == "-c" or $*[i] == "--protocol"
i += 1
protocol = $*[i]
elsif $*[i] == "-m"
num_memories = $*[i+1].to_i
i = i+1
elsif $*[i] == "-p"
num_cores = $*[i+1].to_i
i = i+1
elsif $*[i] == "-s"
memory_size_mb = $*[i+1].to_i
i = i + 1
end
end
net_ports = Array.new
iface_ports = Array.new
assert(protocol == "MOESI_CMP_directory", __FILE__+" cannot be used with protocol "+protocol);
require protocol+".rb"
num_cores.times { |n|
icache = SetAssociativeCache.new("l1i_"+n.to_s, l1_icache_size_kb, l1_icache_latency, l1_icache_assoc, "PSEUDO_LRU")
dcache = SetAssociativeCache.new("l1d_"+n.to_s, l1_dcache_size_kb, l1_dcache_latency, l1_dcache_assoc, "PSEUDO_LRU")
sequencer = Sequencer.new("Sequencer_"+n.to_s, icache, dcache)
iface_ports << sequencer
if protocol == "MOESI_CMP_directory"
net_ports << MOESI_CMP_directory_L1CacheController.new("L1CacheController_"+n.to_s,
"L1Cache",
icache, dcache,
sequencer,
num_l2_banks)
end
}
num_l2_banks.times { |n|
cache = SetAssociativeCache.new("l2u_"+n.to_s, l2_cache_size_kb/num_l2_banks, l2_cache_latency, l2_cache_assoc, "PSEUDO_LRU")
if protocol == "MOESI_CMP_directory"
net_ports << MOESI_CMP_directory_L2CacheController.new("L2CacheController_"+n.to_s,
"L2Cache",
cache)
end
}
num_memories.times { |n|
directory = DirectoryMemory.new("DirectoryMemory_"+n.to_s, memory_size_mb/num_memories)
memory_control = MemoryControl.new("MemoryControl_"+n.to_s)
if protocol == "MOESI_CMP_directory"
net_ports << MOESI_CMP_directory_DirectoryController.new("DirectoryController_"+n.to_s,
"Directory",
directory,
memory_control)
end
}
num_dma.times { |n|
dma_sequencer = DMASequencer.new("DMASequencer_"+n.to_s)
iface_ports << dma_sequencer
if protocol == "MOESI_CMP_directory"
net_ports << MOESI_CMP_directory_DMAController.new("DMAController_"+n.to_s,
"DMA",
dma_sequencer)
end
}
topology = CrossbarTopology.new("theTopology", net_ports)
on_chip_net = Network.new("theNetwork", topology)
RubySystem.init(iface_ports, on_chip_net)

View File

@@ -150,6 +150,9 @@ class NetPort < LibRubyObject
def cppClassName
"NetPort"
end
def self.totalOfType(mach_type)
return @@type_cnt[mach_type]
end
end
class MemoryVector < LibRubyObject
@@ -190,6 +193,7 @@ end
class RubySystem
@@params = Hash.new
@@defaults = Hash.new
@@network = nil
def self.init(iface_ports, network)
@@ -197,6 +201,14 @@ class RubySystem
@@network = network
end
def self.reset()
@@iface_ports = nil
@@network = nil
@@params.each { |param_name, param|
param = @@defaults[param_name]
}
end
def self.default_param(param_name, type, default)
if default.is_a?(FalseClass) || default.is_a?(TrueClass)
assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false"
@@ -204,6 +216,7 @@ class RubySystem
assert default.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}"
end
@@params[param_name] = default
@@defaults[param_name] = default
method_name = (param_name.to_s).to_sym
instance_eval <<-EOS
def #{method_name.to_s}
@@ -233,6 +246,7 @@ class RubySystem
end
}
str += LibRubyObject.printConstructors
#puts str.gsub('%',' ').gsub('#','\n')
return str
end
@@ -287,35 +301,33 @@ end
class CacheController < NetPort
@@total_cache_controllers = 0
attr :caches
attr :sequencer
def initialize(obj_name, mach_type, caches, sequencer)
@@total_cache_controllers = Hash.new
def initialize(obj_name, mach_type, caches)
super(obj_name, mach_type)
@caches = caches
@caches.each { |cache|
caches.each { |cache|
cache.controller = self
}
@sequencer = sequencer
@sequencer.controller = self
@version = @@total_cache_controllers
@@total_cache_controllers += 1
@sequencer.version = @version
buffer_size()
if !@@total_cache_controllers.has_key?(mach_type)
@@total_cache_controllers[mach_type] = 0
end
@version = @@total_cache_controllers[mach_type]
@@total_cache_controllers[mach_type] += 1
# call inhereted parameters
transitions_per_cycle
buffer_size
number_of_TBEs
recycle_latency
end
def argv()
vec = "version "+@version.to_s
@caches.each { |cache|
vec += " cache " + cache.obj_name
}
vec += " sequencer "+@sequencer.obj_name
vec += " transitions_per_cycle "+@params[:transitions_per_cycle].to_s
vec += " buffer_size "+@params[:buffer_size].to_s
vec += " number_of_TBEs "+@params[:number_of_TBEs].to_s
vec += " recycle_latency "+@params[:recycle_latency].to_s
end
def cppClassName()
@@ -323,6 +335,23 @@ class CacheController < NetPort
end
end
class L1CacheController < CacheController
attr :sequencer
def initialize(obj_name, mach_type, caches, sequencer)
super(obj_name, mach_type, caches)
@sequencer = sequencer
@sequencer.controller = self
@sequencer.version = @version
end
def argv()
vec = super()
vec += " sequencer "+@sequencer.obj_name
end
end
class DirectoryController < NetPort
@@total_directory_controllers = 0
attr :directory
@@ -364,7 +393,7 @@ class DMAController < NetPort
end
def argv()
"version "+@version.to_s+" dma_sequencer "+@dma_sequencer.obj_name+" transitions_per_cycle "+@params[:transitions_per_cycle].to_s + " buffer_size "+@params[:buffer_size].to_s + " number_of_TBEs "+@params[:number_of_TBEs].to_s
"version "+@version.to_s+" dma_sequencer "+@dma_sequencer.obj_name+" transitions_per_cycle "+@params[:transitions_per_cycle].to_s + " buffer_size "+@params[:buffer_size].to_s + " number_of_TBEs "+@params[:number_of_TBEs].to_s + " recycle_latency "+@params[:recycle_latency].to_s
end
def cppClassName()
@@ -606,7 +635,7 @@ class Network < LibRubyObject
end
def printTopology()
topology.printFile
topology().printFile
end
def cppClassName()
"SimpleNetwork"
@@ -686,31 +715,6 @@ class Profiler < LibRubyObject
end
class MI_example_CacheController < CacheController
def initialize(obj_name, mach_type, caches, sequencer)
super(obj_name, mach_type, caches, sequencer)
end
def argv()
vec = super()
vec += " issue_latency "+issue_latency.to_s
vec += " cache_response_latency "+cache_response_latency.to_s
end
end
class MI_example_DirectoryController < DirectoryController
def initialize(obj_name, mach_type, directory, memory_control)
super(obj_name, mach_type, directory, memory_control)
end
def argv()
vec = super()
vec += " to_mem_ctrl_latency "+to_mem_ctrl_latency.to_s
vec += " directory_latency "+directory_latency.to_s
vec += " memory_latency "+memory_latency.to_s
end
end
#added by SS
class GarnetNetwork < Network
def initialize(name, topo)

View File

@@ -105,19 +105,6 @@ class Profiler < LibRubyObject
default_param :all_instructions, Boolean, false
end
#added by SS
class MI_example_CacheController < CacheController
default_param :issue_latency, Integer, 2
default_param :cache_response_latency, Integer, 12
end
class MI_example_DirectoryController < DirectoryController
default_param :to_mem_ctrl_latency, Integer, 1
default_param :directory_latency, Integer, 6
default_param :memory_latency, Integer, 158
end
#added by SS
class MemoryControl < LibRubyObject
@@ -141,6 +128,43 @@ class MemoryControl < LibRubyObject
end
###### Protocols #######
## MI_example protocol
class MI_example_CacheController < L1CacheController
default_param :issue_latency, Integer, 2
default_param :cache_response_latency, Integer, 12
end
class MI_example_DirectoryController < DirectoryController
default_param :directory_latency, Integer, 6
end
class MI_example_DMAController < DMAController
default_param :request_latency, Integer, 6
end
## MOESI_CMP_directory protocol
class MOESI_CMP_directory_L1CacheController < L1CacheController
default_param :request_latency, Integer, 2
end
class MOESI_CMP_directory_L2CacheController < CacheController
default_param :request_latency, Integer, 2
default_param :response_latency, Integer, 2
end
class MOESI_CMP_directory_DirectoryController < DirectoryController
default_param :directory_latency, Integer, 6
end
class MOESI_CMP_directory_DMAController < DMAController
default_param :request_latency, Integer, 6
default_param :response_latency, Integer, 6
end
class RubySystem
# Random seed used by the simulation. If set to "rand", the seed

View File

@@ -0,0 +1,10 @@
def log_int(n)
assert(n.is_a?(Fixnum), "log_int takes a number for an argument")
counter = 0
while n >= 2 do
counter += 1
n = n >> 1
end
return counter
end

View File

@@ -85,6 +85,16 @@ MachineID map_Address_to_DMA(const Address & addr)
return dma;
}
inline
MachineID mapAddressToRange(const Address & addr, MachineType type, int low_bit, int num_bits)
{
MachineID mach = {type, 0};
if (num_bits == 0)
return mach;
mach.num = addr.bitSelect(low_bit, low_bit+num_bits-1);
return mach;
}
extern inline NodeID machineIDToNodeID(MachineID machID)
{
return machID.num;

View File

@@ -173,4 +173,9 @@ extern inline Address makeLineAddress(Address addr)
return result;
}
extern inline int addressOffset(Address addr)
{
return addr.getOffset();
}
#endif //SLICC_UTIL_H

View File

@@ -4,9 +4,8 @@
#include "mem/ruby/slicc_interface/AbstractController.hh"
/* SLICC generated types */
#include "mem/protocol/DMARequestMsg.hh"
#include "mem/protocol/DMARequestType.hh"
#include "mem/protocol/DMAResponseMsg.hh"
#include "mem/protocol/SequencerMsg.hh"
#include "mem/protocol/SequencerRequestType.hh"
#include "mem/ruby/system/System.hh"
DMASequencer::DMASequencer(const string & name)
@@ -66,20 +65,16 @@ int64_t DMASequencer::makeRequest(const RubyRequest & request)
active_request.bytes_issued = 0;
active_request.id = makeUniqueRequestID();
DMARequestMsg msg;
SequencerMsg msg;
msg.getPhysicalAddress() = Address(paddr);
msg.getLineAddress() = line_address(msg.getPhysicalAddress());
msg.getType() = write ? DMARequestType_WRITE : DMARequestType_READ;
msg.getOffset() = paddr & m_data_block_mask;
msg.getLen() = (msg.getOffset() + len) <= RubySystem::getBlockSizeBytes() ?
msg.getType() = write ? SequencerRequestType_ST : SequencerRequestType_LD;
int offset = paddr & m_data_block_mask;
msg.getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ?
len :
RubySystem::getBlockSizeBytes() - msg.getOffset();
if (write) {
msg.getType() = DMARequestType_WRITE;
msg.getDataBlk().setData(data, msg.getOffset(), msg.getLen());
} else {
msg.getType() = DMARequestType_READ;
}
RubySystem::getBlockSizeBytes() - offset;
if (write)
msg.getDataBlk().setData(data, offset, msg.getLen());
m_mandatory_q_ptr->enqueue(msg);
active_request.bytes_issued += msg.getLen();
@@ -96,14 +91,13 @@ void DMASequencer::issueNext()
return;
}
DMARequestMsg msg;
SequencerMsg msg;
msg.getPhysicalAddress() = Address(active_request.start_paddr +
active_request.bytes_completed);
assert((msg.getPhysicalAddress().getAddress() & m_data_block_mask) == 0);
msg.getLineAddress() = line_address(msg.getPhysicalAddress());
msg.getOffset() = 0;
msg.getType() = (active_request.write ? DMARequestType_WRITE :
DMARequestType_READ);
msg.getType() = (active_request.write ? SequencerRequestType_ST :
SequencerRequestType_LD);
msg.getLen() = (active_request.len -
active_request.bytes_completed < RubySystem::getBlockSizeBytes() ?
active_request.len - active_request.bytes_completed :
@@ -111,9 +105,9 @@ void DMASequencer::issueNext()
if (active_request.write) {
msg.getDataBlk().setData(&active_request.data[active_request.bytes_completed],
0, msg.getLen());
msg.getType() = DMARequestType_WRITE;
msg.getType() = SequencerRequestType_ST;
} else {
msg.getType() = DMARequestType_READ;
msg.getType() = SequencerRequestType_LD;
}
m_mandatory_q_ptr->enqueue(msg);
active_request.bytes_issued += msg.getLen();

View File

@@ -58,12 +58,14 @@ void DirectoryMemory::init(const vector<string> & argv)
if ( (*it) == "version" )
m_version = atoi( (*(++it)).c_str() );
else if ( (*it) == "size_mb" ) {
m_size_bytes = atoi((*(++it)).c_str()) * (1<<20);
m_size_bytes = atoi((*(++it)).c_str()) * static_cast<uint64>(1<<20);
m_size_bits = log_int(m_size_bytes);
} else if ( (*it) == "controller" ) {
m_controller = RubySystem::getController((*(++it)));
} else
} else {
cerr << "DirectoryMemory: Unkown config parameter: " << (*it) << endl;
assert(0);
}
}
assert(m_controller != NULL);

View File

@@ -59,7 +59,7 @@ public:
int mapAddressToLocalIdx(PhysAddress address);
static int mapAddressToDirectoryVersion(PhysAddress address);
int getSize() { return m_size_bytes; }
uint64 getSize() { return m_size_bytes; }
// Public Methods
void printConfig(ostream& out) const;
@@ -84,8 +84,8 @@ private:
// Data Members (m_ prefix)
Directory_Entry **m_entries;
// int m_size; // # of memory module blocks this directory is responsible for
uint32 m_size_bytes;
uint32 m_size_bits;
uint64 m_size_bytes;
uint64 m_size_bits;
int m_num_entries;
int m_version;

View File

@@ -43,7 +43,6 @@
#include "mem/gems_common/Map.hh"
#include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/slicc_interface/AbstractChip.hh"
template<class ENTRY>
class PerfectCacheLineState {
@@ -53,12 +52,19 @@ public:
ENTRY m_entry;
};
template<class ENTRY>
extern inline
ostream& operator<<(ostream& out, const PerfectCacheLineState<ENTRY>& obj)
{
return out;
}
template<class ENTRY>
class PerfectCacheMemory {
public:
// Constructors
PerfectCacheMemory(AbstractChip* chip_ptr);
PerfectCacheMemory();
// Destructor
//~PerfectCacheMemory();
@@ -106,7 +112,6 @@ private:
// Data Members (m_prefix)
Map<Address, PerfectCacheLineState<ENTRY> > m_map;
AbstractChip* m_chip_ptr;
};
// Output operator declaration
@@ -129,9 +134,8 @@ ostream& operator<<(ostream& out, const PerfectCacheMemory<ENTRY>& obj)
template<class ENTRY>
extern inline
PerfectCacheMemory<ENTRY>::PerfectCacheMemory(AbstractChip* chip_ptr)
PerfectCacheMemory<ENTRY>::PerfectCacheMemory()
{
m_chip_ptr = chip_ptr;
}
// STATIC METHODS

View File

@@ -104,6 +104,9 @@ public:
static RubyPort* getPortOnly(const string & name) {
assert(m_ports.count(name) == 1); return m_ports[name]; }
static RubyPort* getPort(const string & name, void (*hit_callback)(int64_t)) {
if (m_ports.count(name) != 1){
cerr << "Port " << name << " has " << m_ports.count(name) << " instances" << endl;
}
assert(m_ports.count(name) == 1); m_ports[name]->registerHitCallback(hit_callback); return m_ports[name]; }
static Network* getNetwork() { assert(m_network_ptr != NULL); return m_network_ptr; }
static Topology* getTopology(const string & name) { assert(m_topologies.count(name) == 1); return m_topologies[name]; }

View File

@@ -35,11 +35,9 @@
#include "mem/ruby/system/TimerTable.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
TimerTable::TimerTable(Chip* chip_ptr)
TimerTable::TimerTable()
{
assert(chip_ptr != NULL);
m_consumer_ptr = NULL;
m_chip_ptr = chip_ptr;
m_next_valid = false;
m_next_address = Address(0);
m_next_time = 0;

View File

@@ -43,13 +43,12 @@
#include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh"
class Consumer;
class Chip;
class TimerTable {
public:
// Constructors
TimerTable(Chip* chip_ptr);
TimerTable();
// Destructor
//~TimerTable();
@@ -77,7 +76,6 @@ private:
// Data Members (m_prefix)
Map<Address, Time> m_map;
Chip* m_chip_ptr;
mutable bool m_next_valid;
mutable Time m_next_time; // Only valid if m_next_valid is true
mutable Address m_next_address; // Only valid if m_next_valid is true

View File

@@ -50,28 +50,28 @@ public:
// Constructors
AST(Map<string, string> pairs) { m_pairs = pairs; };
AST() {};
// Destructor
virtual ~AST() {};
// Public Methods
virtual void print(ostream& out) const = 0;
void error(string err_msg) const { m_location.error(err_msg); };
string embedError(string err_msg) const { return m_location.embedError(err_msg); };
void warning(string err_msg) const { m_location.warning(err_msg); };
const Location& getLocation() const { return m_location; };
const Map<string, string>& getPairs() const { return m_pairs; };
Map<string, string>& getPairs() { return m_pairs; };
private:
// Private Methods
// Private copy constructor and assignment operator
// AST(const AST& obj);
// AST& operator=(const AST& obj);
// Data Members (m_ prefix)
Location m_location;
Map<string, string> m_pairs;

View File

@@ -36,8 +36,10 @@
*
*/
#include "mem/slicc/ast/ActionDeclAST.hh"
#include "mem/slicc/symbols/Action.hh"
#include "mem/slicc/ast/StatementListAST.hh"
ActionDeclAST::ActionDeclAST(string* ident_ptr,
PairListAST* pairs_ptr,

View File

@@ -41,7 +41,8 @@
#include "mem/slicc/slicc_global.hh"
#include "mem/slicc/ast/DeclAST.hh"
#include "mem/slicc/ast/StatementListAST.hh"
class StatementListAST;
class ActionDeclAST : public DeclAST {
public:

View File

@@ -77,7 +77,14 @@ void EnqueueStatementAST::generate(string& code, Type* return_type_ptr) const
code += ".enqueue(out_msg";
if (getPairs().exist("latency")) {
code += ", m_LATENCY_" + getPairs().lookup("latency");
bool is_number = true;
string val = getPairs().lookup("latency");
for (int i=0; i<val.size(); i++)
if (!isdigit(val[i])) is_number = false;
if (is_number)
code += ", " + getPairs().lookup("latency");
else
code += ", m_" + getPairs().lookup("latency");
}
code += ");\n";

View File

@@ -38,6 +38,7 @@
#include "mem/slicc/ast/FormalParamAST.hh"
#include "mem/slicc/ast/StatementAST.hh"
#include "mem/slicc/ast/TypeAST.hh"
#include "mem/slicc/symbols/SymbolTable.hh"
FormalParamAST::~FormalParamAST()
@@ -46,6 +47,16 @@ FormalParamAST::~FormalParamAST()
delete m_type_ast_ptr;
}
string FormalParamAST::getTypeName() const
{
return m_type_ast_ptr->toString();
}
Type* FormalParamAST::getType() const
{
return m_type_ast_ptr->lookupType();
}
Type* FormalParamAST::generate(string& code) const
{
string param = "param_" + *m_ident_ptr;

View File

@@ -40,7 +40,9 @@
#define FORMALPARAMAST_H
#include "mem/slicc/slicc_global.hh"
#include "mem/slicc/ast/TypeAST.hh"
#include "mem/slicc/ast/AST.hh"
class TypeAST;
class FormalParamAST : public AST {
@@ -55,6 +57,8 @@ public:
Type* generate(string& code) const;
void print(ostream& out) const { out << "[FormalParamAST: " << *m_ident_ptr << "]"; }
string getName() const { return *m_ident_ptr; }
string getTypeName() const;
Type* getType() const;
private:
// Private Methods

View File

@@ -37,6 +37,7 @@
*/
#include "mem/slicc/ast/FuncDeclAST.hh"
#include "mem/slicc/ast/FormalParamAST.hh"
#include "mem/slicc/symbols/SymbolTable.hh"
#include "mem/slicc/main.hh"

View File

@@ -43,7 +43,8 @@
#include "mem/slicc/ast/DeclAST.hh"
#include "mem/slicc/ast/TypeFieldAST.hh"
#include "mem/slicc/ast/TypeAST.hh"
#include "mem/slicc/ast/FormalParamAST.hh"
class FormalParamsAST;
class FuncDeclAST : public DeclAST {
public:

View File

@@ -37,21 +37,20 @@
*/
#include "mem/slicc/ast/MachineAST.hh"
#include "mem/slicc/ast/FormalParamAST.hh"
#include "mem/slicc/symbols/SymbolTable.hh"
MachineAST::MachineAST(string* ident_ptr,
PairListAST* pairs_ptr,
Vector<TypeFieldAST*>* config_params_ptr,
std::vector<std::string*>* latency_vector,
Vector<FormalParamAST*>* config_parameters,
DeclListAST* decl_list_ptr)
: DeclAST(pairs_ptr)
{
m_ident_ptr = ident_ptr;
m_pairs_ptr = pairs_ptr;
m_config_params_ptr = config_params_ptr;
m_config_parameters = config_parameters;
m_decl_list_ptr = decl_list_ptr;
m_latency_vector = latency_vector;
}
MachineAST::~MachineAST()
@@ -69,7 +68,7 @@ void MachineAST::generate()
g_sym_table.pushFrame();
// Create a new machine
machine_ptr = new StateMachine(*m_ident_ptr, getLocation(), getPairs(), m_latency_vector);
machine_ptr = new StateMachine(*m_ident_ptr, getLocation(), getPairs(), m_config_parameters);
g_sym_table.newCurrentMachine(machine_ptr);
// Generate code for all the internal decls

View File

@@ -45,13 +45,14 @@
#include "mem/slicc/ast/TypeFieldAST.hh"
#include "mem/slicc/symbols/StateMachine.hh"
class FormalParamAST;
class MachineAST : public DeclAST {
public:
// Constructors
MachineAST(string* ident_ptr,
PairListAST* pairs_ptr,
Vector<TypeFieldAST*>* config_params_ptr,
std::vector<std::string*>* latency_vector,
Vector<FormalParamAST*>* config_parameters,
DeclListAST* decl_list_ptr);
// Destructor
@@ -69,10 +70,9 @@ private:
MachineAST& operator=(const MachineAST& obj);
// Data Members (m_ prefix)
std::vector<std::string*>* m_latency_vector;
Vector<FormalParamAST*>* m_config_parameters;
string* m_ident_ptr;
DeclListAST* m_decl_list_ptr;
Vector<TypeFieldAST*>* m_config_params_ptr;
PairListAST* m_pairs_ptr;
};

View File

@@ -76,7 +76,7 @@ tokens = [ 'EQ', 'NE', 'LT', 'GT', 'LE', 'GE',
'NOT', 'AND', 'OR',
'PLUS', 'DASH', 'STAR', 'SLASH',
'DOUBLE_COLON', 'SEMICOLON',
'ASSIGN', 'DOT', 'LATENCY',
'ASSIGN', 'DOT',
'IDENT', 'LIT_BOOL', 'FLOATNUMBER', 'NUMBER', 'STRING' ]
tokens += reserved.values()
@@ -197,19 +197,8 @@ def p_decl(p):
| d_func_def"""
p[0] = p[1]
def p_latency(p):
"""latency : LATENCY"""
pass
def p_latencies(p):
"""latencies : latency latencies
| empty"""
return []
def p_d_machine(p):
"""d_machine : MACHINE '(' ident pair_l ')' '{' decl_l '}'
| MACHINE '(' ident pair_l ')' ':' type_members '{' decl_l '}'
| MACHINE '(' ident pair_l ')' ':' latencies '{' decl_l '}'"""
"""d_machine : MACHINE '(' ident pair_l ')' ':' param_l '{' decl_l '}'"""
if len(p) == 9:
decl_l = p[7]
@@ -549,10 +538,11 @@ def scan(filenames):
for filename in filenames:
lex.lexer.lineno = 1
try:
print "parsing ",filename
results = yacc.parse(file(filename, 'r').read())
except (TokenError, ParseError), e:
sys.exit("%s: %s:%d" % (e, filename, e.token.lineno))
for result in results:
result.add(hh, cc)

View File

@@ -111,8 +111,6 @@ extern "C" int yylex();
%type <expr_ptr> expr literal enumeration
%type <expr_vector_ptr> expr_list
%type <stdstring_vector_ptr> myrule
%type <pair_ptr> pair
%type <pair_list_ptr> pair_list pairs
@@ -148,9 +146,7 @@ decls: decl decls { $2->insertAtTop($1); $$ = $2; }
| { $$ = new Vector<DeclAST*>; }
;
decl: MACHINE_DECL '(' ident pair_list ')' ':' myrule '{' decl_list '}' { $$ = new MachineAST($3, $4, NULL, $7, $9); }
// | MACHINE_DECL '(' ident pair_list ')' ':' type_members '{' decl_list '}' { $$ = new MachineAST($3, $4, $7, string_vector, $9); }
| MACHINE_DECL '(' ident pair_list ')' '{' decl_list '}' { $$ = new MachineAST($3, $4, NULL, new vector<string*>(), $7); }
decl: MACHINE_DECL '(' ident pair_list ')' ':' formal_param_list '{' decl_list '}' { $$ = new MachineAST($3, $4, $7, $9); }
| ACTION_DECL '(' ident pair_list ')' statement_list { $$ = new ActionDeclAST($3, $4, $6); }
| IN_PORT_DECL '(' ident ',' type ',' var pair_list ')' statement_list { $$ = new InPortDeclAST($3, $5, $7, $8, $10); }
| OUT_PORT_DECL '(' ident ',' type ',' var pair_list ')' SEMICOLON { $$ = new OutPortDeclAST($3, $5, $7, $8); }
@@ -336,10 +332,6 @@ var: ident { $$ = new VarExprAST($1); }
field: ident { $$ = $1; }
;
myrule: myrule IDENT { $1->push_back($2); }
| IDENT { $$ = new vector<string*>(1, $1); }
;
%%
extern FILE *yyin;

View File

@@ -43,14 +43,25 @@
#include "mem/slicc/symbols/SymbolTable.hh"
#include "mem/gems_common/util.hh"
#include "mem/gems_common/Vector.hh"
#include "mem/slicc/ast/FormalParamAST.hh"
#include <set>
StateMachine::StateMachine(string ident, const Location& location, const Map<string, string>& pairs, std::vector<std::string*>* latency_vector)
StateMachine::StateMachine(string ident, const Location& location, const Map<string, string>& pairs, Vector<FormalParamAST*>* config_parameters)
: Symbol(ident, location, pairs)
{
m_table_built = false;
m_latency_vector = *latency_vector;
m_config_parameters = config_parameters;
for (int i=0; i< m_config_parameters->size(); i++) {
Var* var = new Var(m_config_parameters->ref(i)->getName(),
location,
m_config_parameters->ref(i)->getType(),
"m_"+m_config_parameters->ref(i)->getName(),
Map<string, string>(),
this);
g_sym_table.registerSym(m_config_parameters->ref(i)->getName(), var);
}
}
StateMachine::~StateMachine()
@@ -284,9 +295,8 @@ void StateMachine::printControllerH(ostream& out, string component)
out << "private:" << endl;
//added by SS
// found_to_mem = 0;
std::vector<std::string*>::const_iterator it;
for(it=m_latency_vector.begin();it!=m_latency_vector.end();it++){
out << " int m_" << (*it)->c_str() << ";" << endl;
for(int i=0;i<m_config_parameters->size();i++){
out << " int m_" << m_config_parameters->ref(i)->getName() << ";" << endl;
}
if (strncmp(component.c_str(), "L1Cache", 7) == 0) {
out << " bool servicing_atomic;" << endl;
@@ -429,41 +439,22 @@ void StateMachine::printControllerC(ostream& out, string component)
out << " else if (argv[i] == \"number_of_TBEs\") " << endl;
out << " m_number_of_TBEs = atoi(argv[i+1].c_str());" << endl;
if (m_latency_vector.size()) {
out << " else { " << endl;
std::vector<std::string*>::const_iterator it;
for(it=m_latency_vector.begin();it!=m_latency_vector.end();it++) {
string str = (*it)->c_str();
str.erase(0,8);
//convert to lowercase
size_t i;
char* strc = (char*) malloc (str.length()+1);
strc[str.length()]=0;
for(i=0; i < str.length(); i++) {
strc[i] = str.at(i);
strc[i] = tolower(strc[i]);
}
str = strc;
delete strc;
out << " if (argv[i] == \"" << str << "\"){" << endl;
if (str == "to_mem_ctrl_latency")
out << " m_" << (*it)->c_str() << "=" << "atoi(argv[i+1].c_str())+(random() % 5);" << endl;
if (m_config_parameters->size()) {
for(int i= 0 ; i < m_config_parameters->size(); i++) {
out << " else if (argv[i] == \"" << m_config_parameters->ref(i)->getName() << "\")" << endl;
if (m_config_parameters->ref(i)->getTypeName() == "int")
out << " m_" << m_config_parameters->ref(i)->getName() << "=" << "atoi(argv[i+1].c_str());" << endl;
else
out << " m_" << (*it)->c_str() << "=" << "atoi(argv[i+1].c_str());" << endl;
// out << " printf (\"SET m_" << it->c_str() << "= %i \\n \", m_" << it->c_str() << ");" << endl;
out << " }" << endl;
assert(0); // only int parameters are supported right now
// if (str == "to_mem_ctrl_latency")
// out << " m_" << (*it)->c_str() << "=" << "atoi(argv[i+1].c_str())+(random() % 5);" << endl;
}
out << " }" << endl;
}
out << " }" << endl;
out << " m_net_ptr = net_ptr;" << endl;
out << " m_machineID.type = MachineType_" << component << ";" << endl;
out << " m_machineID.num = m_version;" << endl;
// out << " printf (\"I set m_LATENCY_ISSUE_LATENCY to %i \\n \", m_LATENCY_ISSUE_LATENCY);" << endl;
// out << " printf (\"I set m_LATENCY_CACHE_RESPONSE_LATENCY to %i \\n \", m_LATENCY_CACHE_RESPONSE_LATENCY);" << endl;
// make configuration array
out << " for (size_t i=0; i < argv.size(); i+=2) {" << endl;
out << " if (argv[i] != \"version\") " << endl;
@@ -724,25 +715,7 @@ void StateMachine::printControllerC(ostream& out, string component)
string c_code_string = action.lookupPair("c_code");
/*
size_t found = c_code_string.find("RubyConfig::get");
if (found!=string::npos){ //found --> replace it with local access
//if it is related to latency --> replace it
std::vector<std::string*>::const_iterator it;
for(it=m_latency_vector.begin();it!=m_latency_vector.end();it++){
string str = (*it)->c_str();
str.erase(0,8);
size_t fd = c_code_string.find(str, found);
if (fd!=string::npos && (fd == found+15)){
string rstr = "m_";
rstr += (*it)->c_str();
c_code_string.replace(found,15+str.size()+2,rstr);
break;
}
}
}
*/
// add here:
if (strncmp(component.c_str(), "L1Cache", 7) == 0) {
if (c_code_string.find("writeCallback") != string::npos) {

View File

@@ -49,11 +49,12 @@ class State;
class Action;
class Var;
class Func;
class FormalParamAST;
class StateMachine : public Symbol {
public:
// Constructors
StateMachine(string ident, const Location& location, const Map<string, string>& pairs, std::vector<std::string*>* latency_vector);
StateMachine(string ident, const Location& location, const Map<string, string>& pairs, Vector<FormalParamAST*>* config_parameters);
// Destructor
~StateMachine();
@@ -94,7 +95,7 @@ public:
void print(ostream& out) const { out << "[StateMachine: " << toString() << "]" << endl; }
private:
std::vector<std::string*> m_latency_vector;
Vector<FormalParamAST*>* m_config_parameters;
// Private Methods
void checkForDuplicate(const Symbol& sym) const;

View File

@@ -1,76 +1,76 @@
["-r", "tests/configs/../../src/mem/ruby/config/MI_example-homogeneous.rb", "-p", "8", "-m", "1", "-s", "1024"]
print config: 1
system.cpu1: completed 10000 read accesses @3663630
system.cpu2: completed 10000 read accesses @3663638
system.cpu5: completed 10000 read accesses @3680002
system.cpu7: completed 10000 read accesses @3691164
system.cpu3: completed 10000 read accesses @3698130
system.cpu4: completed 10000 read accesses @3701748
system.cpu6: completed 10000 read accesses @3704092
system.cpu0: completed 10000 read accesses @3742302
system.cpu2: completed 20000 read accesses @6788966
system.cpu7: completed 20000 read accesses @6816416
system.cpu5: completed 20000 read accesses @6822351
system.cpu4: completed 20000 read accesses @6824056
system.cpu1: completed 20000 read accesses @6825604
system.cpu3: completed 20000 read accesses @6829578
system.cpu6: completed 20000 read accesses @6857232
system.cpu0: completed 20000 read accesses @6872452
system.cpu5: completed 30000 read accesses @9928492
system.cpu2: completed 30000 read accesses @9933192
system.cpu7: completed 30000 read accesses @9950074
system.cpu4: completed 30000 read accesses @9965775
system.cpu6: completed 30000 read accesses @9978835
system.cpu0: completed 30000 read accesses @9993926
system.cpu1: completed 30000 read accesses @9994767
system.cpu3: completed 30000 read accesses @9996366
system.cpu5: completed 40000 read accesses @13012070
system.cpu2: completed 40000 read accesses @13044972
system.cpu7: completed 40000 read accesses @13077010
system.cpu4: completed 40000 read accesses @13081178
system.cpu1: completed 40000 read accesses @13100740
system.cpu0: completed 40000 read accesses @13111135
system.cpu6: completed 40000 read accesses @13147706
system.cpu3: completed 40000 read accesses @13153176
system.cpu5: completed 50000 read accesses @16120762
system.cpu2: completed 50000 read accesses @16176586
system.cpu7: completed 50000 read accesses @16213417
system.cpu4: completed 50000 read accesses @16219872
system.cpu6: completed 50000 read accesses @16231538
system.cpu1: completed 50000 read accesses @16246976
system.cpu3: completed 50000 read accesses @16276612
system.cpu0: completed 50000 read accesses @16293234
system.cpu5: completed 60000 read accesses @19263804
system.cpu4: completed 60000 read accesses @19313220
system.cpu2: completed 60000 read accesses @19330470
system.cpu7: completed 60000 read accesses @19340197
system.cpu6: completed 60000 read accesses @19399766
system.cpu0: completed 60000 read accesses @19424570
system.cpu1: completed 60000 read accesses @19425712
system.cpu3: completed 60000 read accesses @19444952
system.cpu5: completed 70000 read accesses @22408750
system.cpu4: completed 70000 read accesses @22449746
system.cpu7: completed 70000 read accesses @22451736
system.cpu2: completed 70000 read accesses @22461052
system.cpu0: completed 70000 read accesses @22554296
system.cpu1: completed 70000 read accesses @22555310
system.cpu3: completed 70000 read accesses @22588935
system.cpu6: completed 70000 read accesses @22602456
system.cpu5: completed 80000 read accesses @25540598
system.cpu4: completed 80000 read accesses @25577430
system.cpu7: completed 80000 read accesses @25617532
system.cpu1: completed 80000 read accesses @25644879
system.cpu2: completed 80000 read accesses @25660256
system.cpu0: completed 80000 read accesses @25710799
system.cpu3: completed 80000 read accesses @25716714
system.cpu6: completed 80000 read accesses @25776606
system.cpu5: completed 90000 read accesses @28693458
system.cpu4: completed 90000 read accesses @28705416
system.cpu7: completed 90000 read accesses @28729734
system.cpu1: completed 90000 read accesses @28778532
system.cpu2: completed 90000 read accesses @28801770
system.cpu0: completed 90000 read accesses @28857559
system.cpu6: completed 90000 read accesses @28885159
system.cpu3: completed 90000 read accesses @28894168
system.cpu7: completed 100000 read accesses @31814464
system.cpu4: completed 10000 read accesses @3654068
system.cpu1: completed 10000 read accesses @3658672
system.cpu6: completed 10000 read accesses @3667702
system.cpu0: completed 10000 read accesses @3693712
system.cpu2: completed 10000 read accesses @3695692
system.cpu7: completed 10000 read accesses @3702934
system.cpu3: completed 10000 read accesses @3713843
system.cpu5: completed 10000 read accesses @3747976
system.cpu4: completed 20000 read accesses @6783252
system.cpu6: completed 20000 read accesses @6788574
system.cpu1: completed 20000 read accesses @6811444
system.cpu2: completed 20000 read accesses @6811575
system.cpu7: completed 20000 read accesses @6823208
system.cpu3: completed 20000 read accesses @6833412
system.cpu0: completed 20000 read accesses @6842332
system.cpu5: completed 20000 read accesses @6892128
system.cpu4: completed 30000 read accesses @9900552
system.cpu6: completed 30000 read accesses @9919466
system.cpu7: completed 30000 read accesses @9934195
system.cpu3: completed 30000 read accesses @9940524
system.cpu2: completed 30000 read accesses @9940526
system.cpu0: completed 30000 read accesses @9949032
system.cpu1: completed 30000 read accesses @10008962
system.cpu5: completed 30000 read accesses @10013847
system.cpu0: completed 40000 read accesses @12997824
system.cpu3: completed 40000 read accesses @13026659
system.cpu4: completed 40000 read accesses @13029141
system.cpu6: completed 40000 read accesses @13053052
system.cpu7: completed 40000 read accesses @13057445
system.cpu2: completed 40000 read accesses @13075320
system.cpu5: completed 40000 read accesses @13152513
system.cpu1: completed 40000 read accesses @13163064
system.cpu3: completed 50000 read accesses @16170822
system.cpu0: completed 50000 read accesses @16183660
system.cpu4: completed 50000 read accesses @16197183
system.cpu6: completed 50000 read accesses @16212971
system.cpu7: completed 50000 read accesses @16214970
system.cpu5: completed 50000 read accesses @16230286
system.cpu2: completed 50000 read accesses @16247930
system.cpu1: completed 50000 read accesses @16329114
system.cpu3: completed 60000 read accesses @19272882
system.cpu7: completed 60000 read accesses @19345830
system.cpu4: completed 60000 read accesses @19346068
system.cpu6: completed 60000 read accesses @19382538
system.cpu0: completed 60000 read accesses @19393516
system.cpu2: completed 60000 read accesses @19397285
system.cpu5: completed 60000 read accesses @19426724
system.cpu1: completed 60000 read accesses @19469424
system.cpu3: completed 70000 read accesses @22377862
system.cpu4: completed 70000 read accesses @22461180
system.cpu2: completed 70000 read accesses @22521889
system.cpu6: completed 70000 read accesses @22522406
system.cpu5: completed 70000 read accesses @22529566
system.cpu7: completed 70000 read accesses @22543033
system.cpu0: completed 70000 read accesses @22547582
system.cpu1: completed 70000 read accesses @22584856
system.cpu3: completed 80000 read accesses @25551111
system.cpu4: completed 80000 read accesses @25606550
system.cpu6: completed 80000 read accesses @25616752
system.cpu2: completed 80000 read accesses @25647434
system.cpu5: completed 80000 read accesses @25665443
system.cpu0: completed 80000 read accesses @25669616
system.cpu1: completed 80000 read accesses @25693304
system.cpu7: completed 80000 read accesses @25704210
system.cpu3: completed 90000 read accesses @28724260
system.cpu6: completed 90000 read accesses @28724466
system.cpu5: completed 90000 read accesses @28743404
system.cpu4: completed 90000 read accesses @28745769
system.cpu2: completed 90000 read accesses @28803478
system.cpu0: completed 90000 read accesses @28806136
system.cpu1: completed 90000 read accesses @28823872
system.cpu7: completed 90000 read accesses @28858910
system.cpu3: completed 100000 read accesses @31871402
hack: be nice to actually delete the event here

View File

@@ -5,11 +5,11 @@ The Regents of The University of Michigan
All Rights Reserved
M5 compiled Jul 29 2009 15:19:07
M5 revision a6e8795b73de+ 6384+ default tip
M5 started Jul 29 2009 15:19:16
M5 compiled Aug 5 2009 13:36:56
M5 revision 26abdfe2d980+ 6439+ default tip
M5 started Aug 5 2009 13:37:49
M5 executing on clover-02.cs.wisc.edu
command line: build/ALPHA_SE/m5.fast -d build/ALPHA_SE/tests/fast/quick/50.memtest/alpha/linux/memtest-ruby -re tests/run.py build/ALPHA_SE/tests/fast/quick/50.memtest/alpha/linux/memtest-ruby
Global frequency set at 1000000000000 ticks per second
info: Entering event queue @ 0. Starting simulation...
Exiting @ tick 31814464 because maximum number of loads reached
Exiting @ tick 31871402 because maximum number of loads reached

View File

@@ -1,34 +1,34 @@
---------- Begin Simulation Statistics ----------
host_mem_usage 1538672 # Number of bytes of host memory used
host_seconds 1279.29 # Real time elapsed on the host
host_tick_rate 24869 # Simulator tick rate (ticks/s)
host_mem_usage 1538648 # Number of bytes of host memory used
host_seconds 1657.04 # Real time elapsed on the host
host_tick_rate 19234 # Simulator tick rate (ticks/s)
sim_freq 1000000000000 # Frequency of simulated ticks
sim_seconds 0.000032 # Number of seconds simulated
sim_ticks 31814464 # Number of ticks simulated
sim_ticks 31871402 # Number of ticks simulated
system.cpu0.num_copies 0 # number of copy accesses completed
system.cpu0.num_reads 99342 # number of read accesses completed
system.cpu0.num_writes 53699 # number of write accesses completed
system.cpu0.num_reads 99819 # number of read accesses completed
system.cpu0.num_writes 53816 # number of write accesses completed
system.cpu1.num_copies 0 # number of copy accesses completed
system.cpu1.num_reads 99812 # number of read accesses completed
system.cpu1.num_writes 53757 # number of write accesses completed
system.cpu1.num_reads 99606 # number of read accesses completed
system.cpu1.num_writes 53868 # number of write accesses completed
system.cpu2.num_copies 0 # number of copy accesses completed
system.cpu2.num_reads 99597 # number of read accesses completed
system.cpu2.num_writes 53671 # number of write accesses completed
system.cpu2.num_reads 99741 # number of read accesses completed
system.cpu2.num_writes 53973 # number of write accesses completed
system.cpu3.num_copies 0 # number of copy accesses completed
system.cpu3.num_reads 99365 # number of read accesses completed
system.cpu3.num_writes 53444 # number of write accesses completed
system.cpu3.num_reads 100000 # number of read accesses completed
system.cpu3.num_writes 53819 # number of write accesses completed
system.cpu4.num_copies 0 # number of copy accesses completed
system.cpu4.num_reads 99713 # number of read accesses completed
system.cpu4.num_writes 54044 # number of write accesses completed
system.cpu4.num_reads 99858 # number of read accesses completed
system.cpu4.num_writes 53805 # number of write accesses completed
system.cpu5.num_copies 0 # number of copy accesses completed
system.cpu5.num_reads 99943 # number of read accesses completed
system.cpu5.num_writes 53789 # number of write accesses completed
system.cpu5.num_reads 99895 # number of read accesses completed
system.cpu5.num_writes 53573 # number of write accesses completed
system.cpu6.num_copies 0 # number of copy accesses completed
system.cpu6.num_reads 99307 # number of read accesses completed
system.cpu6.num_writes 53603 # number of write accesses completed
system.cpu6.num_reads 99989 # number of read accesses completed
system.cpu6.num_writes 53856 # number of write accesses completed
system.cpu7.num_copies 0 # number of copy accesses completed
system.cpu7.num_reads 100000 # number of read accesses completed
system.cpu7.num_writes 53881 # number of write accesses completed
system.cpu7.num_reads 99668 # number of read accesses completed
system.cpu7.num_writes 53858 # number of write accesses completed
---------- End Simulation Statistics ----------