Make .isa-file ##include file paths relative to including file.
authorSteve Reinhardt <stever@eecs.umich.edu>
Wed, 29 Mar 2006 03:29:42 +0000 (22:29 -0500)
committerSteve Reinhardt <stever@eecs.umich.edu>
Wed, 29 Mar 2006 03:29:42 +0000 (22:29 -0500)
Makes .isa files cleaner and simplifies scanner too.
Simplified scanner to work under both old and new versions of scons.

arch/SConscript:
    Simplify .isa scanner... seems to work with both scons 0.96.1 and 0.96.91 now.
    Assumes .isa ##include paths are relative to including file.
arch/alpha/isa/main.isa:
arch/mips/isa/formats/formats.isa:
arch/mips/isa/main.isa:
arch/sparc/isa/formats.isa:
arch/sparc/isa/main.isa:
    Make ##include paths relative to including file.
arch/isa_parser.py:
    Make ##include file paths relative to including file.
    Makes .isa files cleaner and simplifies scanner too.
    Partial rewrite of include-handling code to use cool re.sub() feature
    where you can specify a function to provide the replacement string.
    Minor cleanup of error-handling code.
    Also got rid of '#!' at top to make caller choose which python interpreter
    is used (since SPARC now requires 2.4 to build, we may need to do that via
    scons in the future).

--HG--
rename : arch/mips/isa/formats.isa => arch/mips/isa/formats/formats.isa
extra : convert_revision : 15a3920fa3aaf80cd94083eda853aa4e49425045

arch/SConscript
arch/alpha/isa/main.isa
arch/isa_parser.py
arch/mips/isa/formats.isa [deleted file]
arch/mips/isa/formats/formats.isa [new file with mode: 0644]
arch/mips/isa/main.isa
arch/sparc/isa/formats.isa
arch/sparc/isa/main.isa

index d88d10368fc9d5747db6976eaf163ad06a17c650..99c86156874961828aea005cb79574051a5c76d9 100644 (file)
@@ -100,18 +100,12 @@ for hdr in isa_switch_hdrs:
 #
 import SCons.Scanner
 
-def ISAScan():
-   return SCons.Scanner.Classic("ISAScan",
-                                "$ISASUFFIXES",
-                                "SRCDIR",
-                                '^[ \t]*##[ \t]*include[ \t]*"([^>"]+)"')
+isa_scanner = SCons.Scanner.Classic("ISAScan",
+                                    [".isa", ".ISA"],
+                                    "SRCDIR",
+                                    r'^\s*##include\s+"([\w/.-]*)"')
 
-def ISAPath(env, dir, target=None, source=None, a=None):
-   return (Dir(env['SRCDIR']), Dir('.'))   
-
-iscan = Scanner(function = ISAScan().scan, skeys = [".isa", ".ISA"],
-                path_function = ISAPath)
-env.Append(SCANNERS = iscan)
+env.Append(SCANNERS = isa_scanner)
 
 #
 # Now create a Builder object that uses isa_parser.py to generate C++
@@ -138,8 +132,7 @@ def isa_desc_emitter(target, source, env):
     return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source)
 
 # Pieces are in place, so create the builder.
-isa_desc_builder = Builder(action='$SOURCES $TARGET.dir $CPU_MODELS',
-                           source_scanner = iscan,
+isa_desc_builder = Builder(action='python $SOURCES $TARGET.dir $CPU_MODELS',
                            emitter = isa_desc_emitter)
 
 env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
index d4c744fbcb219f64280754e4e016245e23ab5e21..746fe776de3bc89323ff19b69c07daa3bd926d97 100644 (file)
@@ -418,31 +418,31 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{
 }};
 
 // Integer instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/int.isa"
+##include "int.isa"
 
 // Floating-point instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/fp.isa"
+##include "fp.isa"
 
 // Memory instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/mem.isa"
+##include "mem.isa"
 
 // Branch/jump instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/branch.isa"
+##include "branch.isa"
 
 // PAL instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/pal.isa"
+##include "pal.isa"
 
 // Opcdec fault instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/opcdec.isa"
+##include "opcdec.isa"
 
 // Unimplemented instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/unimp.isa"
+##include "unimp.isa"
 
 // Unknown instruction templates, formats, etc.
-##include "m5/arch/alpha/isa/unknown.isa"
+##include "unknown.isa"
 
 // Execution utility functions
-##include "m5/arch/alpha/isa/util.isa"
+##include "util.isa"
 
 // The actual decoder
-##include "m5/arch/alpha/isa/decoder.isa"
+##include "decoder.isa"
index 3f836ed7ebcb740acfd9625afc3d297cce67cf08..6fce783b1f3fc35a470cf50719db7a88fd017c36 100755 (executable)
@@ -1,5 +1,3 @@
-#! /usr/bin/env python
-
 # Copyright (c) 2003-2005 The Regents of The University of Michigan
 # All rights reserved.
 #
@@ -162,13 +160,12 @@ def t_CPPDIRECTIVE(t):
 
 def t_NEWFILE(t):
     r'^\#\#newfile\s+"[\w/.-]*"'
-    global fileNameStack
-    fileNameStack.append((t.value[11:-1], t.lineno))
+    fileNameStack.push((t.value[11:-1], t.lineno))
     t.lineno = 0
 
 def t_ENDFILE(t):
     r'^\#\#endfile'
-    (filename, t.lineno) = fileNameStack.pop()
+    (old_filename, t.lineno) = fileNameStack.pop()
 
 #
 # The functions t_NEWLINE, t_ignore, and t_error are
@@ -698,7 +695,7 @@ def p_error(t):
     if t:
         error(t.lineno, "syntax error at '%s'" % t.value)
     else:
-        error_bt(0, "unknown syntax error")
+        error(0, "unknown syntax error", True)
 
 # END OF GRAMMAR RULES
 #
@@ -896,6 +893,12 @@ formatStack = Stack(NoFormat())
 # The global default case stack.
 defaultStack = Stack( None )
 
+# Global stack that tracks current file and line number.
+# Each element is a tuple (filename, lineno) that records the
+# *current* filename and the line number in the *previous* file where
+# it was included.
+fileNameStack = Stack()
+
 ###################
 # Utility functions
 
@@ -932,25 +935,22 @@ def fixPythonIndentation(s):
     return s
 
 # Error handler.  Just call exit.  Output formatted to work under
-# Emacs compile-mode.  This function should be called when errors due
-# to user input are detected (as opposed to parser bugs).
-def error(lineno, string):
+# Emacs compile-mode.  Optional 'print_traceback' arg, if set to True,
+# prints a Python stack backtrace too (can be handy when trying to
+# debug the parser itself).
+def error(lineno, string, print_traceback = False):
     spaces = ""
     for (filename, line) in fileNameStack[0:-1]:
-        print spaces + "In file included from " + filename
+        print spaces + "In file included from " + filename + ":"
         spaces += "  "
-    # Uncomment the following line to get a Python stack backtrace for
-    # these errors too.  Can be handy when trying to debug the parser.
-    # traceback.print_exc()
-    sys.exit(spaces + "%s:%d: %s" % (fileNameStack[-1][0], lineno, string))
-
-# Like error(), but include a Python stack backtrace (for processing
-# Python exceptions).  This function should be called for errors that
-# appear to be bugs in the parser itself.
-def error_bt(lineno, string):
-    traceback.print_exc()
-    print >> sys.stderr, "%s:%d: %s" % (input_filename, lineno, string)
-    sys.exit(1)
+    # Print a Python stack backtrace if requested.
+    if (print_traceback):
+        traceback.print_exc()
+    if lineno != 0:
+        line_str = "%d:" % lineno
+    else:
+        line_str = ""
+    sys.exit(spaces + "%s:%s %s" % (fileNameStack[-1][0], line_str, string))
 
 
 #####################################################################
@@ -1070,7 +1070,7 @@ def buildOperandTypeMap(userDict, lineno):
             elif size == 64:
                 ctype = 'double'
         if ctype == '':
-            error(0, 'Unrecognized type description "%s" in userDict')
+            error(lineno, 'Unrecognized type description "%s" in userDict')
         operandTypeMap[ext] = (size, ctype, is_signed)
 
 #
@@ -1701,47 +1701,47 @@ def update_if_needed(file, contents):
         f.write(contents)
         f.close()
 
-# This regular expression matches include directives
+# This regular expression matches '##include' directives
 includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$',
                        re.MULTILINE)
 
-def preprocess_isa_desc(isa_desc):
+# Function to replace a matched '##include' directive with the
+# contents of the specified file (with nested ##includes replaced
+# recursively).  'matchobj' is an re match object (from a match of
+# includeRE) and 'dirname' is the directory relative to which the file
+# path should be resolved.
+def replace_include(matchobj, dirname):
+    fname = matchobj.group('filename')
+    full_fname = os.path.normpath(os.path.join(dirname, fname))
+    contents = '##newfile "%s"\n%s\n##endfile\n' % \
+               (full_fname, read_and_flatten(full_fname))
+    return contents
+
+# Read a file and recursively flatten nested '##include' files.
+def read_and_flatten(filename):
+    current_dir = os.path.dirname(filename)
+    try:
+        contents = open(filename).read()
+    except IOError:
+        error(0, 'Error including file "%s"' % filename)
+    fileNameStack.push((filename, 0))
     # Find any includes and include them
-    pos = 0
-    while 1:
-        m = includeRE.search(isa_desc, pos)
-        if not m:
-            break
-        filename = m.group('filename')
-        print 'Including file "%s"' % filename
-        try:
-            isa_desc = isa_desc[:m.start()] + \
-                       '##newfile "' + filename + '"\n' + \
-                       open(filename).read() + \
-                       '##endfile\n' + \
-                       isa_desc[m.end():]
-        except IOError:
-            error(0, 'Error including file "%s"' % (filename))
-        pos = m.start()
-    return isa_desc
+    contents = includeRE.sub(lambda m: replace_include(m, current_dir),
+                             contents)
+    fileNameStack.pop()
+    return contents
 
 #
 # Read in and parse the ISA description.
 #
 def parse_isa_desc(isa_desc_file, output_dir):
-    # set a global var for the input filename... used in error messages
-    global input_filename
-    input_filename = isa_desc_file
-    global fileNameStack
-    fileNameStack = [(input_filename, 1)]
-
-    # Suck the ISA description file in.
-    input = open(isa_desc_file)
-    isa_desc = input.read()
-    input.close()
-
-    # Perform Preprocessing
-    isa_desc = preprocess_isa_desc(isa_desc)
+    # Read file and (recursively) all included files into a string.
+    # PLY requires that the input be in a single string so we have to
+    # do this up front.
+    isa_desc = read_and_flatten(isa_desc_file)
+
+    # Initialize filename stack with outer file.
+    fileNameStack.push((isa_desc_file, 0))
 
     # Parse it.
     (isa_name, namespace, global_code, namespace_code) = yacc.parse(isa_desc)
diff --git a/arch/mips/isa/formats.isa b/arch/mips/isa/formats.isa
deleted file mode 100644 (file)
index f7a9e4c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// -*- mode:c++ -*-
-
-//Templates from this format are used later
-//Include the basic format
-##include "m5/arch/mips/isa/formats/basic.isa"
-
-//Include the basic format
-##include "m5/arch/mips/isa/formats/noop.isa"
-
-//Include utility formats/functions
-##include "m5/arch/mips/isa/formats/util.isa"
-
-//Include the cop0 formats
-##include "m5/arch/mips/isa/formats/cop0.isa"
-
-//Include the integer formats
-##include "m5/arch/mips/isa/formats/int.isa"
-
-//Include the floatOp format
-##include "m5/arch/mips/isa/formats/fp.isa"
-
-//Include the mem format
-##include "m5/arch/mips/isa/formats/mem.isa"
-
-//Include the trap format
-##include "m5/arch/mips/isa/formats/trap.isa"
-
-//Include the branch format
-##include "m5/arch/mips/isa/formats/branch.isa"
-
-//Include the noop format
-##include "m5/arch/mips/isa/formats/unimp.isa"
-
-//Include the noop format
-##include "m5/arch/mips/isa/formats/unknown.isa"
diff --git a/arch/mips/isa/formats/formats.isa b/arch/mips/isa/formats/formats.isa
new file mode 100644 (file)
index 0000000..7d493ff
--- /dev/null
@@ -0,0 +1,35 @@
+// -*- mode:c++ -*-
+
+//Templates from this format are used later
+//Include the basic format
+##include "basic.isa"
+
+//Include the basic format
+##include "noop.isa"
+
+//Include utility functions
+##include "util.isa"
+
+//Include the cop0 formats
+##include "cop0.isa"
+
+//Include the integer formats
+##include "int.isa"
+
+//Include the floatOp format
+##include "fp.isa"
+
+//Include the mem format
+##include "mem.isa"
+
+//Include the trap format
+##include "trap.isa"
+
+//Include the branch format
+##include "branch.isa"
+
+//Include the noop format
+##include "unimp.isa"
+
+//Include the noop format
+##include "unknown.isa"
index 411e398b49cb863e170ef5f3b988bcfcb71d2e20..01d81323e9a4eafb61af9dfa35c5e359929faea6 100644 (file)
@@ -26,7 +26,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-##include "m5/arch/mips/isa/includes.isa"
+##include "includes.isa"
 
 ////////////////////////////////////////////////////////////////////
 //
 namespace MipsISA;
 
 //Include the bitfield definitions
-##include "m5/arch/mips/isa/bitfields.isa"
+##include "bitfields.isa"
 
 //Include the operand_types and operand definitions
-##include "m5/arch/mips/isa/operands.isa"
+##include "operands.isa"
 
 //Include the base class for mips instructions, and some support code
-##include "m5/arch/mips/isa/base.isa"
+##include "base.isa"
 
 //Include the definitions for the instruction formats
-##include "m5/arch/mips/isa/formats.isa"
+##include "formats/formats.isa"
 
 //Include the decoder definition
-##include "m5/arch/mips/isa/decoder.isa"
+##include "decoder.isa"
index 9310ba3d3d387f91fc42b944fa6584f796131fb2..8683f5e0168a35aef7efe4388cb269172feab90d 100644 (file)
@@ -1,28 +1,28 @@
 //Include the basic format
 //Templates from this format are used later
-##include "m5/arch/sparc/isa/formats/basic.isa"
+##include "formats/basic.isa"
 
 //Include the integerOp and integerOpCc format
-##include "m5/arch/sparc/isa/formats/integerop.isa"
+##include "formats/integerop.isa"
 
 //Include the memory format
-##include "m5/arch/sparc/isa/formats/mem.isa"
+##include "formats/mem.isa"
 
 //Include the compare and swap format
-##include "m5/arch/sparc/isa/formats/cas.isa"
+##include "formats/cas.isa"
 
 //Include the trap format
-##include "m5/arch/sparc/isa/formats/trap.isa"
+##include "formats/trap.isa"
 
 //Include the "unknown" format
-##include "m5/arch/sparc/isa/formats/unknown.isa"
+##include "formats/unknown.isa"
 
 //Include the priveleged mode format
-##include "m5/arch/sparc/isa/formats/priv.isa"
+##include "formats/priv.isa"
 
 //Include the branch format
-##include "m5/arch/sparc/isa/formats/branch.isa"
+##include "formats/branch.isa"
 
 //Include the noop format
-##include "m5/arch/sparc/isa/formats/noop.isa"
+##include "formats/noop.isa"
 
index ab0290d58fdf7fd11586a2d61a04fadf84ec9647..35167d6b7f00c79e71e552dc6b79190586cbb44d 100644 (file)
@@ -26,7 +26,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-##include "m5/arch/sparc/isa/includes.isa"
+##include "includes.isa"
 
 ////////////////////////////////////////////////////////////////////
 //
 namespace SparcISA;
 
 //Include the bitfield definitions
-##include "m5/arch/sparc/isa/bitfields.isa"
+##include "bitfields.isa"
 
 //Include the operand_types and operand definitions
-##include "m5/arch/sparc/isa/operands.isa"
+##include "operands.isa"
 
 //Include the base class for sparc instructions, and some support code
-##include "m5/arch/sparc/isa/base.isa"
+##include "base.isa"
 
 //Include the definitions for the instruction formats
-##include "m5/arch/sparc/isa/formats.isa"
+##include "formats.isa"
 
 //Include the decoder definition
-##include "m5/arch/sparc/isa/decoder.isa"
+##include "decoder.isa"