2009-05-11 19:38:43 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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$
|
|
|
|
*/
|
|
|
|
|
2009-08-04 19:52:52 +02:00
|
|
|
machine(Directory, "Directory protocol")
|
2010-01-30 05:29:26 +01:00
|
|
|
: DirectoryMemory * directory,
|
|
|
|
MemoryControl * memBuffer,
|
|
|
|
int directory_latency = 6
|
2009-08-04 19:52:52 +02:00
|
|
|
{
|
2009-05-11 19:38:43 +02:00
|
|
|
|
|
|
|
// ** 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
|
2009-08-04 19:52:52 +02:00
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
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";
|
2009-08-04 19:52:52 +02:00
|
|
|
MM_DMA, desc="Blocked, going to I";
|
2009-05-11 19:38:43 +02:00
|
|
|
|
|
|
|
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";
|
2009-08-04 19:52:52 +02:00
|
|
|
|
|
|
|
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";
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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";
|
2009-08-04 19:52:52 +02:00
|
|
|
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";
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// TYPES
|
|
|
|
|
|
|
|
// DirectoryEntry
|
2010-01-30 05:29:26 +01:00
|
|
|
structure(Entry, desc="...", interface='AbstractEntry') {
|
2009-05-11 19:38:43 +02:00
|
|
|
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";
|
|
|
|
}
|
|
|
|
|
2009-08-04 19:52:52 +02:00
|
|
|
structure(TBE, desc="...") {
|
2009-08-06 10:41:28 +02:00
|
|
|
Address PhysicalAddress, desc="Physical address for this entry";
|
2009-08-04 19:52:52 +02:00
|
|
|
int Len, desc="Length of request";
|
|
|
|
DataBlock DataBlk, desc="DataBlk";
|
|
|
|
MachineID Requestor, desc="original requestor";
|
|
|
|
}
|
|
|
|
|
|
|
|
external_type(TBETable) {
|
|
|
|
TBE lookup(Address);
|
|
|
|
void allocate(Address);
|
|
|
|
void deallocate(Address);
|
|
|
|
bool isPresent(Address);
|
|
|
|
}
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
// ** OBJECTS **
|
2009-08-04 19:52:52 +02:00
|
|
|
TBETable TBEs, template_hack="<Directory_TBE>";
|
2009-05-11 19:38:43 +02:00
|
|
|
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
void set_tbe(TBE b);
|
|
|
|
void unset_tbe();
|
|
|
|
|
2010-01-30 05:29:26 +01:00
|
|
|
Entry getDirectoryEntry(Address addr), return_by_ref="yes" {
|
|
|
|
return static_cast(Entry, directory[addr]);
|
|
|
|
}
|
|
|
|
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
State getState(TBE tbe, Address addr) {
|
2010-01-30 05:29:26 +01:00
|
|
|
return getDirectoryEntry(addr).DirectoryState;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
void setState(TBE tbe, Address addr, State state) {
|
2009-05-11 19:38:43 +02:00
|
|
|
if (directory.isPresent(addr)) {
|
|
|
|
|
|
|
|
if (state == State:I) {
|
2010-01-30 05:29:26 +01:00
|
|
|
assert(getDirectoryEntry(addr).Owner.count() == 0);
|
|
|
|
assert(getDirectoryEntry(addr).Sharers.count() == 0);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (state == State:S) {
|
2010-01-30 05:29:26 +01:00
|
|
|
assert(getDirectoryEntry(addr).Owner.count() == 0);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (state == State:O) {
|
2010-01-30 05:29:26 +01:00
|
|
|
assert(getDirectoryEntry(addr).Owner.count() == 1);
|
|
|
|
assert(getDirectoryEntry(addr).Sharers.isSuperset(getDirectoryEntry(addr).Owner) == false);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (state == State:M) {
|
2010-01-30 05:29:26 +01:00
|
|
|
assert(getDirectoryEntry(addr).Owner.count() == 1);
|
|
|
|
assert(getDirectoryEntry(addr).Sharers.count() == 0);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((state != State:SS) && (state != State:OO)) {
|
2010-01-30 05:29:26 +01:00
|
|
|
assert(getDirectoryEntry(addr).WaitingUnblocks == 0);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-01-30 05:29:26 +01:00
|
|
|
if ( (getDirectoryEntry(addr).DirectoryState != State:I) && (state == State:I) ) {
|
|
|
|
getDirectoryEntry(addr).DirectoryState := state;
|
2009-05-11 19:38:43 +02:00
|
|
|
// disable coherence checker
|
|
|
|
// sequencer.checkCoherence(addr);
|
|
|
|
}
|
|
|
|
else {
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(addr).DirectoryState := state;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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)) {
|
2010-01-30 05:29:26 +01:00
|
|
|
if (getDirectoryEntry(addr).DirectoryState == State:I) {
|
2009-05-11 19:38:43 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isBlockExclusive(Address addr) {
|
|
|
|
if (directory.isPresent(addr)) {
|
2010-01-30 05:29:26 +01:00
|
|
|
if (getDirectoryEntry(addr).DirectoryState == State:I) {
|
2009-05-11 19:38:43 +02:00
|
|
|
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);
|
2009-08-04 19:52:52 +02:00
|
|
|
out_port(memQueue_out, MemoryMsg, memBuffer);
|
2009-05-11 19:38:43 +02:00
|
|
|
|
|
|
|
// ** 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) {
|
2010-01-30 05:29:26 +01:00
|
|
|
if (getDirectoryEntry(in_msg.Address).WaitingUnblocks == 1) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:Last_Unblock, in_msg.Address,
|
|
|
|
TBEs[in_msg.Address]);
|
2009-05-11 19:38:43 +02:00
|
|
|
} else {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:Unblock, in_msg.Address,
|
|
|
|
TBEs[in_msg.Address]);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
} else if (in_msg.Type == CoherenceResponseType:UNBLOCK_EXCLUSIVE) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:Exclusive_Unblock, in_msg.Address,
|
|
|
|
TBEs[in_msg.Address]);
|
2009-05-11 19:38:43 +02:00
|
|
|
} else if (in_msg.Type == CoherenceResponseType:WRITEBACK_DIRTY_DATA) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:Dirty_Writeback, in_msg.Address,
|
|
|
|
TBEs[in_msg.Address]);
|
2009-05-11 19:38:43 +02:00
|
|
|
} else if (in_msg.Type == CoherenceResponseType:WRITEBACK_CLEAN_ACK) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:Clean_Writeback, in_msg.Address,
|
|
|
|
TBEs[in_msg.Address]);
|
2009-08-04 19:52:52 +02:00
|
|
|
} else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:Data, in_msg.Address,
|
|
|
|
TBEs[in_msg.Address]);
|
2009-05-11 19:38:43 +02:00
|
|
|
} else {
|
|
|
|
error("Invalid message");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
in_port(requestQueue_in, RequestMsg, requestToDir) {
|
|
|
|
if (requestQueue_in.isReady()) {
|
|
|
|
peek(requestQueue_in, RequestMsg) {
|
|
|
|
if (in_msg.Type == CoherenceRequestType:GETS) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:GETS, in_msg.Address, TBEs[in_msg.Address]);
|
2009-05-11 19:38:43 +02:00
|
|
|
} else if (in_msg.Type == CoherenceRequestType:GETX) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:GETX, in_msg.Address, TBEs[in_msg.Address]);
|
2009-05-11 19:38:43 +02:00
|
|
|
} else if (in_msg.Type == CoherenceRequestType:PUTX) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:PUTX, in_msg.Address, TBEs[in_msg.Address]);
|
2009-05-11 19:38:43 +02:00
|
|
|
} else if (in_msg.Type == CoherenceRequestType:PUTO) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:PUTO, in_msg.Address, TBEs[in_msg.Address]);
|
2009-05-11 19:38:43 +02:00
|
|
|
} else if (in_msg.Type == CoherenceRequestType:PUTO_SHARERS) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:PUTO_SHARERS, in_msg.Address, TBEs[in_msg.Address]);
|
2009-08-04 19:52:52 +02:00
|
|
|
} else if (in_msg.Type == CoherenceRequestType:DMA_READ) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:DMA_READ, makeLineAddress(in_msg.Address),
|
|
|
|
TBEs[makeLineAddress(in_msg.Address)]);
|
2009-08-04 19:52:52 +02:00
|
|
|
} else if (in_msg.Type == CoherenceRequestType:DMA_WRITE) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:DMA_WRITE, makeLineAddress(in_msg.Address),
|
|
|
|
TBEs[makeLineAddress(in_msg.Address)]);
|
2009-08-04 19:52:52 +02:00
|
|
|
} 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) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:Memory_Data, in_msg.Address, TBEs[in_msg.Address]);
|
2009-08-04 19:52:52 +02:00
|
|
|
} else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
trigger(Event:Memory_Ack, in_msg.Address, TBEs[in_msg.Address]);
|
2009-05-11 19:38:43 +02:00
|
|
|
} else {
|
2010-12-01 20:30:04 +01:00
|
|
|
DPRINTF(RubySlicc, "%s\n", in_msg.Type);
|
2009-05-11 19:38:43 +02:00
|
|
|
error("Invalid message");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Actions
|
|
|
|
|
|
|
|
action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") {
|
|
|
|
peek(requestQueue_in, RequestMsg) {
|
2009-08-04 19:52:52 +02:00
|
|
|
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
|
2009-05-11 19:38:43 +02:00
|
|
|
out_msg.Address := address;
|
|
|
|
out_msg.Type := CoherenceRequestType:WB_ACK;
|
|
|
|
out_msg.Requestor := in_msg.Requestor;
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
out_msg.RequestorMachine := MachineType:Directory;
|
2009-05-11 19:38:43 +02:00
|
|
|
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) {
|
2009-08-04 19:52:52 +02:00
|
|
|
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
|
2009-05-11 19:38:43 +02:00
|
|
|
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") {
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(address).Owner.clear();
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
action(c_moveOwnerToSharer, "cc", desc="Move owner to sharers") {
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(address).Sharers.addNetDest(getDirectoryEntry(address).Owner);
|
|
|
|
getDirectoryEntry(address).Owner.clear();
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
action(cc_clearSharers, "\c", desc="Clear the sharers field") {
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(address).Sharers.clear();
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2009-08-04 19:52:52 +02:00
|
|
|
action(d_sendDataMsg, "d", desc="Send data to requestor") {
|
|
|
|
peek(memQueue_in, MemoryMsg) {
|
|
|
|
enqueue(responseNetwork_out, ResponseMsg, latency="1") {
|
2009-05-11 19:38:43 +02:00
|
|
|
out_msg.Address := address;
|
|
|
|
out_msg.Sender := machineID;
|
|
|
|
out_msg.SenderMachine := MachineType:Directory;
|
2009-08-04 19:52:52 +02:00
|
|
|
out_msg.Destination.add(in_msg.OriginalRequestorMachId);
|
2010-01-30 05:29:26 +01:00
|
|
|
//out_msg.DataBlk := getDirectoryEntry(in_msg.Address).DataBlk;
|
2009-08-04 19:52:52 +02:00
|
|
|
out_msg.DataBlk := in_msg.DataBlk;
|
2009-05-11 19:38:43 +02:00
|
|
|
out_msg.Dirty := false; // By definition, the block is now clean
|
2009-08-04 19:52:52 +02:00
|
|
|
out_msg.Acks := in_msg.Acks;
|
|
|
|
if (in_msg.ReadX) {
|
|
|
|
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
|
|
|
|
} else {
|
|
|
|
out_msg.Type := CoherenceResponseType:DATA;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
out_msg.MessageSize := MessageSizeType:Response_Data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-11 17:58:37 +02:00
|
|
|
action(p_fwdDataToDMA, "\d", desc="Send data to requestor") {
|
|
|
|
peek(requestQueue_in, RequestMsg) {
|
|
|
|
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.Requestor);
|
2010-01-30 05:29:26 +01:00
|
|
|
out_msg.DataBlk := getDirectoryEntry(in_msg.Address).DataBlk;
|
2009-09-11 17:58:37 +02:00
|
|
|
out_msg.Dirty := false; // By definition, the block is now clean
|
|
|
|
out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
|
|
|
|
out_msg.MessageSize := MessageSizeType:Response_Data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
action(e_ownerIsUnblocker, "e", desc="The owner is now the unblocker") {
|
|
|
|
peek(unblockNetwork_in, ResponseMsg) {
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(address).Owner.clear();
|
|
|
|
getDirectoryEntry(address).Owner.add(in_msg.Sender);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
action(f_forwardRequest, "f", desc="Forward request to owner") {
|
|
|
|
peek(requestQueue_in, RequestMsg) {
|
2009-08-04 19:52:52 +02:00
|
|
|
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
|
2009-05-11 19:38:43 +02:00
|
|
|
out_msg.Address := address;
|
|
|
|
out_msg.Type := in_msg.Type;
|
|
|
|
out_msg.Requestor := in_msg.Requestor;
|
2010-01-30 05:29:26 +01:00
|
|
|
out_msg.Destination.addNetDest(getDirectoryEntry(in_msg.Address).Owner);
|
|
|
|
out_msg.Acks := getDirectoryEntry(address).Sharers.count();
|
|
|
|
if (getDirectoryEntry(address).Sharers.isElement(in_msg.Requestor)) {
|
2009-05-11 19:38:43 +02:00
|
|
|
out_msg.Acks := out_msg.Acks - 1;
|
|
|
|
}
|
|
|
|
out_msg.MessageSize := MessageSizeType:Forwarded_Control;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-04 19:52:52 +02:00
|
|
|
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;
|
2010-01-30 05:29:26 +01:00
|
|
|
out_msg.Destination.addNetDest(getDirectoryEntry(in_msg.Address).Owner);
|
|
|
|
out_msg.Acks := getDirectoryEntry(address).Sharers.count();
|
|
|
|
if (getDirectoryEntry(address).Sharers.isElement(in_msg.Requestor)) {
|
2009-08-04 19:52:52 +02:00
|
|
|
out_msg.Acks := out_msg.Acks - 1;
|
|
|
|
}
|
|
|
|
out_msg.MessageSize := MessageSizeType:Forwarded_Control;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
action(g_sendInvalidations, "g", desc="Send invalidations to sharers, not including the requester") {
|
|
|
|
peek(requestQueue_in, RequestMsg) {
|
2010-01-30 05:29:26 +01:00
|
|
|
if ((getDirectoryEntry(in_msg.Address).Sharers.count() > 1) ||
|
|
|
|
((getDirectoryEntry(in_msg.Address).Sharers.count() > 0) && (getDirectoryEntry(in_msg.Address).Sharers.isElement(in_msg.Requestor) == false))) {
|
2009-08-04 19:52:52 +02:00
|
|
|
enqueue(forwardNetwork_out, RequestMsg, latency=directory_latency) {
|
2009-05-11 19:38:43 +02:00
|
|
|
out_msg.Address := address;
|
|
|
|
out_msg.Type := CoherenceRequestType:INV;
|
|
|
|
out_msg.Requestor := in_msg.Requestor;
|
2010-01-30 05:29:26 +01:00
|
|
|
// out_msg.Destination := getDirectoryEntry(in_msg.Address).Sharers;
|
|
|
|
out_msg.Destination.addNetDest(getDirectoryEntry(in_msg.Address).Sharers);
|
2009-05-11 19:38:43 +02:00
|
|
|
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);
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(in_msg.Address).DataBlk := in_msg.DataBlk;
|
2010-12-01 20:30:04 +01:00
|
|
|
DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
|
|
|
|
in_msg.Address, in_msg.DataBlk);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-31 23:38:22 +02:00
|
|
|
action(p_writeFwdDataToMemory, "p", desc="Write Response data to memory") {
|
|
|
|
peek(unblockNetwork_in, ResponseMsg) {
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(in_msg.Address).DataBlk := in_msg.DataBlk;
|
2010-12-01 20:30:04 +01:00
|
|
|
DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
|
|
|
|
in_msg.Address, in_msg.DataBlk);
|
2009-08-31 23:38:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-04 19:52:52 +02:00
|
|
|
action(ll_checkDataInMemory, "\ld", desc="Check PUTX/PUTO data is same as in the memory") {
|
2009-05-11 19:38:43 +02:00
|
|
|
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
|
2010-01-30 05:29:26 +01:00
|
|
|
assert(getDirectoryEntry(in_msg.Address).DataBlk == in_msg.DataBlk);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
action(m_addUnlockerToSharers, "m", desc="Add the unlocker to the sharer list") {
|
|
|
|
peek(unblockNetwork_in, ResponseMsg) {
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(address).Sharers.add(in_msg.Sender);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
action(n_incrementOutstanding, "n", desc="Increment outstanding requests") {
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(address).WaitingUnblocks := getDirectoryEntry(address).WaitingUnblocks + 1;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
action(o_decrementOutstanding, "o", desc="Decrement outstanding requests") {
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(address).WaitingUnblocks := getDirectoryEntry(address).WaitingUnblocks - 1;
|
|
|
|
assert(getDirectoryEntry(address).WaitingUnblocks >= 0);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2009-08-04 19:52:52 +02:00
|
|
|
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;
|
2010-01-30 05:29:26 +01:00
|
|
|
out_msg.DataBlk := getDirectoryEntry(in_msg.Address).DataBlk;
|
2009-08-04 19:52:52 +02:00
|
|
|
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:
|
2010-01-30 05:29:26 +01:00
|
|
|
out_msg.ReadX := (in_msg.Type == CoherenceRequestType:GETS && getDirectoryEntry(address).Sharers.count() == 0);
|
|
|
|
out_msg.Acks := getDirectoryEntry(address).Sharers.count();
|
|
|
|
if (getDirectoryEntry(address).Sharers.isElement(in_msg.Requestor)) {
|
2009-08-04 19:52:52 +02:00
|
|
|
out_msg.Acks := out_msg.Acks - 1;
|
|
|
|
}
|
2010-12-01 20:30:04 +01:00
|
|
|
DPRINTF(RubySlicc, "%s\n", out_msg);
|
2009-08-04 19:52:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
if (is_valid(tbe)) {
|
|
|
|
out_msg.OriginalRequestorMachId := tbe.Requestor;
|
|
|
|
}
|
2009-08-04 19:52:52 +02:00
|
|
|
out_msg.DataBlk := in_msg.DataBlk;
|
|
|
|
out_msg.MessageSize := in_msg.MessageSize;
|
|
|
|
//out_msg.Prefetch := false;
|
|
|
|
// Not used:
|
|
|
|
out_msg.ReadX := false;
|
2010-01-30 05:29:26 +01:00
|
|
|
out_msg.Acks := getDirectoryEntry(address).Sharers.count(); // for dma requests
|
2010-12-01 20:30:04 +01:00
|
|
|
DPRINTF(RubySlicc, "%s\n", out_msg);
|
2009-08-04 19:52:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2010-01-30 05:29:26 +01:00
|
|
|
out_msg.Acks := getDirectoryEntry(address).Sharers.count(); // for dma requests
|
2010-12-01 20:30:04 +01:00
|
|
|
DPRINTF(RubySlicc, "%s\n", out_msg);
|
2009-08-04 19:52:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
|
2009-08-04 19:52:52 +02:00
|
|
|
action(a_sendDMAAck, "\a", desc="Send DMA Ack that write completed, along with Inv Ack count") {
|
2009-08-31 23:38:22 +02:00
|
|
|
peek(requestQueue_in, RequestMsg) {
|
2009-08-04 19:52:52 +02:00
|
|
|
enqueue(responseNetwork_out, ResponseMsg, latency="1") {
|
|
|
|
out_msg.Address := address;
|
|
|
|
out_msg.Sender := machineID;
|
|
|
|
out_msg.SenderMachine := MachineType:Directory;
|
2009-08-31 23:38:22 +02:00
|
|
|
out_msg.Destination.add(in_msg.Requestor);
|
|
|
|
out_msg.DataBlk := in_msg.DataBlk;
|
2010-01-30 05:29:26 +01:00
|
|
|
out_msg.Acks := getDirectoryEntry(address).Sharers.count(); // for dma requests
|
2009-08-31 23:38:22 +02:00
|
|
|
out_msg.Type := CoherenceResponseType:DMA_ACK;
|
|
|
|
out_msg.MessageSize := MessageSizeType:Writeback_Control;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
action(a_sendDMAAck2, "\aa", desc="Send DMA Ack that write completed, along with Inv Ack count") {
|
|
|
|
peek(unblockNetwork_in, ResponseMsg) {
|
|
|
|
enqueue(responseNetwork_out, ResponseMsg, latency="1") {
|
|
|
|
out_msg.Address := address;
|
|
|
|
out_msg.Sender := machineID;
|
|
|
|
out_msg.SenderMachine := MachineType:Directory;
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
if (is_valid(tbe)) {
|
|
|
|
out_msg.Destination.add(tbe.Requestor);
|
2009-08-31 23:38:22 +02:00
|
|
|
}
|
2009-08-04 19:52:52 +02:00
|
|
|
out_msg.DataBlk := in_msg.DataBlk;
|
2010-01-30 05:29:26 +01:00
|
|
|
out_msg.Acks := getDirectoryEntry(address).Sharers.count(); // for dma requests
|
2009-08-04 19:52:52 +02:00
|
|
|
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) {
|
2010-01-30 05:29:26 +01:00
|
|
|
getDirectoryEntry(address).DataBlk.copyPartial(in_msg.DataBlk, addressOffset(in_msg.Address), in_msg.Len);
|
2009-08-04 19:52:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
action(l_writeDMADataToMemoryFromTBE, "\ll", desc="Write data from a DMA_WRITE to memory") {
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
assert(is_valid(tbe));
|
|
|
|
getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk,
|
|
|
|
addressOffset(tbe.PhysicalAddress), tbe.Len);
|
2009-08-04 19:52:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
action(v_allocateTBE, "v", desc="Allocate TBE entry") {
|
|
|
|
peek (requestQueue_in, RequestMsg) {
|
|
|
|
TBEs.allocate(address);
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
set_tbe(TBEs[address]);
|
|
|
|
tbe.PhysicalAddress := in_msg.Address;
|
|
|
|
tbe.Len := in_msg.Len;
|
|
|
|
tbe.DataBlk := in_msg.DataBlk;
|
|
|
|
tbe.Requestor := in_msg.Requestor;
|
2009-08-04 19:52:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
action(w_deallocateTBE, "w", desc="Deallocate TBE entry") {
|
|
|
|
TBEs.deallocate(address);
|
Change interface between coherence protocols and CacheMemory
The purpose of this patch is to change the way CacheMemory interfaces with
coherence protocols. Currently, whenever a cache controller (defined in the
protocol under consideration) needs to carry out any operation on a cache
block, it looks up the tag hash map and figures out whether or not the block
exists in the cache. In case it does exist, the operation is carried out
(which requires another lookup). As observed through profiling of different
protocols, multiple such lookups take place for a given cache block. It was
noted that the tag lookup takes anything from 10% to 20% of the simulation
time. In order to reduce this time, this patch is being posted.
I have to acknowledge that the many of the thoughts that went in to this
patch belong to Brad.
Changes to CacheMemory, TBETable and AbstractCacheEntry classes:
1. The lookup function belonging to CacheMemory class now returns a pointer
to a cache block entry, instead of a reference. The pointer is NULL in case
the block being looked up is not present in the cache. Similar change has
been carried out in the lookup function of the TBETable class.
2. Function for setting and getting access permission of a cache block have
been moved from CacheMemory class to AbstractCacheEntry class.
3. The allocate function in CacheMemory class now returns pointer to the
allocated cache entry.
Changes to SLICC:
1. Each action now has implicit variables - cache_entry and tbe. cache_entry,
if != NULL, must point to the cache entry for the address on which the action
is being carried out. Similarly, tbe should also point to the transaction
buffer entry of the address on which the action is being carried out.
2. If a cache entry or a transaction buffer entry is passed on as an
argument to a function, it is presumed that a pointer is being passed on.
3. The cache entry and the tbe pointers received __implicitly__ by the
actions, are passed __explicitly__ to the trigger function.
4. While performing an action, set/unset_cache_entry, set/unset_tbe are to
be used for setting / unsetting cache entry and tbe pointers respectively.
5. is_valid() and is_invalid() has been made available for testing whether
a given pointer 'is not NULL' and 'is NULL' respectively.
6. Local variables are now available, but they are assumed to be pointers
always.
7. It is now possible for an object of the derieved class to make calls to
a function defined in the interface.
8. An OOD token has been introduced in SLICC. It is same as the NULL token
used in C/C++. If you are wondering, OOD stands for Out Of Domain.
9. static_cast can now taken an optional parameter that asks for casting the
given variable to a pointer of the given type.
10. Functions can be annotated with 'return_by_pointer=yes' to return a
pointer.
11. StateMachine has two new variables, EntryType and TBEType. EntryType is
set to the type which inherits from 'AbstractCacheEntry'. There can only be
one such type in the machine. TBEType is set to the type for which 'TBE' is
used as the name.
All the protocols have been modified to conform with the new interface.
2011-01-18 01:46:16 +01:00
|
|
|
unset_tbe();
|
2009-08-04 19:52:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
// TRANSITIONS
|
|
|
|
|
|
|
|
transition(I, GETX, MM) {
|
2009-08-04 19:52:52 +02:00
|
|
|
qf_queueMemoryFetchRequest;
|
|
|
|
i_popIncomingRequestQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
transition(I, DMA_READ, XI_M) {
|
|
|
|
qf_queueMemoryFetchRequest;
|
2009-05-11 19:38:43 +02:00
|
|
|
i_popIncomingRequestQueue;
|
|
|
|
}
|
|
|
|
|
2009-08-31 23:38:22 +02:00
|
|
|
transition(I, DMA_WRITE, XI_U) {
|
2009-08-04 19:52:52 +02:00
|
|
|
qw_queueMemoryWBRequest2;
|
2009-08-31 23:38:22 +02:00
|
|
|
a_sendDMAAck; // ack count may be zero
|
2009-08-04 19:52:52 +02:00
|
|
|
l_writeDMADataToMemory;
|
|
|
|
i_popIncomingRequestQueue;
|
|
|
|
}
|
|
|
|
|
2009-09-11 17:58:37 +02:00
|
|
|
transition(XI_M, Memory_Data, I) {
|
2009-08-04 19:52:52 +02:00
|
|
|
d_sendDataMsg; // ack count may be zero
|
|
|
|
q_popMemQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
transition(XI_U, Exclusive_Unblock, I) {
|
|
|
|
cc_clearSharers;
|
|
|
|
c_clearOwner;
|
|
|
|
j_popIncomingUnblockQueue;
|
|
|
|
}
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
transition(S, GETX, MM) {
|
2009-08-04 19:52:52 +02:00
|
|
|
qf_queueMemoryFetchRequest;
|
2009-05-11 19:38:43 +02:00
|
|
|
g_sendInvalidations;
|
|
|
|
i_popIncomingRequestQueue;
|
|
|
|
}
|
|
|
|
|
2009-09-11 17:58:37 +02:00
|
|
|
transition(S, DMA_READ, S) {
|
|
|
|
//qf_queueMemoryFetchRequest;
|
|
|
|
p_fwdDataToDMA;
|
|
|
|
//g_sendInvalidations; // the DMA will collect the invalidations then send an Unblock Exclusive
|
2009-08-04 19:52:52 +02:00
|
|
|
i_popIncomingRequestQueue;
|
|
|
|
}
|
|
|
|
|
2009-08-31 23:38:22 +02:00
|
|
|
transition(S, DMA_WRITE, XI_U) {
|
2009-08-04 19:52:52 +02:00
|
|
|
qw_queueMemoryWBRequest2;
|
2009-08-31 23:38:22 +02:00
|
|
|
a_sendDMAAck; // ack count may be zero
|
2009-08-04 19:52:52 +02:00
|
|
|
l_writeDMADataToMemory;
|
|
|
|
g_sendInvalidations; // the DMA will collect invalidations
|
|
|
|
i_popIncomingRequestQueue;
|
|
|
|
}
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
transition(I, GETS, IS) {
|
2009-08-04 19:52:52 +02:00
|
|
|
qf_queueMemoryFetchRequest;
|
2009-05-11 19:38:43 +02:00
|
|
|
i_popIncomingRequestQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
transition({S, SS}, GETS, SS) {
|
2009-08-04 19:52:52 +02:00
|
|
|
qf_queueMemoryFetchRequest;
|
2009-05-11 19:38:43 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-09-11 17:58:37 +02:00
|
|
|
transition(O, DMA_READ, O) {
|
2009-08-04 19:52:52 +02:00
|
|
|
f_forwardRequest; // this will cause the data to go to DMA directly
|
2009-09-11 17:58:37 +02:00
|
|
|
//g_sendInvalidations; // this will cause acks to be sent to the DMA
|
2009-08-04 19:52:52 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-08-31 23:38:22 +02:00
|
|
|
transition(OI_D, Data, XI_U) {
|
2009-08-04 19:52:52 +02:00
|
|
|
qw_queueMemoryWBRequest;
|
2009-08-31 23:38:22 +02:00
|
|
|
a_sendDMAAck2; // ack count may be zero
|
|
|
|
p_writeFwdDataToMemory;
|
2009-08-04 19:52:52 +02:00
|
|
|
l_writeDMADataToMemoryFromTBE;
|
|
|
|
w_deallocateTBE;
|
|
|
|
j_popIncomingUnblockQueue;
|
|
|
|
}
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
transition({O, OO}, GETS, OO) {
|
|
|
|
f_forwardRequest;
|
|
|
|
n_incrementOutstanding;
|
|
|
|
i_popIncomingRequestQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
transition(M, GETX, MM) {
|
|
|
|
f_forwardRequest;
|
|
|
|
i_popIncomingRequestQueue;
|
|
|
|
}
|
|
|
|
|
2009-08-04 19:52:52 +02:00
|
|
|
// no exclusive unblock will show up to the directory
|
2009-09-11 17:58:37 +02:00
|
|
|
transition(M, DMA_READ, M) {
|
2009-08-04 19:52:52 +02:00
|
|
|
f_forwardRequest; // this will cause the data to go to DMA directly
|
|
|
|
i_popIncomingRequestQueue;
|
|
|
|
}
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-09 20:58:40 +02:00
|
|
|
transition({MM, MO, MI, MIS, OS, OSS, XI_M, XI_U, OI_D}, {GETS, GETX, PUTO, PUTO_SHARERS, PUTX, DMA_READ, DMA_WRITE}) {
|
2009-05-11 19:38:43 +02:00
|
|
|
zz_recycleRequest;
|
|
|
|
}
|
|
|
|
|
|
|
|
transition({MM, MO}, Exclusive_Unblock, M) {
|
|
|
|
cc_clearSharers;
|
|
|
|
e_ownerIsUnblocker;
|
|
|
|
j_popIncomingUnblockQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
transition(MO, Unblock, O) {
|
|
|
|
m_addUnlockerToSharers;
|
|
|
|
j_popIncomingUnblockQueue;
|
|
|
|
}
|
|
|
|
|
2009-08-09 20:58:40 +02:00
|
|
|
transition({IS, SS, OO}, {GETX, PUTO, PUTO_SHARERS, PUTX, DMA_READ, DMA_WRITE}) {
|
2009-05-11 19:38:43 +02:00
|
|
|
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;
|
2009-08-04 19:52:52 +02:00
|
|
|
qw_queueMemoryWBRequest;
|
2009-05-11 19:38:43 +02:00
|
|
|
j_popIncomingUnblockQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
transition(MIS, Dirty_Writeback, S) {
|
|
|
|
c_moveOwnerToSharer;
|
|
|
|
l_writeDataToMemory;
|
2009-08-04 19:52:52 +02:00
|
|
|
qw_queueMemoryWBRequest;
|
2009-05-11 19:38:43 +02:00
|
|
|
j_popIncomingUnblockQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
transition(MIS, Clean_Writeback, S) {
|
|
|
|
c_moveOwnerToSharer;
|
|
|
|
j_popIncomingUnblockQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
transition(OS, Dirty_Writeback, S) {
|
|
|
|
c_clearOwner;
|
|
|
|
l_writeDataToMemory;
|
2009-08-04 19:52:52 +02:00
|
|
|
qw_queueMemoryWBRequest;
|
2009-05-11 19:38:43 +02:00
|
|
|
j_popIncomingUnblockQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
transition(OSS, Dirty_Writeback, S) {
|
|
|
|
c_moveOwnerToSharer;
|
|
|
|
l_writeDataToMemory;
|
2009-08-04 19:52:52 +02:00
|
|
|
qw_queueMemoryWBRequest;
|
2009-05-11 19:38:43 +02:00
|
|
|
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;
|
|
|
|
}
|
2009-08-04 19:52:52 +02:00
|
|
|
|
|
|
|
transition({I, S, O, M, IS, SS, OO, MO, MM, MI, MIS, OS, OSS}, Memory_Data) {
|
|
|
|
d_sendDataMsg;
|
|
|
|
q_popMemQueue;
|
|
|
|
}
|
|
|
|
|
2009-08-31 23:38:22 +02:00
|
|
|
transition({I, S, O, M, IS, SS, OO, MO, MM, MI, MIS, OS, OSS, XI_U, XI_M}, Memory_Ack) {
|
2009-08-04 19:52:52 +02:00
|
|
|
//a_sendAck;
|
|
|
|
q_popMemQueue;
|
|
|
|
}
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|