ruby: move stall and wakeup functions to AbstractController
[gem5.git] / src / mem / slicc / parser.py
index 891f229734c64fd97b8c8708356ed1c293c30158..78b842f7487722049c9a474d3e1f902f1717299f 100644 (file)
@@ -30,88 +30,46 @@ import os.path
 import re
 import sys
 
-from m5.util.grammar import Grammar, TokenError, ParseError
+from m5.util import code_formatter
+from m5.util.grammar import Grammar, ParseError
 
 import slicc.ast as ast
 import slicc.util as util
 from slicc.symbols import SymbolTable
 
-def read_slicc(sources):
-    if not isinstance(sources, (list,tuple)):
-        sources = [ sources ]
-
-    for source in sources:
-        for sm_file in file(source, "r"):
-            sm_file = sm_file.strip()
-            if not sm_file:
-                continue
-            if sm_file.startswith("#"):
-                continue
-            yield sm_file
-
 class SLICC(Grammar):
-    def __init__(self, **kwargs):
-        super(SLICC, self).__init__(**kwargs)
-        self.decl_list_vec = []
-        self.current_file = None
-        self.symtab = SymbolTable()
-
-    def parse(self, filename):
-        self.current_file = filename
-        f = file(filename, 'r')
-        text = f.read()
+    def __init__(self, filename, base_dir, verbose=False, traceback=False, **kwargs):
+        self.protocol = None
+        self.traceback = traceback
+        self.verbose = verbose
+        self.symtab = SymbolTable(self)
+        self.base_dir = base_dir
+
         try:
-            decl_list = super(SLICC, self).parse(text)
-        except (TokenError, ParseError), e:
-            sys.exit("%s: %s:%d" % (e, filename, e.token.lineno))
-        self.decl_list_vec.append(decl_list)
-        self.current_file = None
-
-    def _load(self, *filenames):
-        filenames = list(filenames)
-        while filenames:
-            f = filenames.pop(0)
-            if isinstance(f, (list, tuple)):
-                filenames[0:0] = list(f)
-                continue
-
-            yield f
-            if f.endswith(".slicc"):
-                dirname,basename = os.path.split(f)
-                filenames[0:0] = [ os.path.join(dirname, x) \
-                                   for x in read_slicc(f)]
-            else:
-                assert f.endswith(".sm")
-                self.parse(f)
-
-    def load(self, *filenames, **kwargs):
-        verbose = kwargs.pop("verbose", False)
-        if kwargs:
-            raise TypeError
-
-        gen = self._load(*filenames)
-        if verbose:
-            return gen
-        else:
-            # Run out the generator if we don't want the verbosity
-            for foo in gen:
-                pass
+            self.decl_list = self.parse_file(filename, **kwargs)
+        except ParseError, e:
+            if not self.traceback:
+                sys.exit(str(e))
+            raise
 
-    def findMachines(self):
-        for decl_list in self.decl_list_vec:
-            decl_list.findMachines()
+    def currentLocation(self):
+        return util.Location(self.current_source, self.current_line,
+                             no_warning=not self.verbose)
 
-    def generate(self):
-        for decl_list in self.decl_list_vec:
-            decl_list.generate()
+    def codeFormatter(self, *args, **kwargs):
+        code = code_formatter(*args, **kwargs)
+        code['protocol'] = self.protocol
+        return code
 
-    def writeCodeFiles(self, code_path):
-        util.makeDir(code_path)
-        self.symtab.writeCodeFiles(code_path)
+    def process(self):
+        self.decl_list.findMachines()
+        self.decl_list.generate()
 
-    def writeHTMLFiles(self, code_path):
-        util.makeDir(code_path)
-        self.symtab.writeHTMLFiles(code_path)
+    def writeCodeFiles(self, code_path, includes):
+        self.symtab.writeCodeFiles(code_path, includes)
+
+    def writeHTMLFiles(self, html_path):
+        self.symtab.writeHTMLFiles(html_path)
 
     def files(self):
         f = set([
@@ -119,8 +77,7 @@ class SLICC(Grammar):
             'MachineType.hh',
             'Types.hh' ])
 
-        for decl_list in self.decl_list_vec:
-            f |= decl_list.files()
+        f |= self.decl_list.files()
 
         return f
 
@@ -140,6 +97,8 @@ class SLICC(Grammar):
         t.lexer.lineno += len(t.value)
 
     reserved = {
+        'protocol' : 'PROTOCOL',
+        'include' : 'INCLUDE',
         'global' : 'GLOBAL',
         'machine' : 'MACHINE',
         'in_port' : 'IN_PORT',
@@ -149,18 +108,22 @@ class SLICC(Grammar):
         'structure' : 'STRUCT',
         'external_type' : 'EXTERN_TYPE',
         'enumeration' : 'ENUM',
+        'state_declaration' : 'STATE_DECL',
         'peek' : 'PEEK',
+        'stall_and_wait' : 'STALL_AND_WAIT',
         'enqueue' : 'ENQUEUE',
         'copy_head' : 'COPY_HEAD',
         'check_allocate' : 'CHECK_ALLOCATE',
         'check_stop_slots' : 'CHECK_STOP_SLOTS',
+        'static_cast' : 'STATIC_CAST',
         'if' : 'IF',
+        'is_valid' : 'IS_VALID',
+        'is_invalid' : 'IS_INVALID',
         'else' : 'ELSE',
         'return' : 'RETURN',
-        'THIS' : 'THIS',
-        'CHIP' : 'CHIP',
         'void' : 'VOID',
         'new' : 'NEW',
+        'OOD' : 'OOD',
     }
 
     literals = ':[]{}(),='
@@ -225,7 +188,7 @@ class SLICC(Grammar):
         try:
             t.value = float(t.value)
         except ValueError:
-            raise TokenError("Illegal float", t)
+            raise ParseError("Illegal float", t)
         return t
 
     def t_NUMBER(self, t):
@@ -233,7 +196,7 @@ class SLICC(Grammar):
         try:
             t.value = int(t.value)
         except ValueError:
-            raise TokenError("Illegal number", t)
+            raise ParseError("Illegal number", t)
         return t
 
     def t_STRING1(self, t):
@@ -261,12 +224,36 @@ class SLICC(Grammar):
 
     def p_declsx__list(self, p):
         "declsx : decl declsx"
-        p[0] = [ p[1] ] + p[2]
+        if isinstance(p[1], ast.DeclListAST):
+            decls = p[1].decls
+        elif p[1] is None:
+            decls = []
+        else:
+            decls = [ p[1] ]
+        p[0] = decls + p[2]
 
     def p_declsx__none(self, p):
         "declsx : empty"
         p[0] = []
 
+    def p_decl__protocol(self, p):
+        "decl : PROTOCOL STRING SEMI"
+        if self.protocol:
+            msg = "Protocol can only be set once! Error at %s:%s\n" % \
+                (self.current_source, self.current_line)
+            raise ParseError(msg)
+        self.protocol = p[2]
+        p[0] = None
+
+    def p_decl__include(self, p):
+        "decl : INCLUDE STRING SEMI"
+        dirname = os.path.dirname(self.current_source)
+        if os.path.exists(os.path.join(dirname, p[2])):
+            filename = os.path.join(dirname, p[2])
+        else:
+            filename = os.path.join(self.base_dir, p[2])
+        p[0] = self.parse_file(filename)
+
     def p_decl__machine(self, p):
         "decl : MACHINE '(' ident pairs ')' ':' params '{' decls '}'"
         p[0] = ast.MachineAST(self, p[3], p[4], p[7], p[9])
@@ -285,22 +272,25 @@ class SLICC(Grammar):
 
     def p_decl__trans0(self, p):
         "decl : TRANS '(' idents ',' idents ',' ident pairs ')' idents"
-        p[0] = ast.TransitionDeclAST(self, p[3], p[5], p[7], p[8], p[10])
+        p[0] = ast.TransitionDeclAST(self, [], p[3], p[5], p[7], p[8], p[10])
 
     def p_decl__trans1(self, p):
         "decl : TRANS '(' idents ',' idents           pairs ')' idents"
-        p[0] = ast.TransitionDeclAST(self, p[3], p[5], None, p[6], p[8])
+        p[0] = ast.TransitionDeclAST(self, [], p[3], p[5], None, p[6], p[8])
+
+    def p_decl__trans2(self, p):
+        "decl : TRANS '(' idents ',' idents ',' ident pairs ')' idents idents"
+        p[0] = ast.TransitionDeclAST(self, p[10], p[3], p[5], p[7], p[8], p[11])
+
+    def p_decl__trans3(self, p):
+        "decl : TRANS '(' idents ',' idents           pairs ')' idents idents"
+        p[0] = ast.TransitionDeclAST(self, p[8], p[3], p[5], None, p[6], p[9])
 
     def p_decl__extern0(self, p):
         "decl : EXTERN_TYPE '(' type pairs ')' SEMI"
         p[4]["external"] = "yes"
         p[0] = ast.TypeDeclAST(self, p[3], p[4], [])
 
-    def p_decl__extern1(self, p):
-        "decl : EXTERN_TYPE '(' type pairs ')' '{' type_methods '}'"
-        p[4]["external"] = "yes"
-        p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7])
-
     def p_decl__global(self, p):
         "decl : GLOBAL '(' type pairs ')' '{' type_members '}'"
         p[4]["global"] = "yes"
@@ -315,18 +305,33 @@ class SLICC(Grammar):
         p[4]["enumeration"] = "yes"
         p[0] = ast.EnumDeclAST(self, p[3], p[4], p[7])
 
+    def p_decl__state_decl(self, p):
+        "decl : STATE_DECL '(' type pairs ')' '{' type_states   '}'"
+        p[4]["enumeration"] = "yes"
+        p[4]["state_decl"] = "yes"
+        p[0] = ast.StateDeclAST(self, p[3], p[4], p[7])
+
     def p_decl__object(self, p):
         "decl : type ident pairs SEMI"
         p[0] = ast.ObjDeclAST(self, p[1], p[2], p[3])
 
+    # Function definition and declaration
     def p_decl__func_decl(self, p):
-        """decl : void ident '(' params ')' pairs SEMI
+        "decl : func_decl"
+        p[0] = p[1]
+
+    def p_func_decl__0(self, p):
+        """func_decl :  void ident '(' params ')' pairs SEMI
                 | type ident '(' params ')' pairs SEMI"""
         p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None)
 
     def p_decl__func_def(self, p):
-        """decl : void ident '(' params ')' pairs statements
-                | type ident '(' params ')' pairs statements"""
+        "decl : func_def"
+        p[0] = p[1]
+
+    def p_func_def__0(self, p):
+        """func_def : void ident '(' params ')' pairs statements
+            | type ident '(' params ')' pairs statements"""
         p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7])
 
     # Type fields
@@ -338,28 +343,23 @@ class SLICC(Grammar):
         "type_members : empty"
         p[0] = []
 
+    def p_type_method__0(self, p):
+        "type_member : type_or_void ident '(' types ')' pairs SEMI"
+        p[0] = ast.TypeFieldMethodAST(self, p[1], p[2], p[4], p[6])
+
+    def p_type_method__1(self, p):
+        "type_member : type_or_void ident '(' params ')' pairs statements"
+        p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7])
+
     def p_type_member__1(self, p):
-        "type_member : type ident pairs SEMI"
+        "type_member : type_or_void ident pairs SEMI"
         p[0] = ast.TypeFieldMemberAST(self, p[1], p[2], p[3], None)
 
     def p_type_member__2(self, p):
-        "type_member : type ident ASSIGN expr SEMI"
+        "type_member : type_or_void ident ASSIGN expr SEMI"
         p[0] = ast.TypeFieldMemberAST(self, p[1], p[2],
                                       ast.PairListAST(self), p[4])
 
-    # Methods
-    def p_type_methods__list(self, p):
-        "type_methods : type_method type_methods"
-        p[0] = [ p[1] ] + p[2]
-
-    def p_type_methods(self, p):
-        "type_methods : empty"
-        p[0] = []
-
-    def p_type_method(self, p):
-        "type_method : type_or_void ident '(' types ')' pairs SEMI"
-        p[0] = ast.TypeFieldMethodAST(self, p[1], p[2], p[4], p[6])
-
     # Enum fields
     def p_type_enums__list(self, p):
         "type_enums : type_enum type_enums"
@@ -373,6 +373,19 @@ class SLICC(Grammar):
         "type_enum : ident pairs SEMI"
         p[0] = ast.TypeFieldEnumAST(self, p[1], p[2])
 
+    # States
+    def p_type_states__list(self, p):
+        "type_states : type_state type_states"
+        p[0] = [ p[1] ] + p[2]
+
+    def p_type_states__empty(self, p):
+        "type_states : empty"
+        p[0] = []
+
+    def p_type_state(self, p):
+        "type_state : ident ',' enumeration pairs SEMI"
+        p[0] = ast.TypeFieldStateAST(self, p[1], p[3], p[4])
+
     # Type
     def p_types__multiple(self, p):
         "types : type ',' types"
@@ -386,8 +399,16 @@ class SLICC(Grammar):
         "types : empty"
         p[0] = []
 
-    def p_type(self, p):
-        "type : ident"
+    def p_typestr__multi(self, p):
+        "typestr : typestr DOUBLE_COLON ident"
+        p[0] = '%s::%s' % (p[1], p[3])
+
+    def p_typestr__single(self, p):
+        "typestr : ident"
+        p[0] = p[1]
+
+    def p_type__one(self, p):
+        "type : typestr"
         p[0] = ast.TypeAST(self, p[1])
 
     def p_void(self, p):
@@ -416,10 +437,26 @@ class SLICC(Grammar):
         "param : type ident"
         p[0] = ast.FormalParamAST(self, p[1], p[2])
 
-    def p_param__default(self, p):
+    def p_param__pointer(self, p):
+        "param : type STAR ident"
+        p[0] = ast.FormalParamAST(self, p[1], p[3], None, True)
+
+    def p_param__pointer_default(self, p):
+        "param : type STAR ident '=' STRING"
+        p[0] = ast.FormalParamAST(self, p[1], p[3], p[5], True)
+
+    def p_param__default_number(self, p):
         "param : type ident '=' NUMBER"
         p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
 
+    def p_param__default_bool(self, p):
+        "param : type ident '=' LIT_BOOL"
+        p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
+
+    def p_param__default_string(self, p):
+        "param : type ident '=' STRING"
+        p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
+
     # Idents and lists
     def p_idents__braced(self, p):
         "idents : '{' identx '}'"
@@ -467,7 +504,8 @@ class SLICC(Grammar):
 
     def p_pair__assign(self, p):
         """pair : ident '=' STRING
-                | ident '=' ident"""
+                | ident '=' ident
+                | ident '=' NUMBER"""
         p[0] = ast.PairAST(self, p[1], p[3])
 
     def p_pair__literal(self, p):
@@ -515,6 +553,10 @@ class SLICC(Grammar):
         "statement : ENQUEUE '(' var ',' type pairs ')' statements"
         p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[6], p[8])
 
+    def p_statement__stall_and_wait(self, p):
+        "statement : STALL_AND_WAIT '(' var ',' var ')' SEMI"
+        p[0] = ast.StallAndWaitStatementAST(self, p[3], p[5])
+
     def p_statement__peek(self, p):
         "statement : PEEK '(' var ',' type pairs ')' statements"
         p[0] = ast.PeekStatementAST(self, p[3], p[5], p[6], p[8], "peek")
@@ -531,6 +573,14 @@ class SLICC(Grammar):
         "statement : CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMI"
         p[0] = ast.CheckStopStatementAST(self, p[3], p[5], p[7])
 
+    def p_statement__static_cast(self, p):
+        "aexpr : STATIC_CAST '(' type ',' expr ')'"
+        p[0] = ast.StaticCastAST(self, p[3], "ref", p[5])
+
+    def p_statement__static_cast_ptr(self, p):
+        "aexpr : STATIC_CAST '(' type ',' STRING ',' expr ')'"
+        p[0] = ast.StaticCastAST(self, p[3], p[5], p[7])
+
     def p_statement__return(self, p):
         "statement : RETURN expr SEMI"
         p[0] = ast.ReturnStatementAST(self, p[2])
@@ -556,6 +606,10 @@ class SLICC(Grammar):
         "aexpr : var"
         p[0] = p[1]
 
+    def p_expr__localvar(self, p):
+        "aexpr : type ident"
+        p[0] = ast.LocalVariableAST(self, p[1], p[2])
+
     def p_expr__literal(self, p):
         "aexpr : literal"
         p[0] = p[1]
@@ -572,26 +626,9 @@ class SLICC(Grammar):
         "aexpr : NEW type"
         p[0] = ast.NewExprAST(self, p[2])
 
-    # globally access a local chip component and call a method
-    def p_expr__local_chip_method(self, p):
-        "aexpr : THIS DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'"
-        p[0] = ast.LocalChipMethodAST(self, p[3], p[5], p[8], p[10], p[12])
-
-    # globally access a local chip component and access a data member
-    def p_expr__local_chip_member(self, p):
-        "aexpr : THIS DOT var '[' expr ']' DOT var DOT field"
-        p[0] = ast.LocalChipMemberAST(self, p[3], p[5], p[8], p[10])
-
-    # globally access a specified chip component and call a method
-    def p_expr__specified_chip_method(self, p):
-        "aexpr : CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'"
-        p[0] = ast.SpecifiedChipMethodAST(self, p[3], p[6], p[8], p[11], p[13],
-                                          p[15])
-
-    # globally access a specified chip component and access a data member
-    def p_expr__specified_chip_member(self, p):
-        "aexpr : CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT field"
-        p[0] = ast.SpecifiedChipMemberAST(self, p[3], p[6], p[8], p[11], p[13])
+    def p_expr__null(self, p):
+        "aexpr : OOD"
+        p[0] = ast.OodAST(self)
 
     def p_expr__member(self, p):
         "aexpr : aexpr DOT ident"
@@ -640,9 +677,17 @@ class SLICC(Grammar):
         "aexpr : '(' expr ')'"
         p[0] = p[2]
 
+    def p_expr__is_valid_ptr(self, p):
+        "aexpr : IS_VALID '(' var ')'"
+        p[0] = ast.IsValidPtrExprAST(self, p[3], True)
+
+    def p_expr__is_invalid_ptr(self, p):
+        "aexpr : IS_INVALID '(' var ')'"
+        p[0] = ast.IsValidPtrExprAST(self, p[3], False)
+
     def p_literal__string(self, p):
         "literal : STRING"
-        p[0] = ast.LiteralExprAST(self, p[1], "string")
+        p[0] = ast.LiteralExprAST(self, p[1], "std::string")
 
     def p_literal__number(self, p):
         "literal : NUMBER"
@@ -663,7 +708,3 @@ class SLICC(Grammar):
     def p_var(self, p):
         "var : ident"
         p[0] = ast.VarExprAST(self, p[1])
-
-    def p_field(self, p):
-        "field : ident"
-        p[0] = p[1]