1 # Copyright (c) 2009 The Hewlett-Packard Development Company
2 # Copyright (c) 2017 Google Inc.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met: redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer;
9 # redistributions in binary form must reproduce the above copyright
10 # notice, this list of conditions and the following disclaimer in the
11 # documentation and/or other materials provided with the distribution;
12 # neither the name of the copyright holders nor the names of its
13 # contributors may be used to endorse or promote products derived from
14 # this software without specific prior written permission.
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 # Authors: Nathan Binkert
35 from m5
.util
import code_formatter
36 from m5
.util
.grammar
import Grammar
, ParseError
38 import slicc
.ast
as ast
39 import slicc
.util
as util
40 from slicc
.symbols
import SymbolTable
43 def __init__(self
, filename
, base_dir
, verbose
=False, traceback
=False, **kwargs
):
45 self
.traceback
= traceback
46 self
.verbose
= verbose
47 self
.symtab
= SymbolTable(self
)
48 self
.base_dir
= base_dir
51 self
.decl_list
= self
.parse_file(filename
, **kwargs
)
53 if not self
.traceback
:
57 def currentLocation(self
):
58 return util
.Location(self
.current_source
, self
.current_line
,
59 no_warning
=not self
.verbose
)
61 def codeFormatter(self
, *args
, **kwargs
):
62 code
= code_formatter(*args
, **kwargs
)
63 code
['protocol'] = self
.protocol
67 self
.decl_list
.generate()
69 def writeCodeFiles(self
, code_path
, includes
):
70 self
.symtab
.writeCodeFiles(code_path
, includes
)
72 def writeHTMLFiles(self
, html_path
):
73 self
.symtab
.writeHTMLFiles(html_path
)
78 f |
= self
.decl_list
.files()
84 # C or C++ comment (ignore)
85 def t_c_comment(self
, t
):
87 t
.lexer
.lineno
+= t
.value
.count('\n')
89 def t_cpp_comment(self
, t
):
92 # Define a rule so we can track line numbers
93 def t_newline(self
, t
):
95 t
.lexer
.lineno
+= len(t
.value
)
98 'protocol' : 'PROTOCOL',
99 'include' : 'INCLUDE',
101 'machine' : 'MACHINE',
102 'in_port' : 'IN_PORT',
103 'out_port' : 'OUT_PORT',
105 'transition' : 'TRANS',
106 'structure' : 'STRUCT',
107 'external_type' : 'EXTERN_TYPE',
108 'enumeration' : 'ENUM',
109 'state_declaration' : 'STATE_DECL',
111 'stall_and_wait' : 'STALL_AND_WAIT',
112 'enqueue' : 'ENQUEUE',
113 'check_allocate' : 'CHECK_ALLOCATE',
114 'check_next_cycle' : 'CHECK_NEXT_CYCLE',
115 'check_stop_slots' : 'CHECK_STOP_SLOTS',
116 'static_cast' : 'STATIC_CAST',
118 'is_valid' : 'IS_VALID',
119 'is_invalid' : 'IS_INVALID',
127 literals
= ':[]{}(),='
129 tokens
= [ 'EQ', 'NE', 'LT', 'GT', 'LE', 'GE',
130 'LEFTSHIFT', 'RIGHTSHIFT',
132 'PLUS', 'DASH', 'STAR', 'SLASH',
134 'DOUBLE_COLON', 'SEMI',
136 'IDENT', 'LIT_BOOL', 'FLOATNUMBER', 'NUMBER', 'STRING' ]
137 tokens
+= reserved
.values()
154 t_DOUBLE_COLON
= r
'::'
162 ('left', 'INCR', 'DECR'),
165 ('left', 'EQ', 'NE'),
166 ('left', 'LT', 'GT', 'LE', 'GE'),
167 ('left', 'RIGHTSHIFT', 'LEFTSHIFT'),
168 ('left', 'PLUS', 'DASH'),
169 ('left', 'STAR', 'SLASH'),
170 ('right', 'NOT', 'UMINUS'),
173 def t_IDENT(self
, t
):
174 r
'[a-zA-Z_][a-zA-Z_0-9]*'
175 if t
.value
== 'true':
180 if t
.value
== 'false':
185 # Check for reserved words
186 t
.type = self
.reserved
.get(t
.value
, 'IDENT')
189 def t_FLOATNUMBER(self
, t
):
192 t
.value
= float(t
.value
)
194 raise ParseError("Illegal float", t
)
197 def t_NUMBER(self
, t
):
200 t
.value
= int(t
.value
)
202 raise ParseError("Illegal number", t
)
205 def t_STRING1(self
, t
):
208 t
.value
= t
.value
[1:-1]
211 def t_STRING2(self
, t
):
214 t
.value
= t
.value
[1:-1]
221 def p_empty(self
, p
):
224 def p_decls(self
, p
):
226 p
[0] = ast
.DeclListAST(self
, p
[1])
228 def p_declsx__list(self
, p
):
229 "declsx : decl declsx"
230 if isinstance(p
[1], ast
.DeclListAST
):
238 def p_declsx__none(self
, p
):
242 def p_decl__protocol(self
, p
):
243 "decl : PROTOCOL STRING SEMI"
245 msg
= "Protocol can only be set once! Error at %s:%s\n" % \
246 (self
.current_source
, self
.current_line
)
247 raise ParseError(msg
)
251 def p_decl__include(self
, p
):
252 "decl : INCLUDE STRING SEMI"
253 dirname
= os
.path
.dirname(self
.current_source
)
254 if os
.path
.exists(os
.path
.join(dirname
, p
[2])):
255 filename
= os
.path
.join(dirname
, p
[2])
257 filename
= os
.path
.join(self
.base_dir
, p
[2])
258 p
[0] = self
.parse_file(filename
)
260 def p_decl__machine0(self
, p
):
261 "decl : MACHINE '(' enumeration ')' ':' obj_decls '{' decls '}'"
262 p
[0] = ast
.MachineAST(self
, p
[3], [], p
[7], p
[9])
264 def p_decl__machine1(self
, p
):
265 "decl : MACHINE '(' enumeration pairs ')' ':' obj_decls '{' decls '}'"
266 p
[0] = ast
.MachineAST(self
, p
[3], p
[4], p
[7], p
[9])
268 def p_decl__action(self
, p
):
269 "decl : ACTION '(' ident pairs ')' statements"
270 p
[0] = ast
.ActionDeclAST(self
, p
[3], p
[4], p
[6])
272 def p_decl__in_port(self
, p
):
273 "decl : IN_PORT '(' ident ',' type ',' var pairs ')' statements"
274 p
[0] = ast
.InPortDeclAST(self
, p
[3], p
[5], p
[7], p
[8], p
[10])
276 def p_decl__out_port(self
, p
):
277 "decl : OUT_PORT '(' ident ',' type ',' var pairs ')' SEMI"
278 p
[0] = ast
.OutPortDeclAST(self
, p
[3], p
[5], p
[7], p
[8])
280 def p_decl__trans0(self
, p
):
281 "decl : TRANS '(' idents ',' idents ',' ident_or_star ')' idents"
282 p
[0] = ast
.TransitionDeclAST(self
, [], p
[3], p
[5], p
[7], p
[9])
284 def p_decl__trans1(self
, p
):
285 "decl : TRANS '(' idents ',' idents ')' idents"
286 p
[0] = ast
.TransitionDeclAST(self
, [], p
[3], p
[5], None, p
[7])
288 def p_decl__trans2(self
, p
):
289 "decl : TRANS '(' idents ',' idents ',' ident_or_star ')' idents idents"
290 p
[0] = ast
.TransitionDeclAST(self
, p
[9], p
[3], p
[5], p
[7], p
[10])
292 def p_decl__trans3(self
, p
):
293 "decl : TRANS '(' idents ',' idents ')' idents idents"
294 p
[0] = ast
.TransitionDeclAST(self
, p
[7], p
[3], p
[5], None, p
[8])
296 def p_decl__extern0(self
, p
):
297 "decl : EXTERN_TYPE '(' type pairs ')' SEMI"
298 p
[4]["external"] = "yes"
299 p
[0] = ast
.TypeDeclAST(self
, p
[3], p
[4], [])
301 def p_decl__global(self
, p
):
302 "decl : GLOBAL '(' type pairs ')' '{' type_members '}'"
303 p
[4]["global"] = "yes"
304 p
[0] = ast
.TypeDeclAST(self
, p
[3], p
[4], p
[7])
306 def p_decl__struct(self
, p
):
307 "decl : STRUCT '(' type pairs ')' '{' type_members '}'"
308 p
[0] = ast
.TypeDeclAST(self
, p
[3], p
[4], p
[7])
310 def p_decl__enum(self
, p
):
311 "decl : ENUM '(' type pairs ')' '{' type_enums '}'"
312 p
[4]["enumeration"] = "yes"
313 p
[0] = ast
.EnumDeclAST(self
, p
[3], p
[4], p
[7])
315 def p_decl__state_decl(self
, p
):
316 "decl : STATE_DECL '(' type pairs ')' '{' type_states '}'"
317 p
[4]["enumeration"] = "yes"
318 p
[4]["state_decl"] = "yes"
319 p
[0] = ast
.StateDeclAST(self
, p
[3], p
[4], p
[7])
322 def p_obj_decls__list(self
, p
):
323 "obj_decls : obj_decl obj_decls"
324 p
[0] = [ p
[1] ] + p
[2]
326 def p_obj_decls__empty(self
, p
):
330 def p_type_members__list(self
, p
):
331 "type_members : type_member type_members"
332 p
[0] = [ p
[1] ] + p
[2]
334 def p_type_members__empty(self
, p
):
335 "type_members : empty"
338 def p_type_member__0(self
, p
):
339 """type_member : obj_decl
344 # Member / Variable declarations
345 def p_decl__obj_decl(self
, p
):
349 def p_obj_decl__0(self
, p
):
350 "obj_decl : type ident pairs SEMI"
351 p
[0] = ast
.ObjDeclAST(self
, p
[1], p
[2], p
[3], None, False)
353 def p_obj_decl__1(self
, p
):
354 "obj_decl : type STAR ident pairs SEMI"
355 p
[0] = ast
.ObjDeclAST(self
, p
[1], p
[3], p
[4], None, True)
357 def p_obj_decl__2(self
, p
):
358 "obj_decl : type ident ASSIGN expr SEMI"
359 p
[0] = ast
.ObjDeclAST(self
, p
[1], p
[2], ast
.PairListAST(self
), p
[4],
362 def p_obj_decl__3(self
, p
):
363 "obj_decl : type STAR ident ASSIGN expr SEMI"
364 p
[0] = ast
.ObjDeclAST(self
, p
[1], p
[3], ast
.PairListAST(self
), p
[5],
367 # Function definition and declaration
368 def p_decl__func_decl(self
, p
):
372 def p_func_decl__0(self
, p
):
373 """func_decl : void ident '(' params ')' pairs SEMI
374 | type ident '(' params ')' pairs SEMI"""
375 p
[0] = ast
.FuncDeclAST(self
, p
[1], p
[2], p
[4], p
[6], None)
377 def p_func_decl__1(self
, p
):
378 """func_decl : void ident '(' types ')' pairs SEMI
379 | type ident '(' types ')' pairs SEMI"""
380 p
[0] = ast
.FuncDeclAST(self
, p
[1], p
[2], p
[4], p
[6], None)
382 def p_decl__func_def(self
, p
):
386 def p_func_def__0(self
, p
):
387 """func_def : void ident '(' params ')' pairs statements
388 | type ident '(' params ')' pairs statements"""
389 p
[0] = ast
.FuncDeclAST(self
, p
[1], p
[2], p
[4], p
[6], p
[7])
392 def p_type_enums__list(self
, p
):
393 "type_enums : type_enum type_enums"
394 p
[0] = [ p
[1] ] + p
[2]
396 def p_type_enums__empty(self
, p
):
400 def p_type_enum(self
, p
):
401 "type_enum : ident pairs SEMI"
402 p
[0] = ast
.TypeFieldEnumAST(self
, p
[1], p
[2])
405 def p_type_states__list(self
, p
):
406 "type_states : type_state type_states"
407 p
[0] = [ p
[1] ] + p
[2]
409 def p_type_states__empty(self
, p
):
410 "type_states : empty"
413 def p_type_state(self
, p
):
414 "type_state : ident ',' enumeration pairs SEMI"
415 p
[0] = ast
.TypeFieldStateAST(self
, p
[1], p
[3], p
[4])
418 def p_params__many(self
, p
):
419 "params : param ',' params"
420 p
[0] = [ p
[1] ] + p
[3]
422 def p_params__one(self
, p
):
426 def p_params__none(self
, p
):
430 def p_param(self
, p
):
432 p
[0] = ast
.FormalParamAST(self
, p
[1], p
[2])
434 def p_param__pointer(self
, p
):
435 "param : type STAR ident"
436 p
[0] = ast
.FormalParamAST(self
, p
[1], p
[3], None, True)
438 def p_param__pointer_default(self
, p
):
439 "param : type STAR ident ASSIGN STRING"
440 p
[0] = ast
.FormalParamAST(self
, p
[1], p
[3], p
[5], True)
442 def p_param__default_number(self
, p
):
443 "param : type ident ASSIGN NUMBER"
444 p
[0] = ast
.FormalParamAST(self
, p
[1], p
[2], p
[4])
446 def p_param__default_bool(self
, p
):
447 "param : type ident ASSIGN LIT_BOOL"
448 p
[0] = ast
.FormalParamAST(self
, p
[1], p
[2], p
[4])
450 def p_param__default_string(self
, p
):
451 "param : type ident ASSIGN STRING"
452 p
[0] = ast
.FormalParamAST(self
, p
[1], p
[2], p
[4])
455 def p_types__multiple(self
, p
):
456 "types : type ',' types"
457 p
[0] = [ p
[1] ] + p
[3]
459 def p_types__one(self
, p
):
463 def p_types__empty(self
, p
):
467 def p_typestr__multi(self
, p
):
468 "typestr : typestr DOUBLE_COLON ident"
469 p
[0] = '%s::%s' % (p
[1], p
[3])
471 def p_typestr__single(self
, p
):
475 def p_type__one(self
, p
):
477 p
[0] = ast
.TypeAST(self
, p
[1])
481 p
[0] = ast
.TypeAST(self
, p
[1])
484 def p_idents__braced(self
, p
):
485 "idents : '{' identx '}'"
488 def p_idents__bare(self
, p
):
492 def p_identx__multiple_1(self
, p
):
493 """identx : ident SEMI identx
494 | ident ',' identx"""
495 p
[0] = [ p
[1] ] + p
[3]
497 def p_identx__multiple_2(self
, p
):
498 "identx : ident identx"
499 p
[0] = [ p
[1] ] + p
[2]
501 def p_identx__single(self
, p
):
505 def p_ident(self
, p
):
509 def p_ident_or_star(self
, p
):
510 """ident_or_star : ident
514 # Pair and pair lists
515 def p_pairs__list(self
, p
):
519 def p_pairs__empty(self
, p
):
521 p
[0] = ast
.PairListAST(self
)
523 def p_pairsx__many(self
, p
):
524 "pairsx : pair ',' pairsx"
528 def p_pairsx__one(self
, p
):
530 p
[0] = ast
.PairListAST(self
)
533 def p_pair__assign(self
, p
):
534 """pair : ident '=' STRING
536 | ident '=' NUMBER"""
537 p
[0] = ast
.PairAST(self
, p
[1], p
[3])
539 def p_pair__literal(self
, p
):
541 p
[0] = ast
.PairAST(self
, "short", p
[1])
543 # Below are the rules for action descriptions
544 def p_statements__inner(self
, p
):
545 "statements : '{' statements_inner '}'"
546 p
[0] = ast
.StatementListAST(self
, p
[2])
548 def p_statements__none(self
, p
):
549 "statements : '{' '}'"
550 p
[0] = ast
.StatementListAST(self
, [])
552 def p_statements_inner__many(self
, p
):
553 "statements_inner : statement statements_inner"
554 p
[0] = [ p
[1] ] + p
[2]
556 def p_statements_inner__one(self
, p
):
557 "statements_inner : statement"
560 def p_exprs__multiple(self
, p
):
561 "exprs : expr ',' exprs"
562 p
[0] = [ p
[1] ] + p
[3]
564 def p_exprs__one(self
, p
):
568 def p_exprs__empty(self
, p
):
572 def p_statement__expression(self, p):
573 "statement
: expr SEMI
"
574 p[0] = ast.ExprStatementAST(self, p[1])
576 def p_statement__assign(self, p):
577 "statement
: expr ASSIGN expr SEMI
"
578 p[0] = ast.AssignStatementAST(self, p[1], p[3])
580 def p_statement__enqueue(self, p):
581 "statement
: ENQUEUE
'(' var
',' type ')' statements
"
582 p[0] = ast.EnqueueStatementAST(self, p[3], p[5], None, p[7])
584 def p_statement__enqueue_latency(self, p):
585 "statement
: ENQUEUE
'(' var
',' type ',' expr
')' statements
"
586 p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[7], p[9])
588 def p_statement__stall_and_wait(self, p):
589 "statement
: STALL_AND_WAIT
'(' var
',' var
')' SEMI
"
590 p[0] = ast.StallAndWaitStatementAST(self, p[3], p[5])
592 def p_statement__peek(self, p):
593 "statement
: PEEK
'(' var
',' type pairs
')' statements
"
594 p[0] = ast.PeekStatementAST(self, p[3], p[5], p[6], p[8], "peek
")
596 def p_statement__check_allocate(self, p):
597 "statement
: CHECK_ALLOCATE
'(' var
')' SEMI
"
598 p[0] = ast.CheckAllocateStatementAST(self, p[3])
600 def p_statement__check_next_cycle(self, p):
601 "statement
: CHECK_NEXT_CYCLE
'(' ')' SEMI
"
602 p[0] = ast.CheckNextCycleAST(self)
604 def p_statement__check_stop(self, p):
605 "statement
: CHECK_STOP_SLOTS
'(' var
',' STRING
',' STRING
')' SEMI
"
606 p[0] = ast.CheckStopStatementAST(self, p[3], p[5], p[7])
608 def p_statement__return(self, p):
609 "statement
: RETURN expr SEMI
"
610 p[0] = ast.ReturnStatementAST(self, p[2])
612 def p_statement__if(self, p):
613 "statement
: if_statement
"
616 def p_if_statement__if(self, p):
617 "if_statement
: IF
'(' expr
')' statements
"
618 p[0] = ast.IfStatementAST(self, p[3], p[5], None)
620 def p_if_statement__if_else(self, p):
621 "if_statement
: IF
'(' expr
')' statements ELSE statements
"
622 p[0] = ast.IfStatementAST(self, p[3], p[5], p[7])
624 def p_statement__if_else_if(self, p):
625 "if_statement
: IF
'(' expr
')' statements ELSE if_statement
"
626 p[0] = ast.IfStatementAST(self, p[3], p[5],
627 ast.StatementListAST(self, p[7]))
629 def p_expr__static_cast(self, p):
630 "aexpr
: STATIC_CAST
'(' type ',' expr
')'"
631 p[0] = ast.StaticCastAST(self, p[3], "ref
", p[5])
633 def p_expr__static_cast_ptr(self, p):
634 "aexpr
: STATIC_CAST
'(' type ',' STRING
',' expr
')'"
635 p[0] = ast.StaticCastAST(self, p[3], p[5], p[7])
637 def p_expr__var(self, p):
641 def p_expr__localvar(self, p):
643 p[0] = ast.LocalVariableAST(self, p[1], p[2])
645 def p_expr__literal(self, p):
649 def p_expr__enumeration(self, p):
650 "aexpr
: enumeration
"
653 def p_expr__func_call(self, p):
654 "aexpr
: ident
'(' exprs
')'"
655 p[0] = ast.FuncCallExprAST(self, p[1], p[3])
657 def p_expr__new(self, p):
659 p[0] = ast.NewExprAST(self, p[2])
661 def p_expr__null(self, p):
663 p[0] = ast.OodAST(self)
665 def p_expr__member(self, p):
666 "aexpr
: aexpr DOT ident
"
667 p[0] = ast.MemberExprAST(self, p[1], p[3])
669 def p_expr__member_method_call(self, p):
670 "aexpr
: aexpr DOT ident
'(' exprs
')'"
671 p[0] = ast.MemberMethodCallExprAST(self, p[1],
672 ast.FuncCallExprAST(self, p[3], p[5]))
674 def p_expr__member_method_call_lookup(self, p):
675 "aexpr
: aexpr
'[' exprs
']'"
676 p[0] = ast.MemberMethodCallExprAST(self, p[1],
677 ast.FuncCallExprAST(self, "lookup
", p[3]))
679 def p_expr__class_method_call(self, p):
680 "aexpr
: type DOUBLE_COLON ident
'(' exprs
')'"
681 p[0] = ast.ClassMethodCallExprAST(self, p[1],
682 ast.FuncCallExprAST(self, p[3], p[5]))
684 def p_expr__aexpr(self, p):
688 def p_expr__binary_op(self, p):
689 """expr : expr STAR expr
701 | expr RIGHTSHIFT expr
702 | expr LEFTSHIFT expr"""
703 p[0] = ast.InfixOperatorExprAST(self, p[1], p[2], p[3])
706 def p_expr__unary_op(self, p):
710 | DASH expr %prec UMINUS"""
711 p[0] = ast.PrefixOperatorExprAST(self, p[1], p[2])
713 def p_expr__parens(self, p):
714 "aexpr
: '(' expr
')'"
717 def p_expr__is_valid_ptr(self, p):
718 "aexpr
: IS_VALID
'(' var
')'"
719 p[0] = ast.IsValidPtrExprAST(self, p[3], True)
721 def p_expr__is_invalid_ptr(self, p):
722 "aexpr
: IS_INVALID
'(' var
')'"
723 p[0] = ast.IsValidPtrExprAST(self, p[3], False)
725 def p_literal__string(self, p):
727 p[0] = ast.LiteralExprAST(self, p[1], "std
::string
")
729 def p_literal__number(self, p):
731 p[0] = ast.LiteralExprAST(self, p[1], "int")
733 def p_literal__float(self, p):
734 "literal
: FLOATNUMBER
"
735 p[0] = ast.LiteralExprAST(self, p[1], "int")
737 def p_literal__bool(self, p):
739 p[0] = ast.LiteralExprAST(self, p[1], "bool")
741 def p_enumeration(self, p):
742 "enumeration
: ident
':' ident
"
743 p[0] = ast.EnumExprAST(self, ast.TypeAST(self, p[1]), p[3])
747 p[0] = ast.VarExprAST(self, p[1])