diff --git a/src/mem/protocol/RubySlicc_Types.sm b/src/mem/protocol/RubySlicc_Types.sm
--- a/src/mem/protocol/RubySlicc_Types.sm
+++ b/src/mem/protocol/RubySlicc_Types.sm
@@ -117,15 +117,17 @@
void invalidateBlock(Address);
}
-external_type(AbstractCacheEntry, primitive="yes");
+external_type(AbstractCacheEntry, primitive="yes") {
+ void changePermission(AccessPermission);
+}
external_type(CacheMemory) {
bool cacheAvail(Address);
Address cacheProbe(Address);
- void allocate(Address, AbstractCacheEntry);
+ AbstractCacheEntry allocate(Address, AbstractCacheEntry);
void deallocate(Address);
AbstractCacheEntry lookup(Address);
- void changePermission(Address, AccessPermission);
+ AbstractCacheEntry lookup_ptr(Address);
bool isTagPresent(Address);
void profileMiss(CacheMsg);
diff --git a/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh b/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh
--- a/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh
+++ b/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh
@@ -48,11 +48,17 @@
AbstractCacheEntry();
virtual ~AbstractCacheEntry() = 0;
+ // Get/Set permission of cache entry
+ AccessPermission getPermission() const;
+ void changePermission(AccessPermission new_perm);
+
Address m_Address; // Address of this block, required by CacheMemory
Time m_LastRef; // Last time this block was referenced, required
// by CacheMemory
AccessPermission m_Permission; // Access permission for this
// block, required by CacheMemory
+ int m_locked; // Holds info whether the address is locked,
+ // required for implementing LL/SC
};
inline std::ostream&
@@ -64,4 +70,3 @@
}
#endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCACHEENTRY_HH__
-
diff --git a/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc b/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc
--- a/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc
+++ b/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc
@@ -32,9 +32,26 @@
{
m_Address.setAddress(0);
m_Permission = AccessPermission_NotPresent;
+ m_locked = -1;
}
AbstractCacheEntry::~AbstractCacheEntry()
{
}
+AccessPermission
+AbstractCacheEntry::getPermission() const
+{
+ return m_Permission;
+}
+
+void
+AbstractCacheEntry::changePermission(AccessPermission new_perm)
+{
+ m_Permission = new_perm;
+ if ((new_perm == AccessPermission_Invalid) ||
+ (new_perm == AccessPermission_NotPresent) ||
+ (new_perm == AccessPermission_Stale)) {
+ m_locked = -1;
+ }
+}
diff --git a/src/mem/ruby/system/CacheMemory.hh b/src/mem/ruby/system/CacheMemory.hh
--- a/src/mem/ruby/system/CacheMemory.hh
+++ b/src/mem/ruby/system/CacheMemory.hh
@@ -82,7 +82,7 @@
bool cacheAvail(const Address& address) const;
// find an unused entry and sets the tag appropriate for the address
- void allocate(const Address& address, AbstractCacheEntry* new_entry);
+ AbstractCacheEntry* allocate(const Address& address, AbstractCacheEntry* new_entry);
// Explicitly free up this address
void deallocate(const Address& address);
@@ -91,13 +91,13 @@
Address cacheProbe(const Address& address) const;
// looks an address up in the cache
+ AbstractCacheEntry* lookup_ptr(const Address& address);
+ const AbstractCacheEntry* lookup_ptr(const Address& address) const;
+
+ // looks an address up in the cache
AbstractCacheEntry& lookup(const Address& address);
const AbstractCacheEntry& lookup(const Address& address) const;
- // Get/Set permission of cache block
- AccessPermission getPermission(const Address& address) const;
- void changePermission(const Address& address, AccessPermission new_perm);
-
int getLatency() const { return m_latency; }
// Hook for checkpointing the contents of the cache
@@ -158,7 +158,6 @@
// The second index is the the amount associativity.
m5::hash_map
m_tag_index;
std::vector > m_cache;
- std::vector > m_locked;
AbstractReplacementPolicy *m_replacementPolicy_ptr;
diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc
--- a/src/mem/ruby/system/CacheMemory.cc
+++ b/src/mem/ruby/system/CacheMemory.cc
@@ -75,13 +75,10 @@
assert(false);
m_cache.resize(m_cache_num_sets);
- m_locked.resize(m_cache_num_sets);
for (int i = 0; i < m_cache_num_sets; i++) {
m_cache[i].resize(m_cache_assoc);
- m_locked[i].resize(m_cache_assoc);
for (int j = 0; j < m_cache_assoc; j++) {
m_cache[i][j] = NULL;
- m_locked[i][j] = -1;
}
}
}
@@ -255,7 +252,7 @@
return false;
}
-void
+AbstractCacheEntry*
CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry)
{
assert(address == line_address(address));
@@ -273,13 +270,13 @@
set[i]->m_Permission = AccessPermission_Invalid;
DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n",
address);
- m_locked[cacheSet][i] = -1;
+ set[i]->m_locked = -1;
m_tag_index[address] = i;
m_replacementPolicy_ptr->
touch(cacheSet, i, g_eventQueue_ptr->getTime());
- return;
+ return entry;
}
}
panic("Allocate didn't find an available entry");
@@ -296,9 +293,6 @@
if (loc != -1) {
delete m_cache[cacheSet][loc];
m_cache[cacheSet][loc] = NULL;
- DPRINTF(RubyCache, "Deallocate clearing lock for addr: %x\n",
- address);
- m_locked[cacheSet][loc] = -1;
m_tag_index.erase(address);
}
}
@@ -337,28 +331,26 @@
return *m_cache[cacheSet][loc];
}
-AccessPermission
-CacheMemory::getPermission(const Address& address) const
+// looks an address up in the cache
+AbstractCacheEntry*
+CacheMemory::lookup_ptr(const Address& address)
{
assert(address == line_address(address));
- return lookup(address).m_Permission;
+ Index cacheSet = addressToCacheSet(address);
+ int loc = findTagInSet(cacheSet, address);
+ if(loc == -1) return NULL;
+ return m_cache[cacheSet][loc];
}
-void
-CacheMemory::changePermission(const Address& address,
- AccessPermission new_perm)
+// looks an address up in the cache
+const AbstractCacheEntry*
+CacheMemory::lookup_ptr(const Address& address) const
{
assert(address == line_address(address));
- lookup(address).m_Permission = new_perm;
Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address);
- if ((new_perm == AccessPermission_Invalid) ||
- (new_perm == AccessPermission_NotPresent) ||
- (new_perm == AccessPermission_Stale)) {
- DPRINTF(RubyCache, "Permission clearing lock for addr: %x\n", address);
- m_locked[cacheSet][loc] = -1;
- }
- assert(getPermission(address) == new_perm);
+ if(loc == -1) return NULL;
+ return m_cache[cacheSet][loc];
}
// Sets the most recently used bit for a cache block
@@ -460,10 +452,10 @@
CacheMemory::getMemoryValue(const Address& addr, char* value,
unsigned size_in_bytes)
{
- AbstractCacheEntry& entry = lookup(line_address(addr));
+ AbstractCacheEntry* entry = lookup_ptr(line_address(addr));
unsigned startByte = addr.getAddress() - line_address(addr).getAddress();
for (unsigned i = 0; i < size_in_bytes; ++i) {
- value[i] = entry.getDataBlk().getByte(i + startByte);
+ value[i] = entry->getDataBlk().getByte(i + startByte);
}
}
@@ -471,11 +463,11 @@
CacheMemory::setMemoryValue(const Address& addr, char* value,
unsigned size_in_bytes)
{
- AbstractCacheEntry& entry = lookup(line_address(addr));
+ AbstractCacheEntry* entry = lookup_ptr(line_address(addr));
unsigned startByte = addr.getAddress() - line_address(addr).getAddress();
assert(size_in_bytes > 0);
for (unsigned i = 0; i < size_in_bytes; ++i) {
- entry.getDataBlk().setByte(i + startByte, value[i]);
+ entry->getDataBlk().setByte(i + startByte, value[i]);
}
// entry = lookup(line_address(addr));
@@ -489,7 +481,7 @@
Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address);
assert(loc != -1);
- m_locked[cacheSet][loc] = context;
+ m_cache[cacheSet][loc]->m_locked = context;
}
void
@@ -500,7 +492,7 @@
Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address);
assert(loc != -1);
- m_locked[cacheSet][loc] = -1;
+ m_cache[cacheSet][loc]->m_locked = -1;
}
bool
@@ -511,7 +503,7 @@
int loc = findTagInSet(cacheSet, address);
assert(loc != -1);
DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n",
- address, m_locked[cacheSet][loc], context);
- return m_locked[cacheSet][loc] == context;
+ address, m_cache[cacheSet][loc]->m_locked, context);
+ return m_cache[cacheSet][loc]->m_locked == context;
}
diff --git a/src/mem/ruby/system/TBETable.hh b/src/mem/ruby/system/TBETable.hh
--- a/src/mem/ruby/system/TBETable.hh
+++ b/src/mem/ruby/system/TBETable.hh
@@ -61,8 +61,7 @@
return (m_number_of_TBEs - m_map.size()) >= n;
}
- ENTRY& lookup(const Address& address);
- const ENTRY& lookup(const Address& address) const;
+ ENTRY* lookup(const Address& address);
// Print cache contents
void print(std::ostream& out) const;
@@ -117,21 +116,13 @@
// looks an address up in the cache
template
-inline ENTRY&
+inline ENTRY*
TBETable::lookup(const Address& address)
{
- assert(isPresent(address));
- return m_map.find(address)->second;
+ if(m_map.find(address) != m_map.end()) return &(m_map.find(address)->second);
+ return NULL;
}
-// looks an address up in the cache
-template
-inline const ENTRY&
-TBETable::lookup(const Address& address) const
-{
- assert(isPresent(address));
- return m_map.find(address)->second;
-}
template
inline void
diff --git a/src/mem/slicc/ast/ActionDeclAST.py b/src/mem/slicc/ast/ActionDeclAST.py
--- a/src/mem/slicc/ast/ActionDeclAST.py
+++ b/src/mem/slicc/ast/ActionDeclAST.py
@@ -52,6 +52,25 @@
"addr", self.pairs)
self.symtab.newSymbol(var)
+ machine = self.symtab.state_machine
+ if machine.hasTBEType:
+ tbe_type = self.symtab.find("TBE", Type)
+ var = Var(self.symtab, "tbe", self.location, tbe_type,
+ "(*m_tbe_ptr)", self.pairs)
+ self.symtab.newSymbol(var)
+ var = Var(self.symtab, "tbe_ptr", self.location, tbe_type,
+ "m_tbe_ptr", self.pairs)
+ self.symtab.newSymbol(var)
+
+ if machine.hasEntryType:
+ entry_type = self.symtab.find("Entry", Type)
+ var = Var(self.symtab, "cache_entry", self.location, entry_type,
+ "(*m_cache_entry_ptr)", self.pairs)
+ self.symtab.newSymbol(var)
+ var = Var(self.symtab, "cache_entry_ptr", self.location, entry_type,
+ "m_cache_entry_ptr", self.pairs)
+ self.symtab.newSymbol(var)
+
# Do not allows returns in actions
code = self.slicc.codeFormatter()
self.statement_list.generate(code, None)
diff --git a/src/mem/slicc/ast/FormalParamAST.py b/src/mem/slicc/ast/FormalParamAST.py
--- a/src/mem/slicc/ast/FormalParamAST.py
+++ b/src/mem/slicc/ast/FormalParamAST.py
@@ -48,7 +48,18 @@
param = "param_%s" % self.ident
# Add to symbol table
- v = Var(self.symtab, self.ident, self.location, type, param,
- self.pairs)
- self.symtab.newSymbol(v)
+ if self.pointer or "Entry" == "%s" %(type) or "TBE" == "%s" %(type):
+ v = Var(self.symtab, self.ident, self.location, type,
+ "(*%s)" % param, self.pairs)
+ self.symtab.newSymbol(v)
+ v = Var(self.symtab, "%s_ptr" % self.ident, self.location, type,
+ "%s" % param, self.pairs)
+ self.symtab.newSymbol(v)
+ return type, "%s* %s" % (type.c_ident, param)
+
+ else:
+ v = Var(self.symtab, self.ident, self.location, type, param,
+ self.pairs)
+ self.symtab.newSymbol(v)
+
return type, "%s %s" % (type.c_ident, param)
diff --git a/src/mem/slicc/ast/FuncCallExprAST.py b/src/mem/slicc/ast/FuncCallExprAST.py
--- a/src/mem/slicc/ast/FuncCallExprAST.py
+++ b/src/mem/slicc/ast/FuncCallExprAST.py
@@ -115,8 +115,25 @@
code('''
{
Address addr = ${{cvec[1]}};
- TransitionResult result = doTransition(${{cvec[0]}}, ${machine}_getState(addr), addr);
+''')
+ if machine.hasTBEType and machine.hasEntryType:
+ code('''
+ TransitionResult result = doTransition(${{cvec[0]}}, m_tbe_ptr, m_cache_entry_ptr, addr);
+''')
+ elif machine.hasEntryType:
+ code('''
+ TransitionResult result = doTransition(${{cvec[0]}}, m_cache_entry_ptr, addr);
+''')
+ elif machine.hasTBEType:
+ code('''
+ TransitionResult result = doTransition(${{cvec[0]}}, m_tbe_ptr, addr);
+''')
+ else:
+ code('''
+ TransitionResult result = doTransition(${{cvec[0]}}, addr);
+''')
+ code('''
if (result == TransitionResult_Valid) {
counter++;
continue; // Check the first port again
@@ -175,6 +192,21 @@
elif self.proc_name == "continueProcessing":
code("counter++;")
code("continue; // Check the first port again")
+
+ elif self.proc_name == "set_cache_entry":
+ code("set_cache_entry(m_cache_entry_ptr, %s);" %(cvec[0]));
+ elif self.proc_name == "unset_cache_entry":
+ code("unset_cache_entry(m_cache_entry_ptr);");
+ elif self.proc_name == "is_valid_cache_entry":
+ code("is_valid_cache_entry(m_cache_entry_ptr)");
+
+ elif self.proc_name == "set_tbe":
+ code("set_tbe(m_tbe_ptr, %s);" %(cvec[0]));
+ elif self.proc_name == "unset_tbe":
+ code("unset_tbe(m_tbe_ptr);");
+ elif self.proc_name == "is_valid_tbe":
+ code("is_valid_tbe(m_tbe_ptr)");
+
else:
# Normal function
diff --git a/src/mem/slicc/ast/FuncDeclAST.py b/src/mem/slicc/ast/FuncDeclAST.py
--- a/src/mem/slicc/ast/FuncDeclAST.py
+++ b/src/mem/slicc/ast/FuncDeclAST.py
@@ -26,7 +26,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from slicc.ast.DeclAST import DeclAST
-from slicc.symbols import Func, Type
+from slicc.symbols import Func, Type, Var
class FuncDeclAST(DeclAST):
def __init__(self, slicc, return_type, ident, formals, pairs, statements):
@@ -54,6 +54,7 @@
types = []
params = []
void_type = self.symtab.find("void", Type)
+ machine = self.state_machine
# Generate definition code
self.symtab.pushFrame()
@@ -76,7 +77,6 @@
self.symtab.popFrame()
- machine = self.state_machine
func = Func(self.symtab, self.ident, self.location, return_type,
types, params, str(body), self.pairs, machine)
diff --git a/src/mem/slicc/ast/InPortDeclAST.py b/src/mem/slicc/ast/InPortDeclAST.py
--- a/src/mem/slicc/ast/InPortDeclAST.py
+++ b/src/mem/slicc/ast/InPortDeclAST.py
@@ -117,6 +117,26 @@
void_type, [], [], "", pairs, None)
symtab.newSymbol(func)
+ machine = symtab.state_machine
+ if machine is not None:
+ if machine.hasTBEType:
+ tbe_type = self.symtab.find("TBE", Type)
+ var = Var(self.symtab, "tbe", self.location, tbe_type,
+ "*m_tbe_ptr", self.pairs)
+ self.symtab.newSymbol(var)
+ var = Var(self.symtab, "tbe_ptr", self.location, tbe_type,
+ "m_tbe_ptr", self.pairs)
+ self.symtab.newSymbol(var)
+
+ if machine.hasEntryType:
+ entry_type = self.symtab.find("Entry", Type)
+ var = Var(self.symtab, "cache_entry", self.location, entry_type,
+ "*m_cache_entry_ptr", self.pairs)
+ self.symtab.newSymbol(var)
+ var = Var(self.symtab, "cache_entry_ptr", self.location, entry_type,
+ "m_cache_entry_ptr", self.pairs)
+ self.symtab.newSymbol(var)
+
if self.statements is not None:
rcode = self.slicc.codeFormatter()
rcode.indent()
diff --git a/src/mem/slicc/ast/IsValidPtrExprAST.py b/src/mem/slicc/ast/IsValidPtrExprAST.py
--- /dev/null
+++ b/src/mem/slicc/ast/IsValidPtrExprAST.py
@@ -0,0 +1,19 @@
+from slicc.ast.ExprAST import ExprAST
+from slicc.symbols import Type
+
+class IsValidPtrExprAST(ExprAST):
+ def __init__(self, slicc, variable):
+ super(IsValidPtrExprAST, self).__init__(slicc)
+ self.variable = variable
+
+ def __repr__(self):
+ return "[IsValidPtrExprAST: %r]" % self.variable
+
+ def generate(self, code):
+ # Make sure the variable is valid
+ fix = code.nofix()
+ self.variable.generate(code);
+ code(" != NULL")
+ code.fix(fix)
+ type = self.symtab.find("bool", Type)
+ return type
diff --git a/src/mem/slicc/ast/MethodCallExprAST.py b/src/mem/slicc/ast/MethodCallExprAST.py
--- a/src/mem/slicc/ast/MethodCallExprAST.py
+++ b/src/mem/slicc/ast/MethodCallExprAST.py
@@ -97,48 +97,67 @@
prefix = ""
implements_interface = False
- if methodId not in obj_type.methods:
+
+ if methodId in obj_type.methods:
+ return_type = obj_type.methods[methodId].return_type
+
+ else:
#
- # The initial method check has failed, but before generating an
- # error we must check whether any of the paramTypes implement
- # an interface. If so, we must check if the method ids using
- # the inherited types exist.
- #
- # This code is a temporary fix and only checks for the methodId
- # where all paramTypes are converted to their inherited type. The
- # right way to do this is to replace slicc's simple string
- # comparison for determining the correct overloaded method, with a
- # more robust param by param check.
- #
- implemented_paramTypes = []
- for paramType in paramTypes:
- implemented_paramType = paramType
- if paramType.isInterface:
- implements_interface = True
- implemented_paramType.abstract_ident = paramType["interface"]
+ # Check whether the method is implemented by the super class
+ if "interface" in obj_type:
+ interface_type = self.symtab.find(obj_type["interface"]);
+
+ if methodId in interface_type.methods:
+ return_type = interface_type.methods[methodId].return_type
+ obj_type = interface_type
+
else:
- implemented_paramType.abstract_ident = paramType.c_ident
-
- implemented_paramTypes.append(implemented_paramType)
+ self.error("Invalid method call: " \
+ "Type '%s' does not have a method %s, '%s'",
+ obj_type, self.proc_name, methodId)
- if implements_interface:
- implementedMethodId = obj_type.methodIdAbstract(self.proc_name,
- implemented_paramTypes)
else:
- implementedMethodId = ""
-
- if implementedMethodId not in obj_type.methods:
- self.error("Invalid method call: " \
- "Type '%s' does not have a method '%s' nor '%s'",
- obj_type, methodId, implementedMethodId)
- else:
- #
- # Replace the methodId with the implementedMethodId found in
- # the method list.
- #
- methodId = implementedMethodId
-
- return_type = obj_type.methods[methodId].return_type
+ #
+ # The initial method check has failed, but before generating an
+ # error we must check whether any of the paramTypes implement
+ # an interface. If so, we must check if the method ids using
+ # the inherited types exist.
+ #
+ # This code is a temporary fix and only checks for the methodId
+ # where all paramTypes are converted to their inherited type. The
+ # right way to do this is to replace slicc's simple string
+ # comparison for determining the correct overloaded method, with a
+ # more robust param by param check.
+ #
+ implemented_paramTypes = []
+ for paramType in paramTypes:
+ implemented_paramType = paramType
+ if paramType.isInterface:
+ implements_interface = True
+ implemented_paramType.abstract_ident = paramType["interface"]
+ else:
+ implemented_paramType.abstract_ident = paramType.c_ident
+
+ implemented_paramTypes.append(implemented_paramType)
+
+ if implements_interface:
+ implementedMethodId = obj_type.methodIdAbstract(self.proc_name,
+ implemented_paramTypes)
+ else:
+ implementedMethodId = ""
+
+ if implementedMethodId not in obj_type.methods:
+ self.error("Invalid method call: " \
+ "Type '%s' does not have a method %s, '%s' nor '%s'",
+ obj_type, self.proc_name, methodId, implementedMethodId)
+ else:
+ #
+ # Replace the methodId with the implementedMethodId found in
+ # the method list.
+ #
+ methodId = implementedMethodId
+ return_type = obj_type.methods[methodId].return_type
+
if return_type.isInterface:
prefix = "static_cast<%s &>" % return_type.c_ident
prefix = "%s((%s)." % (prefix, code)
diff --git a/src/mem/slicc/ast/StaticCastAST.py b/src/mem/slicc/ast/StaticCastAST.py
--- a/src/mem/slicc/ast/StaticCastAST.py
+++ b/src/mem/slicc/ast/StaticCastAST.py
@@ -27,18 +27,22 @@
from slicc.ast.ExprAST import ExprAST
class StaticCastAST(ExprAST):
- def __init__(self, slicc, type_ast, expr_ast):
+ def __init__(self, slicc, type_ast, type_modifier, expr_ast):
super(StaticCastAST, self).__init__(slicc)
self.type_ast = type_ast
self.expr_ast = expr_ast
+ self.type_modifier = type_modifier
def __repr__(self):
return "[StaticCastAST: %r]" % self.expr_ast
def generate(self, code):
actual_type, ecode = self.expr_ast.inline(True)
- code('static_cast<${{self.type_ast.type.c_ident}} &>($ecode)')
+ if self.type_modifier:
+ code('static_cast<${{self.type_ast.type.c_ident}} *>($ecode)')
+ else:
+ code('static_cast<${{self.type_ast.type.c_ident}} &>($ecode)')
if not "interface" in self.type_ast.type:
self.expr_ast.error("static cast only premitted for those types " \
diff --git a/src/mem/slicc/ast/TypeDeclAST.py b/src/mem/slicc/ast/TypeDeclAST.py
--- a/src/mem/slicc/ast/TypeDeclAST.py
+++ b/src/mem/slicc/ast/TypeDeclAST.py
@@ -50,10 +50,15 @@
def generate(self):
ident = str(self.type_ast)
+ machine = self.symtab.state_machine
# Make the new type
new_type = Type(self.symtab, ident, self.location, self.pairs,
self.state_machine)
+
+ if machine:
+ machine.addType(new_type)
+
self.symtab.newSymbol(new_type)
# Add all of the fields of the type to it
diff --git a/src/mem/slicc/ast/__init__.py b/src/mem/slicc/ast/__init__.py
--- a/src/mem/slicc/ast/__init__.py
+++ b/src/mem/slicc/ast/__init__.py
@@ -46,6 +46,7 @@
from slicc.ast.IfStatementAST import *
from slicc.ast.InPortDeclAST import *
from slicc.ast.InfixOperatorExprAST import *
+from slicc.ast.IsValidPtrExprAST import *
from slicc.ast.LiteralExprAST import *
from slicc.ast.MachineAST import *
from slicc.ast.MemberExprAST import *
diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py
--- a/src/mem/slicc/parser.py
+++ b/src/mem/slicc/parser.py
@@ -165,6 +165,7 @@
'check_stop_slots' : 'CHECK_STOP_SLOTS',
'static_cast' : 'STATIC_CAST',
'if' : 'IF',
+ 'is_valid_ptr' : 'IS_VALID_PTR',
'else' : 'ELSE',
'return' : 'RETURN',
'THIS' : 'THIS',
@@ -576,7 +577,11 @@
def p_statement__static_cast(self, p):
"aexpr : STATIC_CAST '(' type ',' expr ')'"
- p[0] = ast.StaticCastAST(self, p[3], p[5])
+ p[0] = ast.StaticCastAST(self, p[3], False, p[5])
+
+ def p_statement__static_cast_ptr(self, p):
+ "aexpr : STATIC_CAST '(' type ',' STRING ',' expr ')'"
+ p[0] = ast.StaticCastAST(self, p[3], True, p[7])
def p_statement__return(self, p):
"statement : RETURN expr SEMI"
@@ -687,6 +692,10 @@
"aexpr : '(' expr ')'"
p[0] = p[2]
+ def p_expr__is_valid_ptr(self, p):
+ "aexpr : IS_VALID_PTR '(' var ')'"
+ p[0] = ast.IsValidPtrExprAST(self, p[3])
+
def p_literal__string(self, p):
"literal : STRING"
p[0] = ast.LiteralExprAST(self, p[1], "std::string")
diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py
--- a/src/mem/slicc/symbols/StateMachine.py
+++ b/src/mem/slicc/symbols/StateMachine.py
@@ -46,10 +46,14 @@
super(StateMachine, self).__init__(symtab, ident, location, pairs)
self.table = None
self.config_parameters = config_parameters
+ self.hasCacheMemory = False
+
for param in config_parameters:
if param.pointer:
var = Var(symtab, param.name, location, param.type_ast.type,
"(*m_%s_ptr)" % param.name, {}, self)
+ if "CacheMemory" == "%s" %(param.type_ast.type):
+ self.hasCacheMemory = True
else:
var = Var(symtab, param.name, location, param.type_ast.type,
"m_%s" % param.name, {}, self)
@@ -62,6 +66,8 @@
self.in_ports = []
self.functions = []
self.objects = []
+ self.hasTBEType = False
+ self.hasEntryType = False
self.message_buffer_names = []
@@ -107,6 +113,14 @@
def addObject(self, obj):
self.objects.append(obj)
+ def addType(self, type):
+ type_ident = '%s' % type.c_ident
+
+ if type_ident == "%s_TBE" %self.ident:
+ self.hasTBEType = True
+ elif type_ident == "%s_Entry" %self.ident:
+ self.hasEntryType = True
+
# Needs to be called before accessing the table
def buildTable(self):
assert self.table is None
@@ -264,12 +278,35 @@
int m_number_of_TBEs;
TransitionResult doTransition(${ident}_Event event,
- ${ident}_State state,
+''')
+
+ if self.hasTBEType:
+ code('''
+ ${ident}_TBE* m_tbe_ptr,
+''')
+ if self.hasEntryType:
+ code('''
+ ${ident}_Entry* m_cache_entry_ptr,
+''')
+
+ code('''
const Address& addr);
TransitionResult doTransitionWorker(${ident}_Event event,
${ident}_State state,
${ident}_State& next_state,
+''')
+
+ if self.hasTBEType:
+ code('''
+ ${ident}_TBE*& m_tbe_ptr,
+''')
+ if self.hasEntryType:
+ code('''
+ ${ident}_Entry*& m_cache_entry_ptr,
+''')
+
+ code('''
const Address& addr);
std::string m_name;
@@ -299,13 +336,47 @@
if proto:
code('$proto')
+ if self.hasCacheMemory:
+ code('''
+${ident}_Entry* getCacheEntry(const Address& addr);
+''')
+
+ if self.hasEntryType:
+ code('''
+
+// Set and Reset for cache_entry variable
+void set_cache_entry(${ident}_Entry*& m_cache_entry_ptr, ${ident}_Entry* m_new_cache_entry);
+void unset_cache_entry(${ident}_Entry*& m_cache_entry_ptr);
+''')
+
+ if self.hasTBEType:
+ code('''
+
+// Set and Reset for tbe variable
+void set_tbe(${ident}_TBE*& m_tbe_ptr, ${ident}_TBE* m_new_tbe);
+void unset_tbe(${ident}_TBE*& m_tbe_ptr);
+''')
+
code('''
// Actions
''')
- for action in self.actions.itervalues():
- code('/** \\brief ${{action.desc}} */')
- code('void ${{action.ident}}(const Address& addr);')
+ if self.hasTBEType and self.hasEntryType:
+ for action in self.actions.itervalues():
+ code('/** \\brief ${{action.desc}} */')
+ code('void ${{action.ident}}(${ident}_TBE*& m_tbe_ptr, ${ident}_Entry*& m_cache_entry_ptr, const Address& addr);')
+ elif self.hasTBEType:
+ for action in self.actions.itervalues():
+ code('/** \\brief ${{action.desc}} */')
+ code('void ${{action.ident}}(${ident}_TBE*& m_tbe_ptr, const Address& addr);')
+ elif self.hasEntryType:
+ for action in self.actions.itervalues():
+ code('/** \\brief ${{action.desc}} */')
+ code('void ${{action.ident}}(${ident}_Entry*& m_cache_entry_ptr, const Address& addr);')
+ else:
+ for action in self.actions.itervalues():
+ code('/** \\brief ${{action.desc}} */')
+ code('void ${{action.ident}}(const Address& addr);')
# the controller internal variables
code('''
@@ -730,15 +801,119 @@
code('''
m_profiler.clearStats();
}
+''')
+
+ if self.hasCacheMemory:
+ code('''
+
+${ident}_Entry*
+$c_ident::getCacheEntry(const Address& address)
+{
+ ${ident}_Entry* m_cache_entry_ptr = NULL;
+''')
+ for param in self.config_parameters:
+ if "CacheMemory" == "%s" %(param.type_ast.type):
+ code('''
+
+ m_cache_entry_ptr = (${ident}_Entry*)(*m_${{param.name}}_ptr).lookup_ptr(address);
+ if (m_cache_entry_ptr != NULL) return m_cache_entry_ptr;
+''')
+ code('''
+
+ return NULL;
+}
+''')
+
+ if self.hasEntryType:
+ code('''
+
+// Set and Reset for cache_entry variable
+void
+$c_ident::set_cache_entry(${ident}_Entry*& m_cache_entry_ptr, ${ident}_Entry* m_new_cache_entry)
+{
+ m_cache_entry_ptr = m_new_cache_entry;
+}
+
+void
+$c_ident::unset_cache_entry(${ident}_Entry*& m_cache_entry_ptr)
+{
+ m_cache_entry_ptr = NULL;
+}
+''')
+
+ if self.hasTBEType:
+ code('''
+
+// Set and Reset for tbe variable
+void
+$c_ident::set_tbe(${ident}_TBE*& m_tbe_ptr, ${ident}_TBE* m_new_tbe)
+{
+ m_tbe_ptr = m_new_tbe;
+}
+
+void
+$c_ident::unset_tbe(${ident}_TBE*& m_tbe_ptr)
+{
+ m_tbe_ptr = NULL;
+}
+''')
+
+ code('''
// Actions
''')
- for action in self.actions.itervalues():
- if "c_code" not in action:
- continue
+ if self.hasTBEType and self.hasEntryType:
+ for action in self.actions.itervalues():
+ if "c_code" not in action:
+ continue
- code('''
+ code('''
+/** \\brief ${{action.desc}} */
+void
+$c_ident::${{action.ident}}(${ident}_TBE*& m_tbe_ptr, ${ident}_Entry*& m_cache_entry_ptr, const Address& addr)
+{
+ DPRINTF(RubyGenerated, "executing\\n");
+ ${{action["c_code"]}}
+}
+
+''')
+ elif self.hasTBEType:
+ for action in self.actions.itervalues():
+ if "c_code" not in action:
+ continue
+
+ code('''
+/** \\brief ${{action.desc}} */
+void
+$c_ident::${{action.ident}}(${ident}_TBE*& m_tbe_ptr, const Address& addr)
+{
+ DPRINTF(RubyGenerated, "executing\\n");
+ ${{action["c_code"]}}
+}
+
+''')
+ elif self.hasEntryType:
+ for action in self.actions.itervalues():
+ if "c_code" not in action:
+ continue
+
+ code('''
+/** \\brief ${{action.desc}} */
+void
+$c_ident::${{action.ident}}(${ident}_Entry*& m_cache_entry_ptr, const Address& addr)
+{
+ DPRINTF(RubyGenerated, "executing\\n");
+ ${{action["c_code"]}}
+}
+
+''')
+ else:
+ for action in self.actions.itervalues():
+ if "c_code" not in action:
+ continue
+
+ code('''
/** \\brief ${{action.desc}} */
void
$c_ident::${{action.ident}}(const Address& addr)
@@ -791,6 +966,16 @@
}
''')
+ if self.hasTBEType:
+ code('''
+ ${ident}_TBE* m_tbe_ptr = NULL;
+''')
+
+ if self.hasEntryType:
+ code('''
+ ${ident}_Entry* m_cache_entry_ptr = NULL;
+''')
+
code.indent()
code.indent()
@@ -844,9 +1029,37 @@
TransitionResult
${ident}_Controller::doTransition(${ident}_Event event,
- ${ident}_State state,
+''')
+ if self.hasTBEType:
+ code('''
+ ${ident}_TBE* m_tbe_ptr,
+''')
+ if self.hasEntryType:
+ code('''
+ ${ident}_Entry* m_cache_entry_ptr,
+''')
+
+ code('''
const Address &addr)
{
+''')
+ if self.hasTBEType and self.hasEntryType:
+ code('''
+ ${ident}_State state = ${ident}_getState(m_tbe_ptr, m_cache_entry_ptr, addr);
+''')
+ elif self.hasTBEType:
+ code('''
+ ${ident}_State state = ${ident}_getState(m_tbe_ptr, addr);
+''')
+ elif self.hasEntryType:
+ code('''
+ ${ident}_State state = ${ident}_getState(m_cache_entry_ptr, addr);
+''')
+ else:
+ code('''
+ ${ident}_State state = ${ident}_getState(addr);
+''')
+ code('''
${ident}_State next_state = state;
DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n",
@@ -857,7 +1070,24 @@
addr);
TransitionResult result =
+''')
+ if self.hasTBEType and self.hasEntryType:
+ code('''
+ doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);
+''')
+ elif self.hasEntryType:
+ code('''
+ doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);
+''')
+ elif self.hasTBEType:
+ code('''
+ doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);
+''')
+ else:
+ code('''
doTransitionWorker(event, state, next_state, addr);
+''')
+ code('''
if (result == TransitionResult_Valid) {
DPRINTF(RubyGenerated, "next_state: %s\\n",
@@ -872,8 +1102,25 @@
GET_TRANSITION_COMMENT());
}
CLEAR_TRANSITION_COMMENT();
+''')
+ if self.hasTBEType and self.hasEntryType:
+ code('''
+ ${ident}_setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);
+''')
+ elif self.hasTBEType:
+ code('''
+ ${ident}_setState(m_tbe_ptr, addr, next_state);
+''')
+ elif self.hasEntryType:
+ code('''
+ ${ident}_setState(m_cache_ptr, addr, next_state);
+''')
+ else:
+ code('''
${ident}_setState(addr, next_state);
+''')
+ code('''
} else if (result == TransitionResult_ResourceStall) {
if (Debug::getProtocolTrace()) {
g_system_ptr->getProfiler()->profileTransition("${ident}",
@@ -902,6 +1149,18 @@
${ident}_Controller::doTransitionWorker(${ident}_Event event,
${ident}_State state,
${ident}_State& next_state,
+''')
+
+ if self.hasTBEType:
+ code('''
+ ${ident}_TBE*& m_tbe_ptr,
+''')
+ if self.hasEntryType:
+ code('''
+ ${ident}_Entry*& m_cache_entry_ptr,
+''')
+
+ code('''
const Address& addr)
{
switch(HASH_FUN(state, event)) {
@@ -950,8 +1209,18 @@
if stall:
case('return TransitionResult_ProtocolStall;')
else:
- for action in actions:
- case('${{action.ident}}(addr);')
+ if self.hasTBEType and self.hasEntryType:
+ for action in actions:
+ case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);')
+ elif self.hasTBEType:
+ for action in actions:
+ case('${{action.ident}}(m_tbe_ptr, addr);')
+ elif self.hasEntryType:
+ for action in actions:
+ case('${{action.ident}}(m_cache_entry_ptr, addr);')
+ else:
+ for action in actions:
+ case('${{action.ident}}(addr);')
case('return TransitionResult_Valid;')
case = str(case)