[fbt-commit] SF.net SVN: fbt:[91] trunk/bin/parse_verilog.py
Status: Beta
Brought to you by:
dave_infj
From: <dav...@us...> - 2010-04-12 16:55:50
|
Revision: 91 http://fbt.svn.sourceforge.net/fbt/?rev=91&view=rev Author: dave_infj Date: 2010-04-12 16:55:42 +0000 (Mon, 12 Apr 2010) Log Message: ----------- Add preliminary Verilog support Modified Paths: -------------- trunk/bin/parse_verilog.py Modified: trunk/bin/parse_verilog.py =================================================================== --- trunk/bin/parse_verilog.py 2010-04-09 16:29:04 UTC (rev 90) +++ trunk/bin/parse_verilog.py 2010-04-12 16:55:42 UTC (rev 91) @@ -30,8 +30,10 @@ from __future__ import with_statement from util import * -import sys -import re +import pyparsing +from pyparsing import Literal, CaselessKeyword, Word, ZeroOrMore, OneOrMore, Combine, \ + Group, Optional, Forward, ParseException, alphas, alphanums, printables, \ + restOfLine, cppStyleComment, oneOf, nestedExpr, lineno, col, line import DepList import comp_filter @@ -42,9 +44,162 @@ Determine dependencies for a given file (verilog mode) """ - sys.stderr.write('%s:%s: warning: unsupported verilog source ignored.\n' % - ( prog_name(), relpath(hdl_src) )) + global parser + + global _src + _src = hdl_src # for handle_syntax_err - return DepList.DepList() + # Parse the file + try: + results = parser.parseFile( hdl_src, parseAll = True ) + except pyparsing.ParseException, e: + raise Panic("""\ +%%s:%d: error: Parse exception: + %s +%s +%s^""" % (relpath(hdl_src), + e.lineno, + e, + e.line, + ' '*(e.col-1) + ) + ) + + # Process the results; make and return the dependency list + dep_list = DepList.DepList() + # Each element of results is formatted as follows: + # 'module', <mod_name>, [<entity, instance>, ...], 'endmodule' + for mod_parse_data in results: + ent = mod_parse_data[1] + if ent in dep_list: + raise Panic( "duplicate entity %s declaration found in %s (previous in %s)" % ( + ent, relpath(hdl_src), relpath(dep_list[ent][0]) + ) + ) + dep_list.add_dep( ent, hdl_src, [ent for ent, inst in mod_parse_data[2:-1] + if comp_filter.accept(ent)] ) + + return dep_list + + +def handle_syntax_err( s, loc, toks ): + """ + Handle syntax errors + """ + + global _src + + raise Panic("""\ +%s:%d: error: unexpected syntax: + +%s +%s^ + +Check all of the syntactically required components for this declaration are +both present and free of syntax errors. eg, 'module' must have a valid set of +port declarations. + +If you believe this is genuinely valid Verilog, see the documentation under +Verilog support. +""" % ( relpath(_src), + lineno( loc, s ), + line( loc, s ), + ' '*(col( loc, s )-1) + ) + ) + + +def verilog_grammar(): + """ + Define the partial grammar used to parse Verilog sources + """ + + # Compiler directives (we don't care what they are, therefore we don't care about their + # format.) + directive = Group( Combine( "`" + \ + oneOf("define undef ifdef else endif default_nettype " + "include resetall timescale unconnected_drive " + "nounconnected_drive celldefine endcelldefine") + \ + restOfLine ) ) + + # Various character classes + printable_less_parens = "".join([x for x in printables if x not in ['(',')']]) + printable_less_semi = "".join([x for x in printables if x not in [';']]) + + # word: Any non-whitespace + word = Word( printables ) + + # object indentifiers + ident = Word( alphanums+'_' ) + + # Keywords + begin_kw = CaselessKeyword('begin') + end_kw = CaselessKeyword('end') + func_begin = CaselessKeyword('function') + func_end = CaselessKeyword('endfunction') + module_kw = CaselessKeyword( 'module' ) | CaselessKeyword( 'primitive' ) + endmodule_kw= CaselessKeyword('endmodule') | CaselessKeyword('endprimitive') + + # () groups (with recursion) + paren_group = nestedExpr( Literal('('), Literal(')'), + content=OneOrMore( Word(printable_less_parens) ) + ) + + # begin/end blocks + begin_block = nestedExpr( begin_kw, end_kw, + content=OneOrMore( ~begin_kw + ~end_kw + word ) + ) + + # Functions + function = nestedExpr( func_begin, func_end, + content=OneOrMore( ~func_begin + ~func_end + word ) + ) + + # Statements, block statements and compound statements + statement = Forward() + simple_stmt = OneOrMore(~endmodule_kw + Word(printable_less_semi)) + Literal(';') + compnd_stmt = ( (CaselessKeyword('always') + Literal('@')) | # Special case: always @(...) + Word(alphas) # Any other case: kw( ... ) + ) + paren_group + statement + statement << Group( ~endmodule_kw + (compnd_stmt | begin_block | simple_stmt) ) + + # Module and instance generics + generics = Optional( Literal('#') + paren_group ) + + # Module instances + instance = Group( ident + # Entity name + generics.suppress() + # Optional generics + ident + # Instance name + paren_group.suppress() + # Ports + Literal( ';' ).suppress() # terminal ; + ) + + # Module definitions. For these purposes, we can assume UDPs are the same as modules. + mod_header = (module_kw + # Module keyword + ident + # Entity's name + generics.suppress() + # Optional generic mappings + paren_group.suppress() + # Port mappings + Literal(';').suppress() # Terminal ; + ) + mod_body = ZeroOrMore( instance | # Entity instantiation + function.suppress() | # Function declarations + statement.suppress() # Compound and simple statements + ) + mod_footer = endmodule_kw # End module keyword + syntax_err = OneOrMore( Word(printables) ).setParseAction( handle_syntax_err ) + module = Group( (mod_header | syntax_err) + + mod_body + + (mod_footer | syntax_err) + ) + + v = ZeroOrMore( module ) + + # No comments, no compiler directives (which can appear anywhere in the input) + v.ignore( cppStyleComment ) + v.ignore( directive ) + + return v + +parser = verilog_grammar() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |