ruby: coherence protocols: remove data block from dirctory entry

This patch removes the data block present in the directory entry structure
of each protocol in gem5's mainline.  Firstly, this is required for moving
towards common set of memory controllers for classic and ruby memory systems.
Secondly, the data block was being misused in several places.  It was being
used for having free access to the physical memory instead of calling on the
memory controller.

From now on, the directory controller will not have a direct visibility into
the physical memory.  The Memory Vector object now resides in the
Memory Controller class.  This also means that some significant changes are
being made to the functional accesses in ruby.
This commit is contained in:
Nilay Vaish 2014-11-06 05:42:20 -06:00
parent 0baaed60ab
commit d25b722e4a
32 changed files with 417 additions and 401 deletions

View file

@ -205,13 +205,28 @@ machine(L0Cache, "MESI Directory L0 Cache")
return AccessPermission:NotPresent;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
void functionalRead(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
testAndRead(addr, tbe.DataBlk, pkt);
} else {
testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
}
}
int functionalWrite(Address addr, Packet *pkt) {
int num_functional_writes := 0;
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
num_functional_writes := num_functional_writes +
testAndWrite(addr, tbe.DataBlk, pkt);
return num_functional_writes;
}
return getCacheEntry(addr).DataBlk;
num_functional_writes := num_functional_writes +
testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
return num_functional_writes;
}
void setAccessPermission(Entry cache_entry, Address addr, State state) {

View file

@ -205,13 +205,28 @@ machine(L1Cache, "MESI Directory L1 Cache CMP")
return AccessPermission:NotPresent;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
void functionalRead(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
testAndRead(addr, tbe.DataBlk, pkt);
} else {
testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
}
}
int functionalWrite(Address addr, Packet *pkt) {
int num_functional_writes := 0;
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
num_functional_writes := num_functional_writes +
testAndWrite(addr, tbe.DataBlk, pkt);
return num_functional_writes;
}
return getCacheEntry(addr).DataBlk;
num_functional_writes := num_functional_writes +
testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
return num_functional_writes;
}
void setAccessPermission(Entry cache_entry, Address addr, State state) {

View file

@ -224,13 +224,28 @@ machine(L1Cache, "MESI Directory L1 Cache CMP")
return AccessPermission:NotPresent;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
void functionalRead(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
testAndRead(addr, tbe.DataBlk, pkt);
} else {
testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
}
}
int functionalWrite(Address addr, Packet *pkt) {
int num_functional_writes := 0;
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
num_functional_writes := num_functional_writes +
testAndWrite(addr, tbe.DataBlk, pkt);
return num_functional_writes;
}
return getCacheEntry(addr).DataBlk;
num_functional_writes := num_functional_writes +
testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
return num_functional_writes;
}
void setAccessPermission(Entry cache_entry, Address addr, State state) {

View file

@ -212,13 +212,28 @@ machine(L2Cache, "MESI Directory L2 Cache CMP")
return AccessPermission:NotPresent;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
void functionalRead(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
testAndRead(addr, tbe.DataBlk, pkt);
} else {
testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
}
}
int functionalWrite(Address addr, Packet *pkt) {
int num_functional_writes := 0;
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
num_functional_writes := num_functional_writes +
testAndWrite(addr, tbe.DataBlk, pkt);
return num_functional_writes;
}
return getCacheEntry(addr).DataBlk;
num_functional_writes := num_functional_writes +
testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
return num_functional_writes;
}
void setAccessPermission(Entry cache_entry, Address addr, State state) {

View file

@ -73,7 +73,6 @@ machine(Directory, "MESI Two Level directory protocol")
// DirectoryEntry
structure(Entry, desc="...", interface="AbstractEntry") {
State DirectoryState, desc="Directory state";
DataBlock DataBlk, desc="data for the block";
MachineID Owner;
}
@ -90,6 +89,8 @@ machine(Directory, "MESI Two Level directory protocol")
void allocate(Address);
void deallocate(Address);
bool isPresent(Address);
bool functionalRead(Packet *pkt);
int functionalWrite(Packet *pkt);
}
@ -148,13 +149,22 @@ machine(Directory, "MESI Two Level directory protocol")
return AccessPermission:NotPresent;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
void functionalRead(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
testAndRead(addr, tbe.DataBlk, pkt);
} else {
memBuffer.functionalRead(pkt);
}
}
int functionalWrite(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
testAndWrite(addr, tbe.DataBlk, pkt);
}
return getDirectoryEntry(addr).DataBlk;
return memBuffer.functionalWrite(pkt);
}
void setAccessPermission(Address addr, State state) {
@ -297,7 +307,6 @@ machine(Directory, "MESI Two Level directory protocol")
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.Prefetch := in_msg.Prefetch;
out_msg.DataBlk := getDirectoryEntry(in_msg.Addr).DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
@ -320,13 +329,6 @@ machine(Directory, "MESI Two Level directory protocol")
}
}
action(m_writeDataToMemory, "m", desc="Write dirty writeback to memory") {
peek(responseNetwork_in, ResponseMsg) {
getDirectoryEntry(in_msg.Addr).DataBlk := in_msg.DataBlk;
DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
in_msg.Addr, in_msg.DataBlk);
}
}
//added by SS for dma
action(qf_queueMemoryFetchRequestDMA, "qfd", desc="Queue off-chip fetch request") {
peek(requestNetwork_in, RequestMsg) {
@ -336,7 +338,6 @@ machine(Directory, "MESI Two Level directory protocol")
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := machineID;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
@ -358,25 +359,14 @@ machine(Directory, "MESI Two Level directory protocol")
}
}
action(dw_writeDMAData, "dw", desc="DMA Write data to memory") {
peek(requestNetwork_in, RequestMsg) {
getDirectoryEntry(address).DataBlk.copyPartial(in_msg.DataBlk, addressOffset(in_msg.Addr), in_msg.Len);
}
}
action(qw_queueMemoryWBRequest_partial, "qwp", desc="Queue off-chip writeback request") {
peek(requestNetwork_in, RequestMsg) {
enqueue(memQueue_out, MemoryMsg, to_mem_ctrl_latency) {
out_msg.Addr := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.OriginalRequestorMachId := machineID;
//out_msg.DataBlk := in_msg.DataBlk;
out_msg.DataBlk.copyPartial(in_msg.DataBlk, addressOffset(address), in_msg.Len);
out_msg.MessageSize := in_msg.MessageSize;
//out_msg.Prefetch := in_msg.Prefetch;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
@ -434,15 +424,6 @@ machine(Directory, "MESI Two Level directory protocol")
}
}
action(dwt_writeDMADataFromTBE, "dwt", desc="DMA Write data to memory from TBE") {
assert(is_valid(tbe));
//getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, tbe.Offset, tbe.Len);
getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len);
}
action(qw_queueMemoryWBRequest_partialTBE, "qwt", desc="Queue off-chip writeback request") {
peek(responseNetwork_in, ResponseMsg) {
enqueue(memQueue_out, MemoryMsg, to_mem_ctrl_latency) {
@ -493,7 +474,6 @@ machine(Directory, "MESI Two Level directory protocol")
}
transition(M, Data, MI) {
m_writeDataToMemory;
qw_queueMemoryWBRequest;
k_popIncomingResponseQueue;
}
@ -518,7 +498,6 @@ machine(Directory, "MESI Two Level directory protocol")
}
transition(I, DMA_WRITE, ID_W) {
dw_writeDMAData;
qw_queueMemoryWBRequest_partial;
j_popIncomingRequestQueue;
}
@ -545,7 +524,6 @@ machine(Directory, "MESI Two Level directory protocol")
transition(M_DRD, Data, M_DRDI) {
drp_sendDMAData;
m_writeDataToMemory;
qw_queueMemoryWBRequest;
k_popIncomingResponseQueue;
}
@ -563,13 +541,11 @@ machine(Directory, "MESI Two Level directory protocol")
}
transition(M_DWR, Data, M_DWRI) {
m_writeDataToMemory;
qw_queueMemoryWBRequest_partialTBE;
k_popIncomingResponseQueue;
}
transition(M_DWRI, Memory_Ack, I) {
dwt_writeDMADataFromTBE;
aa_sendAck;
da_sendDMAAck;
w_deallocateTBE;

View file

@ -55,8 +55,9 @@ machine(DMA, "DMA Controller")
State getState(Address addr) {
return cur_state;
}
void setState(Address addr, State state) {
cur_state := state;
cur_state := state;
}
AccessPermission getAccessPermission(Address addr) {
@ -66,8 +67,12 @@ machine(DMA, "DMA Controller")
void setAccessPermission(Address addr, State state) {
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
error("DMA does not support get data block.");
void functionalRead(Address addr, Packet *pkt) {
error("DMA does not support functional read.");
}
int functionalWrite(Address addr, Packet *pkt) {
error("DMA does not support functional write.");
}
out_port(requestToDir_out, RequestMsg, requestToDir, desc="...");

View file

@ -171,13 +171,28 @@ machine(L1Cache, "MI Example L1 Cache")
}
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
void functionalRead(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
testAndRead(addr, tbe.DataBlk, pkt);
} else {
testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
}
}
int functionalWrite(Address addr, Packet *pkt) {
int num_functional_writes := 0;
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
num_functional_writes := num_functional_writes +
testAndWrite(addr, tbe.DataBlk, pkt);
return num_functional_writes;
}
return getCacheEntry(addr).DataBlk;
num_functional_writes := num_functional_writes +
testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
return num_functional_writes;
}
// NETWORK PORTS

View file

@ -84,7 +84,6 @@ machine(Directory, "Directory protocol")
// DirectoryEntry
structure(Entry, desc="...", interface="AbstractEntry") {
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";
}
@ -151,7 +150,6 @@ machine(Directory, "Directory protocol")
if (state == State:I) {
assert(getDirectoryEntry(addr).Owner.count() == 0);
assert(getDirectoryEntry(addr).Sharers.count() == 0);
directory.invalidateBlock(addr);
}
}
}
@ -175,13 +173,22 @@ machine(Directory, "Directory protocol")
}
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
void functionalRead(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
testAndRead(addr, tbe.DataBlk, pkt);
} else {
memBuffer.functionalRead(pkt);
}
}
int functionalWrite(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
testAndWrite(addr, tbe.DataBlk, pkt);
}
return getDirectoryEntry(addr).DataBlk;
return memBuffer.functionalWrite(pkt);
}
// ** OUT_PORTS **
@ -326,7 +333,10 @@ machine(Directory, "Directory protocol")
out_msg.PhysicalAddress := address;
out_msg.LineAddress := address;
out_msg.Type := DMAResponseType:DATA;
out_msg.DataBlk := in_msg.DataBlk; // we send the entire data block and rely on the dma controller to split it up if need be
// we send the entire data block and rely on the dma controller
// to split it up if need be
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Destination.add(tbe.DmaRequestor);
out_msg.MessageSize := MessageSizeType:Response_Data;
}
@ -386,21 +396,7 @@ machine(Directory, "Directory protocol")
action(p_popIncomingDMARequestQueue, "p", desc="Pop incoming DMA queue") {
dmaRequestQueue_in.dequeue();
}
action(l_writeDataToMemory, "pl", desc="Write PUTX data to memory") {
peek(requestQueue_in, RequestMsg) {
// assert(in_msg.Dirty);
// assert(in_msg.MessageSize == MessageSizeType:Writeback_Data);
getDirectoryEntry(in_msg.Addr).DataBlk := in_msg.DataBlk;
//getDirectoryEntry(in_msg.Addr).DataBlk.copyPartial(in_msg.DataBlk, addressOffset(in_msg.Addr), in_msg.Len);
}
}
action(dwt_writeDMADataFromTBE, "dwt", desc="DMA Write data to memory from TBE") {
assert(is_valid(tbe));
getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len);
}
action(v_allocateTBE, "v", desc="Allocate TBE") {
peek(dmaRequestQueue_in, DMARequestMsg) {
TBEs.allocate(address);
@ -450,7 +446,6 @@ machine(Directory, "Directory protocol")
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.DataBlk := getDirectoryEntry(in_msg.Addr).DataBlk;
DPRINTF(RubySlicc,"%s\n", out_msg);
}
}
@ -464,7 +459,6 @@ machine(Directory, "Directory protocol")
out_msg.Sender := machineID;
//out_msg.OriginalRequestorMachId := machineID;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
DPRINTF(RubySlicc,"%s\n", out_msg);
}
}
@ -475,12 +469,9 @@ machine(Directory, "Directory protocol")
enqueue(memQueue_out, MemoryMsg, 1) {
out_msg.Addr := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
//out_msg.OriginalRequestorMachId := machineID;
//out_msg.DataBlk := in_msg.DataBlk;
out_msg.DataBlk.copyPartial(in_msg.DataBlk, addressOffset(in_msg.PhysicalAddress), 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;
DPRINTF(RubySlicc,"%s\n", out_msg);
}
}
@ -493,19 +484,17 @@ machine(Directory, "Directory protocol")
out_msg.Addr := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
// get incoming data
// out_msg.DataBlk := in_msg.DataBlk;
out_msg.DataBlk.copyPartial(tbe.DataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len);
out_msg.MessageSize := in_msg.MessageSize;
//out_msg.Prefetch := in_msg.Prefetch;
// get incoming data
out_msg.DataBlk.copyPartial(
tbe.DataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len);
out_msg.MessageSize := in_msg.MessageSize;
DPRINTF(RubySlicc,"%s\n", out_msg);
}
}
}
action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") {
peek(requestQueue_in, RequestMsg) {
enqueue(memQueue_out, MemoryMsg, 1) {
@ -525,13 +514,7 @@ machine(Directory, "Directory protocol")
memQueue_in.dequeue();
}
action(w_writeDataToMemoryFromTBE, "\w", desc="Write date to directory memory from TBE") {
assert(is_valid(tbe));
getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk;
}
// TRANSITIONS
transition({M_DRD, M_DWR, M_DWRI, M_DRDI}, GETX) {
z_recycleRequestQueue;
}
@ -582,7 +565,6 @@ machine(Directory, "Directory protocol")
}
transition(ID_W, Memory_Ack, I) {
dwt_writeDMADataFromTBE;
da_sendDMAAck;
w_deallocateTBE;
l_popMemQueue;
@ -595,7 +577,6 @@ machine(Directory, "Directory protocol")
}
transition(M_DRD, PUTX, M_DRDI) {
l_writeDataToMemory;
drp_sendDMAData;
c_clearOwner;
l_queueMemoryWBRequest;
@ -616,14 +597,12 @@ machine(Directory, "Directory protocol")
}
transition(M_DWR, PUTX, M_DWRI) {
l_writeDataToMemory;
qw_queueMemoryWBRequest_partialTBE;
c_clearOwner;
i_popIncomingRequestQueue;
}
transition(M_DWRI, Memory_Ack, I) {
w_writeDataToMemoryFromTBE;
l_sendWriteBackAck;
da_sendDMAAck;
w_deallocateTBE;
@ -644,7 +623,6 @@ machine(Directory, "Directory protocol")
}
transition(MI, Memory_Ack, I) {
w_writeDataToMemoryFromTBE;
l_sendWriteBackAck;
w_deallocateTBE;
l_popMemQueue;
@ -659,5 +637,4 @@ machine(Directory, "Directory protocol")
b_sendWriteBackNack;
i_popIncomingRequestQueue;
}
}

View file

@ -66,8 +66,12 @@ machine(DMA, "DMA Controller")
void setAccessPermission(Address addr, State state) {
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
error("DMA Controller does not support getDataBlock function.\n");
void functionalRead(Address addr, Packet *pkt) {
error("DMA does not support functional read.");
}
int functionalWrite(Address addr, Packet *pkt) {
error("DMA does not support functional write.");
}
out_port(requestToDir_out, DMARequestMsg, requestToDir, desc="...");

View file

@ -212,18 +212,34 @@ machine(L1Cache, "Directory protocol")
}
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
void functionalRead(Address addr, Packet *pkt) {
Entry cache_entry := getCacheEntry(addr);
if(is_valid(cache_entry)) {
return cache_entry.DataBlk;
testAndRead(addr, cache_entry.DataBlk, pkt);
} else {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
testAndRead(addr, tbe.DataBlk, pkt);
} else {
error("Data block missing!");
}
}
}
int functionalWrite(Address addr, Packet *pkt) {
int num_functional_writes := 0;
Entry cache_entry := getCacheEntry(addr);
if(is_valid(cache_entry)) {
num_functional_writes := num_functional_writes +
testAndWrite(addr, cache_entry.DataBlk, pkt);
return num_functional_writes;
}
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
}
error("Data block missing!");
num_functional_writes := num_functional_writes +
testAndWrite(addr, tbe.DataBlk, pkt);
return num_functional_writes;
}
Event mandatory_request_type_to_event(RubyRequestType type) {

View file

@ -520,13 +520,28 @@ machine(L2Cache, "Token protocol")
}
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
void functionalRead(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
testAndRead(addr, tbe.DataBlk, pkt);
} else {
testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
}
}
int functionalWrite(Address addr, Packet *pkt) {
int num_functional_writes := 0;
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
num_functional_writes := num_functional_writes +
testAndWrite(addr, tbe.DataBlk, pkt);
return num_functional_writes;
}
return getCacheEntry(addr).DataBlk;
num_functional_writes := num_functional_writes +
testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
return num_functional_writes;
}
MessageBuffer triggerQueue, ordered="true";

View file

@ -96,7 +96,6 @@ machine(Directory, "Directory protocol")
// DirectoryEntry
structure(Entry, desc="...", interface='AbstractEntry') {
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";
@ -191,8 +190,12 @@ machine(Directory, "Directory protocol")
}
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
return getDirectoryEntry(addr).DataBlk;
void functionalRead(Address addr, Packet *pkt) {
memBuffer.functionalRead(pkt);
}
int functionalWrite(Address addr, Packet *pkt) {
return memBuffer.functionalWrite(pkt);
}
// if no sharers, then directory can be considered
@ -346,7 +349,6 @@ machine(Directory, "Directory protocol")
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:Directory;
out_msg.Destination.add(in_msg.OriginalRequestorMachId);
//out_msg.DataBlk := getDirectoryEntry(in_msg.Addr).DataBlk;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Dirty := false; // By definition, the block is now clean
out_msg.Acks := in_msg.Acks;
@ -367,7 +369,6 @@ machine(Directory, "Directory protocol")
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:Directory;
out_msg.Destination.add(in_msg.Requestor);
out_msg.DataBlk := getDirectoryEntry(in_msg.Addr).DataBlk;
out_msg.Dirty := false; // By definition, the block is now clean
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
out_msg.MessageSize := MessageSizeType:Response_Data;
@ -375,8 +376,6 @@ machine(Directory, "Directory protocol")
}
}
action(e_ownerIsUnblocker, "e", desc="The owner is now the unblocker") {
peek(unblockNetwork_in, ResponseMsg) {
getDirectoryEntry(address).Owner.clear();
@ -445,40 +444,6 @@ machine(Directory, "Directory protocol")
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);
getDirectoryEntry(in_msg.Addr).DataBlk := in_msg.DataBlk;
DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
in_msg.Addr, in_msg.DataBlk);
}
}
action(p_writeFwdDataToMemory, "p", desc="Write Response data to memory") {
peek(unblockNetwork_in, ResponseMsg) {
getDirectoryEntry(in_msg.Addr).DataBlk := in_msg.DataBlk;
DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
in_msg.Addr, in_msg.DataBlk);
}
}
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);
// 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
DPRINTF(RubySlicc, "Address: %s, MsgDataBlock: %s MemoryDataBlock: %s\n",
in_msg.Addr, in_msg.DataBlk,
getDirectoryEntry(in_msg.Addr).DataBlk);
assert(getDirectoryEntry(in_msg.Addr).DataBlk == in_msg.DataBlk);
}
}
action(m_addUnlockerToSharers, "m", desc="Add the unlocker to the sharer list") {
peek(unblockNetwork_in, ResponseMsg) {
getDirectoryEntry(address).Sharers.add(in_msg.Sender);
@ -505,7 +470,6 @@ machine(Directory, "Directory protocol")
out_msg.Type := MemoryRequestType:MEMORY_READ;
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.DataBlk := getDirectoryEntry(in_msg.Addr).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:
@ -540,6 +504,29 @@ machine(Directory, "Directory protocol")
}
}
action(qw_queueMemoryWBRequestFromMessageAndTBE, "qwmt",
desc="Queue off-chip writeback request") {
peek(unblockNetwork_in, ResponseMsg) {
enqueue(memQueue_out, MemoryMsg, 1) {
out_msg.Addr := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.Sender := machineID;
if (is_valid(tbe)) {
out_msg.OriginalRequestorMachId := tbe.Requestor;
}
out_msg.DataBlk := in_msg.DataBlk;
out_msg.DataBlk.copyPartial(tbe.DataBlk,
addressOffset(tbe.PhysicalAddress), tbe.Len);
out_msg.MessageSize := in_msg.MessageSize;
// Not used:
out_msg.ReadX := false;
out_msg.Acks := getDirectoryEntry(address).Sharers.count(); // for dma requests
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
}
action(qw_queueMemoryWBRequest2, "/qw", desc="Queue off-chip writeback request") {
peek(requestQueue_in, RequestMsg) {
enqueue(memQueue_out, MemoryMsg, 1) {
@ -594,18 +581,6 @@ machine(Directory, "Directory protocol")
}
}
action(l_writeDMADataToMemory, "\l", desc="Write data from a DMA_WRITE to memory") {
peek(requestQueue_in, RequestMsg) {
getDirectoryEntry(address).DataBlk.copyPartial(in_msg.DataBlk, addressOffset(in_msg.Addr), in_msg.Len);
}
}
action(l_writeDMADataToMemoryFromTBE, "\ll", desc="Write data from a DMA_WRITE to memory") {
assert(is_valid(tbe));
getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk,
addressOffset(tbe.PhysicalAddress), tbe.Len);
}
action(v_allocateTBE, "v", desc="Allocate TBE entry") {
peek (requestQueue_in, RequestMsg) {
TBEs.allocate(address);
@ -623,9 +598,7 @@ machine(Directory, "Directory protocol")
}
// TRANSITIONS
transition(I, GETX, MM) {
qf_queueMemoryFetchRequest;
i_popIncomingRequestQueue;
@ -639,7 +612,6 @@ machine(Directory, "Directory protocol")
transition(I, DMA_WRITE, XI_U) {
qw_queueMemoryWBRequest2;
a_sendDMAAck; // ack count may be zero
l_writeDMADataToMemory;
i_popIncomingRequestQueue;
}
@ -670,7 +642,6 @@ machine(Directory, "Directory protocol")
transition(S, DMA_WRITE, XI_U) {
qw_queueMemoryWBRequest2;
a_sendDMAAck; // ack count may be zero
l_writeDMADataToMemory;
g_sendInvalidations; // the DMA will collect invalidations
i_popIncomingRequestQueue;
}
@ -720,10 +691,8 @@ machine(Directory, "Directory protocol")
}
transition(OI_D, Data, XI_U) {
qw_queueMemoryWBRequest;
qw_queueMemoryWBRequestFromMessageAndTBE;
a_sendDMAAck2; // ack count may be zero
p_writeFwdDataToMemory;
l_writeDMADataToMemoryFromTBE;
w_deallocateTBE;
j_popIncomingUnblockQueue;
}
@ -842,14 +811,12 @@ machine(Directory, "Directory protocol")
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;
}
@ -861,14 +828,12 @@ 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;
}
@ -881,13 +846,11 @@ machine(Directory, "Directory protocol")
transition(MI, Clean_Writeback, I) {
c_clearOwner;
cc_clearSharers;
ll_checkDataInMemory;
j_popIncomingUnblockQueue;
}
transition(OS, Clean_Writeback, S) {
c_clearOwner;
ll_checkDataInMemory;
j_popIncomingUnblockQueue;
}

View file

@ -91,8 +91,12 @@ machine(DMA, "DMA Controller")
void setAccessPermission(Address addr, State state) {
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
error("DMA Controller does not support getDataBlock().\n");
void functionalRead(Address addr, Packet *pkt) {
error("DMA does not support functional read.");
}
int functionalWrite(Address addr, Packet *pkt) {
error("DMA does not support functional write.");
}
out_port(reqToDirectory_out, RequestMsg, reqToDir, desc="...");

View file

@ -240,8 +240,15 @@ machine(L1Cache, "Token protocol")
return L1Icache_entry;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
return getCacheEntry(addr).DataBlk;
void functionalRead(Address addr, Packet *pkt) {
testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
}
int functionalWrite(Address addr, Packet *pkt) {
int num_functional_writes := 0;
num_functional_writes := num_functional_writes +
testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
return num_functional_writes;
}
Entry getL1DCacheEntry(Address addr), return_by_pointer="yes" {

View file

@ -157,8 +157,15 @@ machine(L2Cache, "Token protocol")
return cache_entry;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
return getCacheEntry(addr).DataBlk;
void functionalRead(Address addr, Packet *pkt) {
testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
}
int functionalWrite(Address addr, Packet *pkt) {
int num_functional_writes := 0;
num_functional_writes := num_functional_writes +
testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
return num_functional_writes;
}
int getTokens(Entry cache_entry) {

View file

@ -121,7 +121,6 @@ machine(Directory, "Token protocol")
// DirectoryEntry
structure(Entry, desc="...", interface="AbstractEntry") {
State DirectoryState, desc="Directory state";
DataBlock DataBlk, desc="data for the block";
int Tokens, default="max_tokens()", desc="Number of tokens for the line we're holding";
// The following state is provided to allow for bandwidth
@ -188,10 +187,6 @@ machine(Directory, "Token protocol")
return dir_entry;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
return getDirectoryEntry(addr).DataBlk;
}
State getState(TBE tbe, Address addr) {
if (is_valid(tbe)) {
return tbe.TBEState;
@ -250,6 +245,24 @@ machine(Directory, "Token protocol")
persistentTable.markEntries(addr);
}
void functionalRead(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
testAndRead(addr, tbe.DataBlk, pkt);
} else {
memBuffer.functionalRead(pkt);
}
}
int functionalWrite(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
testAndWrite(addr, tbe.DataBlk, pkt);
}
return memBuffer.functionalWrite(pkt);
}
// ** OUT_PORTS **
out_port(responseNetwork_out, ResponseMsg, responseFromDir);
out_port(persistentNetwork_out, PersistentMsg, persistentFromDir);
@ -598,7 +611,7 @@ machine(Directory, "Token protocol")
out_msg.Destination.add(in_msg.OriginalRequestorMachId);
assert(getDirectoryEntry(address).Tokens > 0);
out_msg.Tokens := getDirectoryEntry(in_msg.Addr).Tokens;
out_msg.DataBlk := getDirectoryEntry(in_msg.Addr).DataBlk;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Dirty := false;
out_msg.MessageSize := MessageSizeType:Response_Data;
}
@ -615,7 +628,7 @@ machine(Directory, "Token protocol")
out_msg.Destination.add(persistentTable.findSmallest(address));
assert(getDirectoryEntry(address).Tokens > 0);
out_msg.Tokens := getDirectoryEntry(address).Tokens;
out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Dirty := false;
out_msg.MessageSize := MessageSizeType:Response_Data;
}
@ -646,7 +659,6 @@ machine(Directory, "Token protocol")
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
@ -659,7 +671,6 @@ machine(Directory, "Token protocol")
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := persistentTable.findSmallest(address);
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
@ -672,18 +683,20 @@ machine(Directory, "Token protocol")
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
}
action(lq_queueMemoryWbRequest, "lq", desc="Write data to memory") {
enqueue(memQueue_out, MemoryMsg, 1) {
out_msg.Addr := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
peek(responseNetwork_in, ResponseMsg) {
enqueue(memQueue_out, MemoryMsg, 1) {
out_msg.Addr := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.DataBlk := in_msg.DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
}
@ -694,7 +707,8 @@ machine(Directory, "Token protocol")
// first, initialize the data blk to the current version of system memory
out_msg.DataBlk := tbe.DataBlk;
// then add the dma write data
out_msg.DataBlk.copyPartial(tbe.DmaDataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len);
out_msg.DataBlk.copyPartial(
tbe.DmaDataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len);
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
@ -759,15 +773,6 @@ machine(Directory, "Token protocol")
}
}
action(cd_writeCleanDataToTbe, "cd", desc="Write clean memory data to TBE") {
tbe.DataBlk := getDirectoryEntry(address).DataBlk;
}
action(dwt_writeDmaDataFromTBE, "dwt", desc="DMA Write data to memory from TBE") {
getDirectoryEntry(address).DataBlk := tbe.DataBlk;
getDirectoryEntry(address).DataBlk.copyPartial(tbe.DmaDataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len);
}
action(f_incrementTokens, "f", desc="Increment the number of tokens we're tracking") {
peek(responseNetwork_in, ResponseMsg) {
assert(in_msg.Tokens >= 1);
@ -811,20 +816,6 @@ machine(Directory, "Token protocol")
memQueue_in.dequeue();
}
action(m_writeDataToMemory, "m", desc="Write dirty writeback to memory") {
peek(responseNetwork_in, ResponseMsg) {
getDirectoryEntry(in_msg.Addr).DataBlk := in_msg.DataBlk;
DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
in_msg.Addr, in_msg.DataBlk);
}
}
action(n_checkData, "n", desc="Check incoming clean data message") {
peek(responseNetwork_in, ResponseMsg) {
assert(getDirectoryEntry(in_msg.Addr).DataBlk == in_msg.DataBlk);
}
}
action(r_bounceResponse, "r", desc="Bounce response to starving processor") {
peek(responseNetwork_in, ResponseMsg) {
enqueue(responseNetwork_out, ResponseMsg, 1) {
@ -869,12 +860,6 @@ machine(Directory, "Token protocol")
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(getDirectoryEntry(in_msg.Addr).DataBlk == in_msg.DataBlk);
// Bounce the message, but "re-associate" the data and the owner
// token. In essence we're converting an ACK_OWNER message to a
// DATA_OWNER message, keeping the number of tokens the same.
@ -884,7 +869,6 @@ machine(Directory, "Token protocol")
out_msg.Sender := machineID;
out_msg.Destination.add(persistentTable.findSmallest(address));
out_msg.Tokens := in_msg.Tokens;
out_msg.DataBlk := getDirectoryEntry(in_msg.Addr).DataBlk;
out_msg.Dirty := in_msg.Dirty;
out_msg.MessageSize := MessageSizeType:Response_Data;
}
@ -948,7 +932,6 @@ machine(Directory, "Token protocol")
transition(O, DMA_WRITE, O_DW) {
vd_allocateDmaRequestInTBE;
cd_writeCleanDataToTbe;
bw_broadcastWrite;
st_scheduleTimeout;
p_popDmaRequestQueue;
@ -956,8 +939,6 @@ machine(Directory, "Token protocol")
transition(O, DMA_WRITE_All_Tokens, O_DW_W) {
vd_allocateDmaRequestInTBE;
cd_writeCleanDataToTbe;
dwt_writeDmaDataFromTBE;
ld_queueMemoryDmaWriteFromTbe;
p_popDmaRequestQueue;
}
@ -985,7 +966,6 @@ machine(Directory, "Token protocol")
}
transition(O, {Data_Owner, Data_All_Tokens}) {
n_checkData;
f_incrementTokens;
k_popIncomingResponseQueue;
}
@ -1026,7 +1006,6 @@ machine(Directory, "Token protocol")
transition(O_DW, Ack_Owner) {
f_incrementTokens;
cd_writeCleanDataToTbe;
k_popIncomingResponseQueue;
}
@ -1038,7 +1017,6 @@ machine(Directory, "Token protocol")
transition({NO_DW, O_DW}, Data_All_Tokens, O_DW_W) {
f_incrementTokens;
rd_recordDataInTbe;
dwt_writeDmaDataFromTBE;
ld_queueMemoryDmaWriteFromTbe;
ut_unsetReissueTimer;
k_popIncomingResponseQueue;
@ -1046,7 +1024,6 @@ machine(Directory, "Token protocol")
transition(O_DW, Ack_All_Tokens, O_DW_W) {
f_incrementTokens;
dwt_writeDmaDataFromTBE;
ld_queueMemoryDmaWriteFromTbe;
ut_unsetReissueTimer;
k_popIncomingResponseQueue;
@ -1054,8 +1031,6 @@ machine(Directory, "Token protocol")
transition(O_DW, Ack_Owner_All_Tokens, O_DW_W) {
f_incrementTokens;
cd_writeCleanDataToTbe;
dwt_writeDmaDataFromTBE;
ld_queueMemoryDmaWriteFromTbe;
ut_unsetReissueTimer;
k_popIncomingResponseQueue;
@ -1100,14 +1075,12 @@ machine(Directory, "Token protocol")
}
transition(NO, {Data_Owner, Data_All_Tokens}, O_W) {
m_writeDataToMemory;
f_incrementTokens;
lq_queueMemoryWbRequest;
k_popIncomingResponseQueue;
}
transition(NO, {Ack_Owner, Ack_Owner_All_Tokens}, O) {
n_checkData;
f_incrementTokens;
k_popIncomingResponseQueue;
}
@ -1160,7 +1133,6 @@ machine(Directory, "Token protocol")
}
transition(NO_DR, {Data_Owner, Data_All_Tokens}, O_W) {
m_writeDataToMemory;
f_incrementTokens;
dd_sendDmaData;
lr_queueMemoryDmaReadWriteback;
@ -1195,11 +1167,17 @@ machine(Directory, "Token protocol")
k_popIncomingResponseQueue;
}
transition({DW_L, DR_L, L}, {Ack_Owner_All_Tokens, Ack_Owner}) {
transition({DW_L, DR_L}, {Ack_Owner_All_Tokens, Ack_Owner}) {
bd_bounceDatalessOwnerToken;
k_popIncomingResponseQueue;
}
transition(L, {Ack_Owner_All_Tokens, Ack_Owner}, L_O_W) {
f_incrementTokens;
qp_queueMemoryForPersistent;
k_popIncomingResponseQueue;
}
transition(L, {Unlockdown, Own_Lock_or_Unlock}, NO) {
l_popIncomingPersistentQueue;
}

View file

@ -68,8 +68,12 @@ machine(DMA, "DMA Controller")
void setAccessPermission(Address addr, State state) {
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
error("DMA Controller does not support getDataBlock function.\n");
void functionalRead(Address addr, Packet *pkt) {
error("DMA does not support functional read.");
}
int functionalWrite(Address addr, Packet *pkt) {
error("DMA does not support functional write.");
}
out_port(reqToDirectory_out, DMARequestMsg, reqToDirectory, desc="...");

View file

@ -205,18 +205,34 @@ machine({L1Cache, L2Cache}, "AMD Hammer-like protocol")
return L1Icache_entry;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
void functionalRead(Address addr, Packet *pkt) {
Entry cache_entry := getCacheEntry(addr);
if(is_valid(cache_entry)) {
return cache_entry.DataBlk;
testAndRead(addr, cache_entry.DataBlk, pkt);
} else {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
testAndRead(addr, tbe.DataBlk, pkt);
} else {
error("Missing data block");
}
}
}
int functionalWrite(Address addr, Packet *pkt) {
int num_functional_writes := 0;
Entry cache_entry := getCacheEntry(addr);
if(is_valid(cache_entry)) {
num_functional_writes := num_functional_writes +
testAndWrite(addr, cache_entry.DataBlk, pkt);
return num_functional_writes;
}
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
}
error("Missing data block");
num_functional_writes := num_functional_writes +
testAndWrite(addr, tbe.DataBlk, pkt);
return num_functional_writes;
}
Entry getL2CacheEntry(Address address), return_by_pointer="yes" {

View file

@ -147,14 +147,12 @@ machine(Directory, "AMD Hammer-like protocol")
// DirectoryEntry
structure(Entry, desc="...", interface="AbstractEntry") {
State DirectoryState, desc="Directory state";
DataBlock DataBlk, desc="data for the block";
}
// ProbeFilterEntry
structure(PfEntry, desc="...", interface="AbstractCacheEntry") {
State PfState, desc="Directory state";
MachineID Owner, desc="Owner node";
DataBlock DataBlk, desc="data for the block";
Set Sharers, desc="sharing vector for full bit directory";
}
@ -208,20 +206,6 @@ machine(Directory, "AMD Hammer-like protocol")
return dir_entry;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
Entry dir_entry := getDirectoryEntry(addr);
if(is_valid(dir_entry)) {
return dir_entry.DataBlk;
}
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
return tbe.DataBlk;
}
error("Data block missing!");
}
PfEntry getProbeFilterEntry(Address addr), return_by_pointer="yes" {
if (probe_filter_enabled || full_bit_dir_enabled) {
PfEntry pfEntry := static_cast(PfEntry, "pointer", probeFilter.lookup(addr));
@ -282,6 +266,24 @@ machine(Directory, "AMD Hammer-like protocol")
getDirectoryEntry(addr).changePermission(Directory_State_to_permission(state));
}
void functionalRead(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
testAndRead(addr, tbe.DataBlk, pkt);
} else {
memBuffer.functionalRead(pkt);
}
}
int functionalWrite(Address addr, Packet *pkt) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
testAndWrite(addr, tbe.DataBlk, pkt);
}
return memBuffer.functionalWrite(pkt);
}
Event cache_request_to_event(CoherenceRequestType type) {
if (type == CoherenceRequestType:GETS) {
return Event:GETS;
@ -851,7 +853,6 @@ machine(Directory, "AMD Hammer-like protocol")
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
@ -865,7 +866,6 @@ machine(Directory, "AMD Hammer-like protocol")
out_msg.Sender := machineID;
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
@ -1179,38 +1179,6 @@ machine(Directory, "AMD Hammer-like protocol")
}
}
action(wr_writeResponseDataToMemory, "wr", desc="Write response data to memory") {
peek(responseToDir_in, ResponseMsg) {
getDirectoryEntry(address).DataBlk := in_msg.DataBlk;
DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
in_msg.Addr, in_msg.DataBlk);
}
}
action(l_writeDataToMemory, "l", desc="Write PUTX/PUTO data to memory") {
peek(memQueue_in, MemoryMsg) {
getDirectoryEntry(address).DataBlk := in_msg.DataBlk;
DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
in_msg.Addr, in_msg.DataBlk);
}
}
action(dwt_writeDmaDataFromTBE, "dwt", desc="DMA Write data to memory from TBE") {
DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
assert(is_valid(tbe));
getDirectoryEntry(address).DataBlk := tbe.DataBlk;
DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
getDirectoryEntry(address).DataBlk.copyPartial(tbe.DmaDataBlk, addressOffset(tbe.PhysicalAddress), tbe.Len);
DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
}
action(wdt_writeDataFromTBE, "wdt", desc="DMA Write data to memory from TBE") {
assert(is_valid(tbe));
DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
getDirectoryEntry(address).DataBlk := tbe.DataBlk;
DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
}
action(a_assertCacheData, "ac", desc="Assert that a cache provided the data") {
assert(is_valid(tbe));
assert(tbe.CacheDirty);
@ -1277,18 +1245,21 @@ machine(Directory, "AMD Hammer-like protocol")
}
}
action(ly_queueMemoryWriteFromTBE, "ly", desc="Write data to memory from TBE") {
enqueue(memQueue_out, MemoryMsg, 1) {
assert(is_valid(tbe));
out_msg.Addr := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.DataBlk := tbe.DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
action(ll_checkIncomingWriteback, "\l", desc="Check PUTX/PUTO response message") {
peek(unblockNetwork_in, ResponseMsg) {
assert(in_msg.Dirty == false);
assert(in_msg.MessageSize == MessageSizeType:Writeback_Control);
DPRINTF(RubySlicc, "%s\n", in_msg.DataBlk);
DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
// 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(getDirectoryEntry(address).DataBlk == in_msg.DataBlk);
}
}
@ -1651,20 +1622,26 @@ machine(Directory, "AMD Hammer-like protocol")
}
transition(S_R, Data) {
wr_writeResponseDataToMemory;
m_decrementNumberOfMessages;
o_checkForCompletion;
n_popResponseQueue;
}
transition(NO_R, {Data, Exclusive_Data}) {
wr_writeResponseDataToMemory;
r_recordCacheData;
m_decrementNumberOfMessages;
o_checkForCompletion;
n_popResponseQueue;
}
transition({O_R, S_R, NO_R}, All_acks_and_data_no_sharers, E) {
transition({O_R, S_R}, All_acks_and_data_no_sharers, E) {
w_deallocateTBE;
k_wakeUpDependents;
g_popTriggerQueue;
}
transition(NO_R, All_acks_and_data_no_sharers, WB_E_W) {
ly_queueMemoryWriteFromTBE;
w_deallocateTBE;
k_wakeUpDependents;
g_popTriggerQueue;
@ -1730,14 +1707,14 @@ machine(Directory, "AMD Hammer-like protocol")
n_popResponseQueue;
}
transition(NO_DR_B, All_acks_and_owner_data, O) {
transition(NO_DR_B, All_acks_and_owner_data, WB_O_W) {
//
// Note that the DMA consistency model allows us to send the DMA device
// a response as soon as we receive valid data and prior to receiving
// all acks. However, to simplify the protocol we wait for all acks.
//
dt_sendDmaDataFromTbe;
wdt_writeDataFromTBE;
ly_queueMemoryWriteFromTBE;
w_deallocateTBE;
k_wakeUpDependents;
g_popTriggerQueue;
@ -1750,20 +1727,19 @@ machine(Directory, "AMD Hammer-like protocol")
// all acks. However, to simplify the protocol we wait for all acks.
//
dt_sendDmaDataFromTbe;
wdt_writeDataFromTBE;
w_deallocateTBE;
k_wakeUpDependents;
g_popTriggerQueue;
}
transition(NO_DR_B_D, All_acks_and_owner_data, O) {
transition(NO_DR_B_D, All_acks_and_owner_data, WB_O_W) {
//
// Note that the DMA consistency model allows us to send the DMA device
// a response as soon as we receive valid data and prior to receiving
// all acks. However, to simplify the protocol we wait for all acks.
//
dt_sendDmaDataFromTbe;
wdt_writeDataFromTBE;
ly_queueMemoryWriteFromTBE;
w_deallocateTBE;
k_wakeUpDependents;
g_popTriggerQueue;
@ -1776,42 +1752,41 @@ machine(Directory, "AMD Hammer-like protocol")
// all acks. However, to simplify the protocol we wait for all acks.
//
dt_sendDmaDataFromTbe;
wdt_writeDataFromTBE;
w_deallocateTBE;
k_wakeUpDependents;
g_popTriggerQueue;
}
transition(O_DR_B, All_acks_and_owner_data, O) {
wdt_writeDataFromTBE;
transition(O_DR_B, All_acks_and_owner_data, WB_O_W) {
ly_queueMemoryWriteFromTBE;
w_deallocateTBE;
k_wakeUpDependents;
g_popTriggerQueue;
}
transition(O_DR_B, All_acks_and_data_no_sharers, E) {
wdt_writeDataFromTBE;
transition(O_DR_B, All_acks_and_data_no_sharers, WB_E_W) {
ly_queueMemoryWriteFromTBE;
w_deallocateTBE;
pfd_probeFilterDeallocate;
k_wakeUpDependents;
g_popTriggerQueue;
}
transition(NO_DR_B, All_acks_and_data_no_sharers, E) {
transition(NO_DR_B, All_acks_and_data_no_sharers, WB_E_W) {
//
// Note that the DMA consistency model allows us to send the DMA device
// a response as soon as we receive valid data and prior to receiving
// all acks. However, to simplify the protocol we wait for all acks.
//
dt_sendDmaDataFromTbe;
wdt_writeDataFromTBE;
ly_queueMemoryWriteFromTBE;
w_deallocateTBE;
ppfd_possibleProbeFilterDeallocate;
k_wakeUpDependents;
g_popTriggerQueue;
}
transition(NO_DR_B_D, All_acks_and_data_no_sharers, E) {
transition(NO_DR_B_D, All_acks_and_data_no_sharers, WB_E_W) {
a_assertCacheData;
//
// Note that the DMA consistency model allows us to send the DMA device
@ -1819,7 +1794,7 @@ machine(Directory, "AMD Hammer-like protocol")
// all acks. However, to simplify the protocol we wait for all acks.
//
dt_sendDmaDataFromTbe;
wdt_writeDataFromTBE;
ly_queueMemoryWriteFromTBE;
w_deallocateTBE;
ppfd_possibleProbeFilterDeallocate;
k_wakeUpDependents;
@ -1827,7 +1802,6 @@ machine(Directory, "AMD Hammer-like protocol")
}
transition(NO_DW_B_W, All_acks_and_data_no_sharers, NO_DW_W) {
dwt_writeDmaDataFromTBE;
ld_queueMemoryDmaWrite;
g_popTriggerQueue;
}
@ -1883,18 +1857,16 @@ machine(Directory, "AMD Hammer-like protocol")
transition(WB, Writeback_Exclusive_Dirty, WB_E_W) {
rs_removeSharer;
l_queueMemoryWBRequest;
pfd_probeFilterDeallocate;
j_popIncomingUnblockQueue;
}
transition(WB_E_W, Memory_Ack, E) {
l_writeDataToMemory;
pfd_probeFilterDeallocate;
k_wakeUpDependents;
l_popMemQueue;
}
transition(WB_O_W, Memory_Ack, O) {
l_writeDataToMemory;
k_wakeUpDependents;
l_popMemQueue;
}

View file

@ -66,8 +66,12 @@ machine(DMA, "DMA Controller")
void setAccessPermission(Address addr, State state) {
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
error("DMA Controller does not support getDataBlock function.\n");
void functionalRead(Address addr, Packet *pkt) {
error("DMA does not support functional read.");
}
int functionalWrite(Address addr, Packet *pkt) {
error("DMA does not support functional write.");
}
out_port(requestToDir_out, DMARequestMsg, requestToDir, desc="...");

View file

@ -114,8 +114,12 @@ machine(L1Cache, "Network_test L1 Cache")
return OOD;
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
error("Network Test does not support get data block.");
void functionalRead(Address addr, Packet *pkt) {
error("Network test does not support functional read.");
}
int functionalWrite(Address addr, Packet *pkt) {
error("Network test does not support functional write.");
}
// NETWORK PORTS

View file

@ -76,8 +76,12 @@ machine(Directory, "Network_test Directory")
void setAccessPermission(Address addr, State state) {
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
error("Network Test does not support get data block.");
void functionalRead(Address addr, Packet *pkt) {
error("Network test does not support functional read.");
}
int functionalWrite(Address addr, Packet *pkt) {
error("Network test does not support functional write.");
}
// ** IN_PORTS **

View file

@ -163,6 +163,8 @@ structure (WireBuffer, inport="yes", outport="yes", external = "yes") {
structure (MemoryControl, inport="yes", outport="yes", external = "yes") {
void recordRequestType(CacheRequestType);
void functionalRead(Packet *pkt);
int functionalWrite(Packet *pkt);
}
structure (DMASequencer, external = "yes") {

View file

@ -35,6 +35,7 @@
#include <iostream>
#include "base/misc.hh"
#include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/slicc_interface/AbstractEntry.hh"
@ -50,6 +51,12 @@ class AbstractCacheEntry : public AbstractEntry
// Get/Set permission of the entry
void changePermission(AccessPermission new_perm);
// The methods below are those called by ruby runtime, add when it
// is absolutely necessary and should all be virtual function.
virtual DataBlock& getDataBlk()
{ panic("getDataBlk() not implemented!"); }
Address m_Address; // Address of this block, required by CacheMemory
int m_locked; // Holds info whether the address is locked,
// required for implementing LL/SC

View file

@ -67,7 +67,6 @@ class AbstractController : public ClockedObject, public Consumer
virtual MessageBuffer* getMandatoryQueue() const = 0;
virtual AccessPermission getAccessPermission(const Address& addr) = 0;
virtual DataBlock& getDataBlock(const Address& addr) = 0;
virtual void print(std::ostream & out) const = 0;
virtual void wakeup() = 0;
@ -82,9 +81,11 @@ class AbstractController : public ClockedObject, public Consumer
//! The boolean return value indicates if the read was performed
//! successfully.
virtual bool functionalReadBuffers(PacketPtr&) = 0;
virtual void functionalRead(const Address &addr, PacketPtr) = 0;
//! The return value indicates the number of messages written with the
//! data from the packet.
virtual uint32_t functionalWriteBuffers(PacketPtr&) = 0;
virtual int functionalWrite(const Address &addr, PacketPtr) = 0;
//! Function for enqueuing a prefetch request
virtual void enqueuePrefetch(const Address&, const RubyRequestType&)

View file

@ -33,8 +33,6 @@
#include "mem/protocol/AccessPermission.hh"
class DataBlock;
class AbstractEntry
{
public:
@ -45,10 +43,6 @@ class AbstractEntry
AccessPermission getPermission() const;
void changePermission(AccessPermission new_perm);
// The methods below are those called by ruby runtime, add when it
// is absolutely necessary and should all be virtual function.
virtual DataBlock& getDataBlk() = 0;
virtual void print(std::ostream& out) const = 0;
AccessPermission m_Permission; // Access permission for this

View file

@ -57,7 +57,6 @@ DirectoryMemory::init()
m_entries = new AbstractEntry*[m_num_entries];
for (int i = 0; i < m_num_entries; i++)
m_entries[i] = NULL;
m_ram = g_system_ptr->getMemoryVector();
m_num_directories++;
m_num_directories_bits = ceilLog2(m_num_directories);
@ -132,7 +131,6 @@ DirectoryMemory::allocate(const PhysAddress& address, AbstractEntry* entry)
idx = mapAddressToLocalIdx(address);
assert(idx < m_num_entries);
entry->getDataBlk().assign(m_ram->getBlockPtr(address));
entry->changePermission(AccessPermission_Read_Only);
m_entries[idx] = entry;

View file

@ -35,7 +35,6 @@
#include "mem/protocol/DirectoryRequestType.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/slicc_interface/AbstractEntry.hh"
#include "mem/ruby/structures/MemoryVector.hh"
#include "params/RubyDirectoryMemory.hh"
#include "sim/sim_object.hh"
@ -80,8 +79,6 @@ class DirectoryMemory : public SimObject
static int m_num_directories_bits;
static uint64_t m_total_size_bytes;
static int m_numa_high_bit;
MemoryVector* m_ram;
};
inline std::ostream&

View file

@ -89,9 +89,9 @@ class MemoryControl : public ClockedObject, public Consumer
virtual void recordRequestType(MemoryControlRequestType requestType);
virtual bool functionalReadBuffers(Packet *pkt)
virtual bool functionalRead(Packet *pkt)
{ fatal("Functional read access not implemented!");}
virtual uint32_t functionalWriteBuffers(Packet *pkt)
virtual uint32_t functionalWrite(Packet *pkt)
{ fatal("Functional read access not implemented!");}
protected:

View file

@ -173,6 +173,7 @@ RubyMemoryControl::RubyMemoryControl(const Params *p)
void
RubyMemoryControl::init()
{
m_ram = g_system_ptr->getMemoryVector();
m_msg_counter = 0;
assert(m_tFaw <= 62); // must fit in a uint64 shift register
@ -282,6 +283,19 @@ RubyMemoryControl::enqueue(const MsgPtr& message, Cycles latency)
physical_address_t addr = memMess->getAddr().getAddress();
MemoryRequestType type = memMess->getType();
bool is_mem_read = (type == MemoryRequestType_MEMORY_READ);
if (is_mem_read) {
m_ram->read(memMess->getAddr(), const_cast<uint8_t *>(
memMess->getDataBlk().getData(0,
RubySystem::getBlockSizeBytes())),
RubySystem::getBlockSizeBytes());
} else {
m_ram->write(memMess->getAddr(), const_cast<uint8_t *>(
memMess->getDataBlk().getData(0,
RubySystem::getBlockSizeBytes())),
RubySystem::getBlockSizeBytes());
}
MemoryNode *thisReq = new MemoryNode(arrival_time, message, addr,
is_mem_read, !is_mem_read);
enqueueMemRef(thisReq);
@ -706,7 +720,7 @@ RubyMemoryControl::wakeup()
* being lists.
*/
bool
RubyMemoryControl::functionalReadBuffers(Packet *pkt)
RubyMemoryControl::functionalRead(Packet *pkt)
{
for (std::list<MemoryNode *>::iterator it = m_input_queue.begin();
it != m_input_queue.end(); ++it) {
@ -734,7 +748,10 @@ RubyMemoryControl::functionalReadBuffers(Packet *pkt)
}
}
return false;
m_ram->read(Address(pkt->getAddr()), pkt->getPtr<uint8_t>(true),
pkt->getSize());
return true;
}
/**
@ -746,7 +763,7 @@ RubyMemoryControl::functionalReadBuffers(Packet *pkt)
* for debugging purposes.
*/
uint32_t
RubyMemoryControl::functionalWriteBuffers(Packet *pkt)
RubyMemoryControl::functionalWrite(Packet *pkt)
{
uint32_t num_functional_writes = 0;
@ -776,6 +793,10 @@ RubyMemoryControl::functionalWriteBuffers(Packet *pkt)
}
}
m_ram->write(Address(pkt->getAddr()), pkt->getPtr<uint8_t>(true),
pkt->getSize());
num_functional_writes++;
return num_functional_writes;
}

View file

@ -36,15 +36,12 @@
#include "mem/protocol/MemoryMsg.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/profiler/MemCntrlProfiler.hh"
#include "mem/ruby/slicc_interface/Message.hh"
#include "mem/ruby/structures/MemoryControl.hh"
#include "mem/ruby/structures/MemoryNode.hh"
#include "mem/ruby/structures/MemoryVector.hh"
#include "mem/ruby/system/System.hh"
#include "params/RubyMemoryControl.hh"
#include "sim/sim_object.hh"
// This constant is part of the definition of tFAW; see
// the comments in header to RubyMemoryControl.cc
@ -95,8 +92,8 @@ class RubyMemoryControl : public MemoryControl
int getRanksPerDimm() { return m_ranks_per_dimm; };
int getDimmsPerChannel() { return m_dimms_per_channel; }
bool functionalReadBuffers(Packet *pkt);
uint32_t functionalWriteBuffers(Packet *pkt);
bool functionalRead(Packet *pkt);
uint32_t functionalWrite(Packet *pkt);
private:
void enqueueToDirectory(MemoryNode *req, Cycles latency);
@ -165,6 +162,9 @@ class RubyMemoryControl : public MemoryControl
int m_idleCount; // watchdog timer for shutting down
MemCntrlProfiler* m_profiler_ptr;
// Actual physical memory.
MemoryVector* m_ram;
};
std::ostream& operator<<(std::ostream& out, const RubyMemoryControl& obj);

View file

@ -427,10 +427,6 @@ RubySystem::functionalRead(PacketPtr pkt)
}
assert(num_rw <= 1);
uint8_t *data = pkt->getPtr<uint8_t>(true);
unsigned int size_in_bytes = pkt->getSize();
unsigned startByte = address.getAddress() - line_address.getAddress();
// This if case is meant to capture what happens in a Broadcast/Snoop
// protocol where the block does not exist in the cache hierarchy. You
// only want to read from the Backing_Store memory if there is no copy in
@ -439,20 +435,12 @@ RubySystem::functionalRead(PacketPtr pkt)
// The reason is because the Backing_Store memory could easily be stale, if
// there are copies floating around the cache hierarchy, so you want to read
// it only if it's not in the cache hierarchy at all.
if (num_invalid == (num_controllers - 1) &&
num_backing_store == 1) {
if (num_invalid == (num_controllers - 1) && num_backing_store == 1) {
DPRINTF(RubySystem, "only copy in Backing_Store memory, read from it\n");
for (unsigned int i = 0; i < num_controllers; ++i) {
access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_address);
if (access_perm == AccessPermission_Backing_Store) {
DataBlock& block = m_abs_cntrl_vec[i]->
getDataBlock(line_address);
DPRINTF(RubySystem, "reading from %s block %s\n",
m_abs_cntrl_vec[i]->name(), block);
for (unsigned j = 0; j < size_in_bytes; ++j) {
data[j] = block.getByte(j + startByte);
}
m_abs_cntrl_vec[i]->functionalRead(line_address, pkt);
return true;
}
}
@ -470,14 +458,7 @@ RubySystem::functionalRead(PacketPtr pkt)
access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_address);
if (access_perm == AccessPermission_Read_Only ||
access_perm == AccessPermission_Read_Write) {
DataBlock& block = m_abs_cntrl_vec[i]->
getDataBlock(line_address);
DPRINTF(RubySystem, "reading from %s block %s\n",
m_abs_cntrl_vec[i]->name(), block);
for (unsigned j = 0; j < size_in_bytes; ++j) {
data[j] = block.getByte(j + startByte);
}
m_abs_cntrl_vec[i]->functionalRead(line_address, pkt);
return true;
}
}
@ -500,10 +481,6 @@ RubySystem::functionalWrite(PacketPtr pkt)
DPRINTF(RubySystem, "Functional Write request for %s\n",addr);
uint8_t *data = pkt->getPtr<uint8_t>(true);
unsigned int size_in_bytes = pkt->getSize();
unsigned startByte = addr.getAddress() - line_addr.getAddress();
uint32_t M5_VAR_USED num_functional_writes = 0;
for (unsigned int i = 0; i < num_controllers;++i) {
@ -513,23 +490,11 @@ RubySystem::functionalWrite(PacketPtr pkt)
access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_addr);
if (access_perm != AccessPermission_Invalid &&
access_perm != AccessPermission_NotPresent) {
num_functional_writes++;
DataBlock& block = m_abs_cntrl_vec[i]->getDataBlock(line_addr);
DPRINTF(RubySystem, "%s\n",block);
for (unsigned j = 0; j < size_in_bytes; ++j) {
block.setByte(j + startByte, data[j]);
}
DPRINTF(RubySystem, "%s\n",block);
num_functional_writes +=
m_abs_cntrl_vec[i]->functionalWrite(line_addr, pkt);
}
}
for (unsigned int i = 0; i < m_memory_controller_vec.size() ;++i) {
num_functional_writes +=
m_memory_controller_vec[i]->functionalWriteBuffers(pkt);
}
num_functional_writes += m_network->functionalWrite(pkt);
DPRINTF(RubySystem, "Messages written = %u\n", num_functional_writes);