SLICC: Use pointers for directory entries
SLICC uses pointers for cache and TBE entries but not for directory entries. This patch changes the protocols, SLICC and Ruby memory system so that even directory entries are referenced using pointers. --HG-- extra : rebase_source : abeb4ac78033d003153751f216fd1948251fcfad
This commit is contained in:
parent
19e65a6502
commit
734ef9a209
|
@ -110,8 +110,16 @@ machine(Directory, "MESI_CMP_filter_directory protocol")
|
|||
void set_tbe(TBE tbe);
|
||||
void unset_tbe();
|
||||
|
||||
Entry getDirectoryEntry(Address addr), return_by_ref="yes" {
|
||||
return static_cast(Entry, directory[addr]);
|
||||
Entry getDirectoryEntry(Address addr), return_by_pointer="yes" {
|
||||
Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
|
||||
|
||||
if (is_valid(dir_entry)) {
|
||||
return dir_entry;
|
||||
}
|
||||
|
||||
dir_entry := static_cast(Entry, "pointer",
|
||||
directory.allocate(addr, new Entry));
|
||||
return dir_entry;
|
||||
}
|
||||
|
||||
State getState(TBE tbe, Address addr) {
|
||||
|
|
|
@ -79,8 +79,16 @@ machine(Directory, "Directory protocol")
|
|||
void set_tbe(TBE b);
|
||||
void unset_tbe();
|
||||
|
||||
Entry getDirectoryEntry(Address addr), return_by_ref="yes" {
|
||||
return static_cast(Entry, directory[addr]);
|
||||
Entry getDirectoryEntry(Address addr), return_by_pointer="yes" {
|
||||
Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
|
||||
|
||||
if (is_valid(dir_entry)) {
|
||||
return dir_entry;
|
||||
}
|
||||
|
||||
dir_entry := static_cast(Entry, "pointer",
|
||||
directory.allocate(addr, new Entry));
|
||||
return dir_entry;
|
||||
}
|
||||
|
||||
State getState(TBE tbe, Address addr) {
|
||||
|
|
|
@ -126,8 +126,16 @@ machine(Directory, "Directory protocol")
|
|||
void set_tbe(TBE b);
|
||||
void unset_tbe();
|
||||
|
||||
Entry getDirectoryEntry(Address addr), return_by_ref="yes" {
|
||||
return static_cast(Entry, directory[addr]);
|
||||
Entry getDirectoryEntry(Address addr), return_by_pointer="yes" {
|
||||
Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
|
||||
|
||||
if (is_valid(dir_entry)) {
|
||||
return dir_entry;
|
||||
}
|
||||
|
||||
dir_entry := static_cast(Entry, "pointer",
|
||||
directory.allocate(addr, new Entry));
|
||||
return dir_entry;
|
||||
}
|
||||
|
||||
State getState(TBE tbe, Address addr) {
|
||||
|
|
|
@ -165,8 +165,16 @@ machine(Directory, "Token protocol")
|
|||
void set_tbe(TBE b);
|
||||
void unset_tbe();
|
||||
|
||||
Entry getDirectoryEntry(Address addr), return_by_ref="yes" {
|
||||
return static_cast(Entry, directory[addr]);
|
||||
Entry getDirectoryEntry(Address addr), return_by_pointer="yes" {
|
||||
Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
|
||||
|
||||
if (is_valid(dir_entry)) {
|
||||
return dir_entry;
|
||||
}
|
||||
|
||||
dir_entry := static_cast(Entry, "pointer",
|
||||
directory.allocate(addr, new Entry));
|
||||
return dir_entry;
|
||||
}
|
||||
|
||||
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
|
||||
|
|
|
@ -186,8 +186,16 @@ machine(Directory, "AMD Hammer-like protocol")
|
|||
|
||||
TBETable TBEs, template_hack="<Directory_TBE>";
|
||||
|
||||
Entry getDirectoryEntry(Address addr), return_by_ref="yes" {
|
||||
return static_cast(Entry, directory[addr]);
|
||||
Entry getDirectoryEntry(Address addr), return_by_pointer="yes" {
|
||||
Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
|
||||
|
||||
if (is_valid(dir_entry)) {
|
||||
return dir_entry;
|
||||
}
|
||||
|
||||
dir_entry := static_cast(Entry, "pointer",
|
||||
directory.allocate(addr, new Entry));
|
||||
return dir_entry;
|
||||
}
|
||||
|
||||
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
|
||||
|
|
|
@ -125,6 +125,7 @@ structure(AbstractEntry, primitive="yes", external = "yes") {
|
|||
}
|
||||
|
||||
structure (DirectoryMemory, external = "yes") {
|
||||
AbstractEntry allocate(Address, AbstractEntry);
|
||||
AbstractEntry lookup(Address);
|
||||
bool isPresent(Address);
|
||||
void invalidateBlock(Address);
|
||||
|
|
|
@ -59,7 +59,7 @@ DirectoryMemory::init()
|
|||
if (m_use_map) {
|
||||
m_sparseMemory = new SparseMemory(m_map_levels);
|
||||
} else {
|
||||
m_entries = new Directory_Entry*[m_num_entries];
|
||||
m_entries = new AbstractEntry*[m_num_entries];
|
||||
for (int i = 0; i < m_num_entries; i++)
|
||||
m_entries[i] = NULL;
|
||||
m_ram = g_system_ptr->getMemoryVector();
|
||||
|
@ -150,38 +150,40 @@ DirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
|
|||
return ret >> (RubySystem::getBlockSizeBits());
|
||||
}
|
||||
|
||||
Directory_Entry&
|
||||
AbstractEntry*
|
||||
DirectoryMemory::lookup(PhysAddress address)
|
||||
{
|
||||
assert(isPresent(address));
|
||||
Directory_Entry* entry;
|
||||
DPRINTF(RubyCache, "Looking up address: %s\n", address);
|
||||
|
||||
if (m_use_map) {
|
||||
return m_sparseMemory->lookup(address);
|
||||
} else {
|
||||
uint64_t idx = mapAddressToLocalIdx(address);
|
||||
assert(idx < m_num_entries);
|
||||
return m_entries[idx];
|
||||
}
|
||||
}
|
||||
|
||||
AbstractEntry*
|
||||
DirectoryMemory::allocate(const PhysAddress& address, AbstractEntry* entry)
|
||||
{
|
||||
assert(isPresent(address));
|
||||
uint64 idx;
|
||||
DPRINTF(RubyCache, "Looking up address: %s\n", address);
|
||||
|
||||
if (m_use_map) {
|
||||
if (m_sparseMemory->exist(address)) {
|
||||
entry = m_sparseMemory->lookup(address);
|
||||
assert(entry != NULL);
|
||||
} else {
|
||||
// Note: SparseMemory internally creates a new Directory Entry
|
||||
m_sparseMemory->add(address);
|
||||
entry = m_sparseMemory->lookup(address);
|
||||
entry->changePermission(AccessPermission_Read_Write);
|
||||
}
|
||||
m_sparseMemory->add(address, entry);
|
||||
entry->changePermission(AccessPermission_Read_Write);
|
||||
} else {
|
||||
idx = mapAddressToLocalIdx(address);
|
||||
assert(idx < m_num_entries);
|
||||
entry = m_entries[idx];
|
||||
|
||||
if (entry == NULL) {
|
||||
entry = new Directory_Entry();
|
||||
entry->getDataBlk().assign(m_ram->getBlockPtr(address));
|
||||
entry->changePermission(AccessPermission_Read_Only);
|
||||
m_entries[idx] = entry;
|
||||
}
|
||||
entry->getDataBlk().assign(m_ram->getBlockPtr(address));
|
||||
entry->changePermission(AccessPermission_Read_Only);
|
||||
m_entries[idx] = entry;
|
||||
}
|
||||
|
||||
return *entry;
|
||||
return entry;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -32,9 +32,9 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "mem/protocol/Directory_Entry.hh"
|
||||
#include "mem/ruby/common/Address.hh"
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/ruby/slicc_interface/AbstractEntry.hh"
|
||||
#include "mem/ruby/system/MemoryVector.hh"
|
||||
#include "mem/ruby/system/SparseMemory.hh"
|
||||
#include "params/RubyDirectoryMemory.hh"
|
||||
|
@ -58,7 +58,9 @@ class DirectoryMemory : public SimObject
|
|||
void printConfig(std::ostream& out) const;
|
||||
static void printGlobalConfig(std::ostream & out);
|
||||
bool isPresent(PhysAddress address);
|
||||
Directory_Entry& lookup(PhysAddress address);
|
||||
AbstractEntry* lookup(PhysAddress address);
|
||||
AbstractEntry* allocate(const PhysAddress& address,
|
||||
AbstractEntry* new_entry);
|
||||
|
||||
void invalidateBlock(PhysAddress address);
|
||||
|
||||
|
@ -72,7 +74,7 @@ class DirectoryMemory : public SimObject
|
|||
|
||||
private:
|
||||
const std::string m_name;
|
||||
Directory_Entry **m_entries;
|
||||
AbstractEntry **m_entries;
|
||||
// int m_size; // # of memory module blocks this directory is
|
||||
// responsible for
|
||||
uint64 m_size_bytes;
|
||||
|
|
|
@ -92,9 +92,7 @@ SparseMemory::recursivelyRemoveTables(SparseMapType* curTable, int curLevel)
|
|||
delete nextTable;
|
||||
} else {
|
||||
// If at the last level, delete the directory entry
|
||||
Directory_Entry* dirEntry;
|
||||
dirEntry = (Directory_Entry*)(entryStruct->entry);
|
||||
delete dirEntry;
|
||||
delete (AbstractEntry*)(entryStruct->entry);
|
||||
}
|
||||
entryStruct->entry = NULL;
|
||||
}
|
||||
|
@ -149,7 +147,7 @@ SparseMemory::exist(const Address& address) const
|
|||
|
||||
// add an address to memory
|
||||
void
|
||||
SparseMemory::add(const Address& address)
|
||||
SparseMemory::add(const Address& address, AbstractEntry* entry)
|
||||
{
|
||||
assert(address == line_address(address));
|
||||
assert(!exist(address));
|
||||
|
@ -187,9 +185,8 @@ SparseMemory::add(const Address& address)
|
|||
|
||||
// if the last level, add a directory entry. Otherwise add a map.
|
||||
if (level == (m_number_of_levels - 1)) {
|
||||
Directory_Entry* tempDirEntry = new Directory_Entry();
|
||||
tempDirEntry->getDataBlk().clear();
|
||||
newEntry = (void*)tempDirEntry;
|
||||
entry->getDataBlk().clear();
|
||||
newEntry = (void*)entry;
|
||||
} else {
|
||||
SparseMapType* tempMap = new SparseMapType;
|
||||
newEntry = (void*)(tempMap);
|
||||
|
@ -262,10 +259,8 @@ SparseMemory::recursivelyRemoveLevels(const Address& address,
|
|||
// if this is the last level, we have reached the Directory
|
||||
// Entry and thus we should delete it including the
|
||||
// SparseMemEntry container struct.
|
||||
Directory_Entry* dirEntry;
|
||||
dirEntry = (Directory_Entry*)(entryStruct->entry);
|
||||
delete (AbstractEntry*)(entryStruct->entry);
|
||||
entryStruct->entry = NULL;
|
||||
delete dirEntry;
|
||||
curInfo.curTable->erase(curAddress);
|
||||
m_removes_per_level[curInfo.level]++;
|
||||
}
|
||||
|
@ -303,17 +298,14 @@ SparseMemory::remove(const Address& address)
|
|||
}
|
||||
|
||||
// looks an address up in memory
|
||||
Directory_Entry*
|
||||
AbstractEntry*
|
||||
SparseMemory::lookup(const Address& address)
|
||||
{
|
||||
assert(exist(address));
|
||||
assert(address == line_address(address));
|
||||
|
||||
DPRINTF(RubyCache, "address: %s\n", address);
|
||||
|
||||
Address curAddress;
|
||||
SparseMapType* curTable = m_map_head;
|
||||
Directory_Entry* entry = NULL;
|
||||
AbstractEntry* entry = NULL;
|
||||
|
||||
// Initiallize the high bit to be the total number of bits plus
|
||||
// the block offset. However the highest bit index is one less
|
||||
|
@ -336,13 +328,18 @@ SparseMemory::lookup(const Address& address)
|
|||
// Adjust the highBit value for the next level
|
||||
highBit -= m_number_of_bits_per_level[level];
|
||||
|
||||
// The entry should be in the table and valid
|
||||
curTable = (SparseMapType*)(((*curTable)[curAddress]).entry);
|
||||
assert(curTable != NULL);
|
||||
// If the address is found, move on to the next level.
|
||||
// Otherwise, return not found
|
||||
if (curTable->count(curAddress) != 0) {
|
||||
curTable = (SparseMapType*)(((*curTable)[curAddress]).entry);
|
||||
} else {
|
||||
DPRINTF(RubyCache, "Not found\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// The last entry actually points to the Directory entry not a table
|
||||
entry = (Directory_Entry*)curTable;
|
||||
entry = (AbstractEntry*)curTable;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <iostream>
|
||||
|
||||
#include "base/hashmap.hh"
|
||||
#include "mem/protocol/Directory_Entry.hh"
|
||||
#include "mem/ruby/slicc_interface/AbstractEntry.hh"
|
||||
#include "mem/ruby/common/Address.hh"
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
|
||||
|
@ -60,10 +60,10 @@ class SparseMemory
|
|||
void printConfig(std::ostream& out) { }
|
||||
|
||||
bool exist(const Address& address) const;
|
||||
void add(const Address& address);
|
||||
void add(const Address& address, AbstractEntry*);
|
||||
void remove(const Address& address);
|
||||
|
||||
Directory_Entry* lookup(const Address& address);
|
||||
AbstractEntry* lookup(const Address& address);
|
||||
|
||||
// Print cache contents
|
||||
void print(std::ostream& out) const;
|
||||
|
|
|
@ -52,8 +52,9 @@ class FormalParamAST(AST):
|
|||
self.pairs)
|
||||
self.symtab.newSymbol(v)
|
||||
if self.pointer or str(type) == "TBE" or (
|
||||
"interface" in type and type["interface"] == "AbstractCacheEntry"):
|
||||
|
||||
"interface" in type and (
|
||||
type["interface"] == "AbstractCacheEntry" or
|
||||
type["interface"] == "AbstractEntry")):
|
||||
return type, "%s* %s" % (type.c_ident, param)
|
||||
else:
|
||||
return type, "const %s& %s" % (type.c_ident, param)
|
||||
|
|
|
@ -52,7 +52,9 @@ class LocalVariableAST(StatementAST):
|
|||
self.pairs)
|
||||
self.symtab.newSymbol(v)
|
||||
if self.pointer or str(type) == "TBE" or (
|
||||
"interface" in type and type["interface"] == "AbstractCacheEntry"):
|
||||
"interface" in type and (
|
||||
type["interface"] == "AbstractCacheEntry" or
|
||||
type["interface"] == "AbstractEntry")):
|
||||
code += "%s* %s" % (type.c_ident, ident)
|
||||
else:
|
||||
code += "%s %s" % (type.c_ident, ident)
|
||||
|
|
|
@ -41,7 +41,10 @@ class MemberExprAST(ExprAST):
|
|||
return_type, gcode = self.expr_ast.inline(True)
|
||||
fix = code.nofix()
|
||||
|
||||
if str(return_type) == "TBE" or ("interface" in return_type and return_type["interface"] == "AbstractCacheEntry"):
|
||||
if str(return_type) == "TBE" \
|
||||
or ("interface" in return_type and
|
||||
(return_type["interface"] == "AbstractCacheEntry" or
|
||||
return_type["interface"] == "AbstractEntry")):
|
||||
code("(*$gcode).m_${{self.field}}")
|
||||
else:
|
||||
code("($gcode).m_${{self.field}}")
|
||||
|
|
|
@ -162,8 +162,10 @@ class MemberMethodCallExprAST(MethodCallExprAST):
|
|||
prefix = "static_cast<%s &>" % return_type.c_ident
|
||||
|
||||
if str(obj_type) == "AbstractCacheEntry" or \
|
||||
("interface" in obj_type and
|
||||
obj_type["interface"] == "AbstractCacheEntry"):
|
||||
str(obj_type) == "AbstractEntry" or \
|
||||
("interface" in obj_type and (
|
||||
obj_type["interface"] == "AbstractCacheEntry" or
|
||||
obj_type["interface"] == "AbstractEntry")):
|
||||
prefix = "%s((*(%s))." % (prefix, code)
|
||||
else:
|
||||
prefix = "%s((%s)." % (prefix, code)
|
||||
|
|
Loading…
Reference in a new issue