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)