slicc: added MOESI_CMP_directory, DMA SequencerMsg, parameterized controllers
This changeset contains a lot of different changes that are too mingled to separate. They are: 1. Added MOESI_CMP_directory I made the changes necessary to bring back MOESI_CMP_directory, including adding a DMA controller. I got rid of MOESI_CMP_directory_m and made MOESI_CMP_directory use a memory controller. Added a new configuration for two level protocols in general, and MOESI_CMP_directory in particular. 2. DMA Sequencer uses a generic SequencerMsg I will eventually make the cache Sequencer use this type as well. It doesn't contain an offset field, just a physical address and a length. MI_example has been updated to deal with this. 3. Parameterized Controllers SLICC controllers can now take custom parameters to use for mapping, latencies, etc. Currently, only int parameters are supported.
This commit is contained in:
parent
c1e0bd1df4
commit
33b28fde7a
47 changed files with 1187 additions and 1068 deletions
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
|
||||
machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_DIRECTORY_LATENCY LATENCY_MEMORY_LATENCY {
|
||||
machine(Directory, "Directory protocol")
|
||||
: int directory_latency
|
||||
{
|
||||
|
||||
MessageBuffer forwardFromDir, network="To", virtual_network="2", ordered="false";
|
||||
MessageBuffer responseFromDir, network="To", virtual_network="1", ordered="false";
|
||||
|
@ -65,9 +67,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 +182,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 +194,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 +206,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;
|
||||
|
@ -240,7 +242,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
|
|||
|
||||
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;
|
||||
|
@ -265,7 +267,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
|
|||
|
||||
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;
|
||||
|
@ -280,7 +282,7 @@ 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;
|
||||
|
@ -292,7 +294,7 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -318,7 +320,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 +332,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 +361,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 +391,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 +405,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;
|
||||
|
@ -416,7 +418,7 @@ 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") {
|
||||
// enqueue(memQueue_out, MemoryMsg, latency="1") {
|
||||
// out_msg.Address := address;
|
||||
// out_msg.Type := MemoryRequestType:MEMORY_WB;
|
||||
// out_msg.OriginalRequestorMachId := machineID;
|
||||
|
@ -431,12 +433,12 @@ machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_D
|
|||
|
||||
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 +449,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 +467,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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -32,7 +32,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
machine(L1Cache, "Directory protocol") {
|
||||
machine(L1Cache, "Directory protocol")
|
||||
: int request_latency,
|
||||
int l2_select_low_bit,
|
||||
int l2_select_high_bit
|
||||
{
|
||||
|
||||
// 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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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_high_bit));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
267
src/mem/protocol/MOESI_CMP_directory-dma.sm
Normal file
267
src/mem/protocol/MOESI_CMP_directory-dma.sm
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -57,5 +57,5 @@ int N_tokens();
|
|||
bool distributedPersistentEnabled();
|
||||
Address setOffset(Address addr, int offset);
|
||||
Address makeLineAddress(Address addr);
|
||||
|
||||
int addressOffset(Address addr);
|
||||
|
||||
|
|
|
@ -17,11 +17,16 @@ L1_CACHE_LATENCY = 1
|
|||
num_memories = 2
|
||||
memory_size_mb = 1024
|
||||
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 +41,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")
|
||||
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|
|
||||
|
@ -55,7 +64,7 @@ num_memories.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)
|
||||
|
|
35
src/mem/ruby/config/MI_example.rb
Normal file
35
src/mem/ruby/config/MI_example.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
|
||||
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
|
||||
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
|
79
src/mem/ruby/config/MOESI_CMP_directory.rb
Normal file
79
src/mem/ruby/config/MOESI_CMP_directory.rb
Normal file
|
@ -0,0 +1,79 @@
|
|||
|
||||
require "cfg.rb"
|
||||
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
l2_select_high_bit = num_block_bits + num_select_bits - 1
|
||||
|
||||
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_high_bit " + l2_select_high_bit.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
|
98
src/mem/ruby/config/TwoLevel_SplitL1UnifiedL2.rb
Normal file
98
src/mem/ruby/config/TwoLevel_SplitL1UnifiedL2.rb
Normal file
|
@ -0,0 +1,98 @@
|
|||
#!/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"
|
||||
|
||||
# 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)
|
|
@ -233,6 +233,7 @@ class RubySystem
|
|||
end
|
||||
}
|
||||
str += LibRubyObject.printConstructors
|
||||
#puts str.gsub('%',' ').gsub('#','\n')
|
||||
return str
|
||||
end
|
||||
|
||||
|
@ -287,35 +288,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 +322,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 +380,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 +622,7 @@ class Network < LibRubyObject
|
|||
end
|
||||
|
||||
def printTopology()
|
||||
topology.printFile
|
||||
topology().printFile
|
||||
end
|
||||
def cppClassName()
|
||||
"SimpleNetwork"
|
||||
|
@ -686,31 +702,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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -85,6 +85,14 @@ MachineID map_Address_to_DMA(const Address & addr)
|
|||
return dma;
|
||||
}
|
||||
|
||||
inline
|
||||
MachineID mapAddressToRange(const Address & addr, MachineType type, int low_bit, int high_bit)
|
||||
{
|
||||
MachineID mach = {type, 0};
|
||||
mach.num = addr.bitSelect(low_bit, high_bit);
|
||||
return mach;
|
||||
}
|
||||
|
||||
extern inline NodeID machineIDToNodeID(MachineID machID)
|
||||
{
|
||||
return machID.num;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
@ -190,19 +190,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]
|
||||
|
@ -542,10 +531,19 @@ 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:
|
||||
raise type(e), tuple([filename] + [ i for i in e ])
|
||||
except (ParseError,TokenError), e:
|
||||
print "File ",filename," ",e
|
||||
raise e
|
||||
#except ParseError, e:
|
||||
# print "File ",filename," "e
|
||||
# raise e, tuple([filename] + [ i for i in e ])
|
||||
|
||||
#except ParseError, e:
|
||||
# print e
|
||||
|
||||
|
||||
for result in results:
|
||||
result.add(hh, cc)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue