[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.
|