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