From: Tiago Mück Date: Fri, 28 Feb 2020 21:32:00 +0000 (-0600) Subject: mem-ruby: able to define resource stalls handlers X-Git-Tag: develop-gem5-snapshot~380 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4e2216d68b14e51351c6c87708820fdeac1f1608;p=gem5.git mem-ruby: able to define resource stalls handlers Input ports can specify a custom handler that is called on resource stalls. The handler should return 'true' to indicate the stall was handled and new messages from that queue can be processed on that cycle. When it returns 'false' or no handler is defined, a resource stall is generated. Handlers are defined using the 'rsc_stall_handler' (for resource stalls) and the 'prot_stall_handler' (for protocol stalls) parameters. For example: in_port(mandatory_in, RubyRequest, mandatoryQueue, rsc_stall_handler=mandatory_in_stall_handler) { ... } bool mandatory_in_stall_handler() { // Do something here to handle the stall ! return true; // or return false if we don't want to do anything } Note: this patch required a change to the generate() functions interface in the SLICC compiler, so we could propagate a reference to the in_port to the appropriate generate() functions. The updated interface allows passing and forwarding of keyword arguments. Change-Id: I3481d130d5eb411e6760a54d098d3da5de511c86 Signed-off-by: Tiago Mück Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31265 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- diff --git a/src/mem/slicc/ast/AssignStatementAST.py b/src/mem/slicc/ast/AssignStatementAST.py index b95979354..d3e449d4e 100644 --- a/src/mem/slicc/ast/AssignStatementAST.py +++ b/src/mem/slicc/ast/AssignStatementAST.py @@ -36,7 +36,7 @@ class AssignStatementAST(StatementAST): def __repr__(self): return "[AssignStatementAST: %r := %r]" % (self.lvalue, self.rvalue) - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): lcode = self.slicc.codeFormatter() rcode = self.slicc.codeFormatter() diff --git a/src/mem/slicc/ast/CheckAllocateStatementAST.py b/src/mem/slicc/ast/CheckAllocateStatementAST.py index b96153b0a..425e8053d 100644 --- a/src/mem/slicc/ast/CheckAllocateStatementAST.py +++ b/src/mem/slicc/ast/CheckAllocateStatementAST.py @@ -35,7 +35,7 @@ class CheckAllocateStatementAST(StatementAST): def __repr__(self): return "[CheckAllocateStatementAst: %r]" % self.variable - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): # FIXME - check the type of the variable # Make sure the variable is valid diff --git a/src/mem/slicc/ast/CheckNextCycleAST.py b/src/mem/slicc/ast/CheckNextCycleAST.py index 5ca869d57..f3797755e 100644 --- a/src/mem/slicc/ast/CheckNextCycleAST.py +++ b/src/mem/slicc/ast/CheckNextCycleAST.py @@ -35,6 +35,6 @@ class CheckNextCycleAST(StatementAST): def __repr__(self): return "[CheckNextCycleAST]" - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): code("scheduleEvent(Cycles(1));") return "CheckNextCycle" diff --git a/src/mem/slicc/ast/CheckProbeStatementAST.py b/src/mem/slicc/ast/CheckProbeStatementAST.py index 53454635a..0d84bbce4 100644 --- a/src/mem/slicc/ast/CheckProbeStatementAST.py +++ b/src/mem/slicc/ast/CheckProbeStatementAST.py @@ -37,7 +37,7 @@ class CheckProbeStatementAST(StatementAST): def __repr__(self): return "[CheckProbeStatementAst: %r]" % self.in_port - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): self.in_port.assertType("InPort") self.address.assertType("Addr") diff --git a/src/mem/slicc/ast/DeferEnqueueingStatementAST.py b/src/mem/slicc/ast/DeferEnqueueingStatementAST.py index 40b9a4c52..970483627 100644 --- a/src/mem/slicc/ast/DeferEnqueueingStatementAST.py +++ b/src/mem/slicc/ast/DeferEnqueueingStatementAST.py @@ -48,7 +48,7 @@ class DeferEnqueueingStatementAST(StatementAST): return "[DeferEnqueueingStatementAst: %s %s %s]" % \ (self.queue_name, self.type_ast.ident, self.statements) - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): code("{") code.indent() self.symtab.pushFrame() diff --git a/src/mem/slicc/ast/EnqueueStatementAST.py b/src/mem/slicc/ast/EnqueueStatementAST.py index 556643e4e..a8c157e42 100644 --- a/src/mem/slicc/ast/EnqueueStatementAST.py +++ b/src/mem/slicc/ast/EnqueueStatementAST.py @@ -42,7 +42,7 @@ class EnqueueStatementAST(StatementAST): return "[EnqueueStatementAst: %s %s %s]" % \ (self.queue_name, self.type_ast.ident, self.statements) - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): code("{") code.indent() self.symtab.pushFrame() diff --git a/src/mem/slicc/ast/EnumExprAST.py b/src/mem/slicc/ast/EnumExprAST.py index 9cb76a8a1..27da269e9 100644 --- a/src/mem/slicc/ast/EnumExprAST.py +++ b/src/mem/slicc/ast/EnumExprAST.py @@ -40,7 +40,7 @@ class EnumExprAST(ExprAST): def __repr__(self): return "[EnumExpr: %s:%s]" % (self.type_ast, self.value) - def generate(self, code): + def generate(self, code, **kwargs): fix = code.nofix() code('${{self.type_ast.type.c_ident}}_${{self.value}}') code.fix(fix) diff --git a/src/mem/slicc/ast/ExprAST.py b/src/mem/slicc/ast/ExprAST.py index 393101112..75554b2d3 100644 --- a/src/mem/slicc/ast/ExprAST.py +++ b/src/mem/slicc/ast/ExprAST.py @@ -34,9 +34,9 @@ class ExprAST(AST): # The default is no resources pass - def inline(self, get_type=False): + def inline(self, get_type=False, **kwargs): code = self.slicc.codeFormatter(fix_newlines=False) - return_type = self.generate(code) + return_type = self.generate(code, **kwargs) if get_type: return return_type, code else: diff --git a/src/mem/slicc/ast/ExprStatementAST.py b/src/mem/slicc/ast/ExprStatementAST.py index 6c77522c7..7189df040 100644 --- a/src/mem/slicc/ast/ExprStatementAST.py +++ b/src/mem/slicc/ast/ExprStatementAST.py @@ -38,8 +38,8 @@ class ExprStatementAST(StatementAST): def __repr__(self): return "[ExprStatementAST: %s]" % (self.expr) - def generate(self, code, return_type): - actual_type,rcode = self.expr.inline(True) + def generate(self, code, return_type, **kwargs): + actual_type,rcode = self.expr.inline(True, **kwargs) code("$rcode;") # The return type must be void, except for local var decls diff --git a/src/mem/slicc/ast/FuncCallExprAST.py b/src/mem/slicc/ast/FuncCallExprAST.py index b3cc9f1ec..d93ee04e9 100644 --- a/src/mem/slicc/ast/FuncCallExprAST.py +++ b/src/mem/slicc/ast/FuncCallExprAST.py @@ -1,3 +1,15 @@ +# Copyright (c) 2020 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 1999-2008 Mark D. Hill and David A. Wood # Copyright (c) 2009 The Hewlett-Packard Development Company # Copyright (c) 2013 Advanced Micro Devices, Inc. @@ -38,7 +50,9 @@ class FuncCallExprAST(ExprAST): def __repr__(self): return "[FuncCallExpr: %s %s]" % (self.proc_name, self.exprs) - def generate(self, code): + # When calling generate for statements in a in_port, the reference to + # the port must be provided as the in_port kwarg (see InPortDeclAST) + def generate(self, code, **kwargs): machine = self.state_machine if self.proc_name == "DPRINTF": @@ -148,18 +162,53 @@ class FuncCallExprAST(ExprAST): TransitionResult result = doTransition(${{cvec[0]}}, ${{cvec[1]}}); ''') + assert('in_port' in kwargs) + in_port = kwargs['in_port'] + code(''' if (result == TransitionResult_Valid) { counter++; continue; // Check the first port again - } - - if (result == TransitionResult_ResourceStall || - result == TransitionResult_ProtocolStall) { + } else if (result == TransitionResult_ResourceStall) { +''') + if 'rsc_stall_handler' in in_port.pairs: + stall_func_name = in_port.pairs['rsc_stall_handler'] + code(''' + if (${{stall_func_name}}()) { + counter++; + continue; // Check the first port again + } else { + scheduleEvent(Cycles(1)); + // Cannot do anything with this transition, go check next doable transition (mostly likely of next port) + } +''') + else: + code(''' scheduleEvent(Cycles(1)); - // Cannot do anything with this transition, go check next doable transition (mostly likely of next port) +''') + code(''' + } else if (result == TransitionResult_ProtocolStall) { +''') + if 'prot_stall_handler' in in_port.pairs: + stall_func_name = in_port.pairs['prot_stall_handler'] + code(''' + if (${{stall_func_name}}()) { + counter++; + continue; // Check the first port again + } else { + scheduleEvent(Cycles(1)); + // Cannot do anything with this transition, go check next doable transition (mostly likely of next port) + } +''') + else: + code(''' + scheduleEvent(Cycles(1)); + // Cannot do anything with this transition, go check next doable transition (mostly likely of next port) +''') + code(''' } + } ''') elif self.proc_name == "error": diff --git a/src/mem/slicc/ast/FuncDeclAST.py b/src/mem/slicc/ast/FuncDeclAST.py index 47ae7076e..675c40813 100644 --- a/src/mem/slicc/ast/FuncDeclAST.py +++ b/src/mem/slicc/ast/FuncDeclAST.py @@ -43,7 +43,7 @@ class FuncDeclAST(DeclAST): def files(self, parent=None): return set() - def generate(self, parent = None): + def generate(self, parent = None, **kwargs): types = [] params = [] void_type = self.symtab.find("void", Type) diff --git a/src/mem/slicc/ast/IfStatementAST.py b/src/mem/slicc/ast/IfStatementAST.py index 3ad3d182d..2ddd7c052 100644 --- a/src/mem/slicc/ast/IfStatementAST.py +++ b/src/mem/slicc/ast/IfStatementAST.py @@ -42,7 +42,7 @@ class IfStatementAST(StatementAST): def __repr__(self): return "[IfStatement: %r%r%r]" % (self.cond, self.then, self.else_) - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): cond_code = self.slicc.codeFormatter() cond_type = self.cond.generate(cond_code) @@ -56,7 +56,7 @@ class IfStatementAST(StatementAST): # Then part code.indent() self.symtab.pushFrame() - self.then.generate(code, return_type) + self.then.generate(code, return_type, **kwargs) self.symtab.popFrame() code.dedent() # Else part @@ -64,7 +64,7 @@ class IfStatementAST(StatementAST): code('} else {') code.indent() self.symtab.pushFrame() - self.else_.generate(code, return_type) + self.else_.generate(code, return_type, **kwargs) self.symtab.popFrame() code.dedent() code('}') # End scope diff --git a/src/mem/slicc/ast/InPortDeclAST.py b/src/mem/slicc/ast/InPortDeclAST.py index e0aa25236..8e80b6ad1 100644 --- a/src/mem/slicc/ast/InPortDeclAST.py +++ b/src/mem/slicc/ast/InPortDeclAST.py @@ -1,3 +1,15 @@ +# Copyright (c) 2020 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 1999-2008 Mark D. Hill and David A. Wood # Copyright (c) 2009 The Hewlett-Packard Development Company # All rights reserved. @@ -118,7 +130,7 @@ class InPortDeclAST(DeclAST): rcode = self.slicc.codeFormatter() rcode.indent() rcode.indent() - self.statements.generate(rcode, None) + self.statements.generate(rcode, None, in_port=in_port) in_port["c_code_in_port"] = str(rcode) symtab.popFrame() diff --git a/src/mem/slicc/ast/IsValidPtrExprAST.py b/src/mem/slicc/ast/IsValidPtrExprAST.py index e68e084c0..a7d89a9b8 100644 --- a/src/mem/slicc/ast/IsValidPtrExprAST.py +++ b/src/mem/slicc/ast/IsValidPtrExprAST.py @@ -38,7 +38,7 @@ class IsValidPtrExprAST(ExprAST): def __repr__(self): return "[IsValidPtrExprAST: %r]" % self.variable - def generate(self, code): + def generate(self, code, **kwargs): # Make sure the variable is valid fix = code.nofix() code("(") diff --git a/src/mem/slicc/ast/LiteralExprAST.py b/src/mem/slicc/ast/LiteralExprAST.py index 6d259c17f..59756b173 100644 --- a/src/mem/slicc/ast/LiteralExprAST.py +++ b/src/mem/slicc/ast/LiteralExprAST.py @@ -37,7 +37,7 @@ class LiteralExprAST(ExprAST): def __repr__(self): return "[Literal: %s]" % self.literal - def generate(self, code): + def generate(self, code, **kwargs): fix = code.nofix() if self.type == "std::string": code('("${{self.literal}}")') diff --git a/src/mem/slicc/ast/LocalVariableAST.py b/src/mem/slicc/ast/LocalVariableAST.py index c1a5fdbd9..da75477c8 100644 --- a/src/mem/slicc/ast/LocalVariableAST.py +++ b/src/mem/slicc/ast/LocalVariableAST.py @@ -52,7 +52,7 @@ class LocalVariableAST(StatementAST): else: return code - def generate(self, code): + def generate(self, code, **kwargs): type = self.type_ast.type; ident = "%s" % self.ident; diff --git a/src/mem/slicc/ast/MethodCallExprAST.py b/src/mem/slicc/ast/MethodCallExprAST.py index 102ab6e4c..9908fc815 100644 --- a/src/mem/slicc/ast/MethodCallExprAST.py +++ b/src/mem/slicc/ast/MethodCallExprAST.py @@ -33,7 +33,7 @@ class MethodCallExprAST(ExprAST): self.proc_name = proc_name self.expr_ast_vec = expr_ast_vec - def generate(self, code): + def generate(self, code, **kwargs): tmp = self.slicc.codeFormatter() paramTypes = [] for expr_ast in self.expr_ast_vec: diff --git a/src/mem/slicc/ast/NewExprAST.py b/src/mem/slicc/ast/NewExprAST.py index a42350768..2f33bfac3 100644 --- a/src/mem/slicc/ast/NewExprAST.py +++ b/src/mem/slicc/ast/NewExprAST.py @@ -39,7 +39,7 @@ class NewExprAST(ExprAST): def name(self): return str(self.type_ast) - def generate(self, code): + def generate(self, code, **kwargs): type = self.type_ast.type fix = code.nofix() code("new ${{type.c_ident}}") diff --git a/src/mem/slicc/ast/ObjDeclAST.py b/src/mem/slicc/ast/ObjDeclAST.py index efc7ef928..523a491ab 100644 --- a/src/mem/slicc/ast/ObjDeclAST.py +++ b/src/mem/slicc/ast/ObjDeclAST.py @@ -40,7 +40,7 @@ class ObjDeclAST(DeclAST): def __repr__(self): return "[ObjDecl: %r]" % self.ident - def generate(self, parent = None): + def generate(self, parent = None, **kwargs): if "network" in self and not ("virtual_network" in self or "physical_network" in self) : self.error("Network queues require a 'virtual_network' attribute") diff --git a/src/mem/slicc/ast/OodAST.py b/src/mem/slicc/ast/OodAST.py index 0f4cf141c..173a1566e 100644 --- a/src/mem/slicc/ast/OodAST.py +++ b/src/mem/slicc/ast/OodAST.py @@ -35,6 +35,6 @@ class OodAST(ExprAST): def __repr__(self): return "[Ood:]" - def generate(self, code): + def generate(self, code, **kwargs): code += "NULL" return "OOD" diff --git a/src/mem/slicc/ast/OperatorExprAST.py b/src/mem/slicc/ast/OperatorExprAST.py index cab13692c..5c5ea834f 100644 --- a/src/mem/slicc/ast/OperatorExprAST.py +++ b/src/mem/slicc/ast/OperatorExprAST.py @@ -39,7 +39,7 @@ class InfixOperatorExprAST(ExprAST): def __repr__(self): return "[InfixExpr: %r %s %r]" % (self.left, self.op, self.right) - def generate(self, code): + def generate(self, code, **kwargs): lcode = self.slicc.codeFormatter() rcode = self.slicc.codeFormatter() @@ -104,7 +104,7 @@ class PrefixOperatorExprAST(ExprAST): def __repr__(self): return "[PrefixExpr: %s %r]" % (self.op, self.operand) - def generate(self, code): + def generate(self, code, **kwargs): opcode = self.slicc.codeFormatter() optype = self.operand.generate(opcode) diff --git a/src/mem/slicc/ast/PeekStatementAST.py b/src/mem/slicc/ast/PeekStatementAST.py index 20e514010..2ad182ff4 100644 --- a/src/mem/slicc/ast/PeekStatementAST.py +++ b/src/mem/slicc/ast/PeekStatementAST.py @@ -42,7 +42,7 @@ class PeekStatementAST(StatementAST): return "[PeekStatementAST: %r queue_name: %r type: %r %r]" % \ (self.method, self.queue_name, self.type_ast, self.statements) - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): self.symtab.pushFrame() msg_type = self.type_ast.type @@ -91,7 +91,7 @@ class PeekStatementAST(StatementAST): ''') # The other statements - self.statements.generate(code, return_type) + self.statements.generate(code, return_type, **kwargs) self.symtab.popFrame() code("}") diff --git a/src/mem/slicc/ast/ReturnStatementAST.py b/src/mem/slicc/ast/ReturnStatementAST.py index 754bb4c9f..415d442c7 100644 --- a/src/mem/slicc/ast/ReturnStatementAST.py +++ b/src/mem/slicc/ast/ReturnStatementAST.py @@ -36,7 +36,7 @@ class ReturnStatementAST(StatementAST): def __repr__(self): return "[ReturnStatementAST: %r]" % self.expr_ast - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): actual_type, ecode = self.expr_ast.inline(True) code('return $ecode;') diff --git a/src/mem/slicc/ast/StallAndWaitStatementAST.py b/src/mem/slicc/ast/StallAndWaitStatementAST.py index ad261e26f..04d9e20ed 100644 --- a/src/mem/slicc/ast/StallAndWaitStatementAST.py +++ b/src/mem/slicc/ast/StallAndWaitStatementAST.py @@ -37,7 +37,7 @@ class StallAndWaitStatementAST(StatementAST): def __repr__(self): return "[StallAndWaitStatementAst: %r]" % self.in_port - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): self.in_port.assertType("InPort") self.address.assertType("Addr") diff --git a/src/mem/slicc/ast/StatementListAST.py b/src/mem/slicc/ast/StatementListAST.py index 1475c5c97..9d74e66dc 100644 --- a/src/mem/slicc/ast/StatementListAST.py +++ b/src/mem/slicc/ast/StatementListAST.py @@ -37,9 +37,9 @@ class StatementListAST(AST): def __repr__(self): return "[StatementListAST: %r]" % self.statements - def generate(self, code, return_type): + def generate(self, code, return_type, **kwargs): for statement in self.statements: - statement.generate(code, return_type) + statement.generate(code, return_type, **kwargs) def findResources(self, resources): for statement in self.statements: diff --git a/src/mem/slicc/ast/StaticCastAST.py b/src/mem/slicc/ast/StaticCastAST.py index 71280ba67..4c664865a 100644 --- a/src/mem/slicc/ast/StaticCastAST.py +++ b/src/mem/slicc/ast/StaticCastAST.py @@ -37,7 +37,7 @@ class StaticCastAST(ExprAST): def __repr__(self): return "[StaticCastAST: %r]" % self.expr_ast - def generate(self, code): + def generate(self, code, **kwargs): actual_type, ecode = self.expr_ast.inline(True) if self.type_modifier == "pointer": code('static_cast<${{self.type_ast.type.c_ident}} *>($ecode)') diff --git a/src/mem/slicc/ast/TypeFieldEnumAST.py b/src/mem/slicc/ast/TypeFieldEnumAST.py index b9a8ae80f..f55499057 100644 --- a/src/mem/slicc/ast/TypeFieldEnumAST.py +++ b/src/mem/slicc/ast/TypeFieldEnumAST.py @@ -38,7 +38,7 @@ class TypeFieldEnumAST(TypeFieldAST): def __repr__(self): return "[TypeFieldEnum: %r]" % self.field_id - def generate(self, type): + def generate(self, type, **kwargs): if str(type) == "State": self.error("States must in a State Declaration, not a normal enum.") diff --git a/src/mem/slicc/ast/TypeFieldStateAST.py b/src/mem/slicc/ast/TypeFieldStateAST.py index deac143bb..ff1ae9720 100644 --- a/src/mem/slicc/ast/TypeFieldStateAST.py +++ b/src/mem/slicc/ast/TypeFieldStateAST.py @@ -40,7 +40,7 @@ class TypeFieldStateAST(TypeFieldAST): def __repr__(self): return "[TypeFieldState: %r]" % self.field_id - def generate(self, type): + def generate(self, type, **kwargs): if not str(type) == "State": self.error("State Declaration must be of type State.") diff --git a/src/mem/slicc/ast/VarExprAST.py b/src/mem/slicc/ast/VarExprAST.py index 19a619b37..f555c72d1 100644 --- a/src/mem/slicc/ast/VarExprAST.py +++ b/src/mem/slicc/ast/VarExprAST.py @@ -60,7 +60,7 @@ class VarExprAST(ExprAST): "'%s' is expected to be type '%s' not '%s'", self.var.ident, expected_type, self.var.type) - def generate(self, code): + def generate(self, code, **kwargs): fix = code.nofix() code("${{self.var.code}}") code.fix(fix)