|  | # -*- mode:python -*- | 
|  |  | 
|  | # Copyright (c) 2006 The Regents of The University of Michigan | 
|  | # All rights reserved. | 
|  | # | 
|  | # Redistribution and use in source and binary forms, with or without | 
|  | # modification, are permitted provided that the following conditions are | 
|  | # met: redistributions of source code must retain the above copyright | 
|  | # notice, this list of conditions and the following disclaimer; | 
|  | # redistributions in binary form must reproduce the above copyright | 
|  | # notice, this list of conditions and the following disclaimer in the | 
|  | # documentation and/or other materials provided with the distribution; | 
|  | # neither the name of the copyright holders nor the names of its | 
|  | # contributors may be used to endorse or promote products derived from | 
|  | # this software without specific prior written permission. | 
|  | # | 
|  | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
|  | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
|  | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
|  | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
|  | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|  | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|  | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | # | 
|  | # Authors: Steve Reinhardt | 
|  |  | 
|  | import sys | 
|  | import os | 
|  | import re | 
|  |  | 
|  | Import('*') | 
|  |  | 
|  | ################################################################# | 
|  | # | 
|  | # ISA "switch header" generation. | 
|  | # | 
|  | # Auto-generate arch headers that include the right ISA-specific | 
|  | # header based on the setting of THE_ISA preprocessor variable. | 
|  | # | 
|  | ################################################################# | 
|  |  | 
|  | # List of headers to generate | 
|  | isa_switch_hdrs = Split(''' | 
|  | decoder.hh | 
|  | interrupts.hh | 
|  | isa.hh | 
|  | isa_traits.hh | 
|  | kernel_stats.hh | 
|  | locked_mem.hh | 
|  | microcode_rom.hh | 
|  | mmapped_ipr.hh | 
|  | mt.hh | 
|  | process.hh | 
|  | pseudo_inst.hh | 
|  | registers.hh | 
|  | remote_gdb.hh | 
|  | stacktrace.hh | 
|  | tlb.hh | 
|  | types.hh | 
|  | utility.hh | 
|  | vtophys.hh | 
|  | ''') | 
|  |  | 
|  | # Set up this directory to support switching headers | 
|  | make_switching_dir('arch', isa_switch_hdrs, env) | 
|  |  | 
|  | ################################################################# | 
|  | # | 
|  | # Include architecture-specific files. | 
|  | # | 
|  | ################################################################# | 
|  |  | 
|  | # | 
|  | # Build a SCons scanner for ISA files | 
|  | # | 
|  | import SCons.Scanner | 
|  |  | 
|  | isa_scanner = SCons.Scanner.Classic("ISAScan", | 
|  | [".isa", ".ISA"], | 
|  | "SRCDIR", | 
|  | r'^\s*##include\s+"([\w/.-]*)"') | 
|  |  | 
|  | env.Append(SCANNERS = isa_scanner) | 
|  |  | 
|  | # | 
|  | # Now create a Builder object that uses isa_parser.py to generate C++ | 
|  | # output from the ISA description (*.isa) files. | 
|  | # | 
|  |  | 
|  | isa_parser = File('isa_parser.py') | 
|  |  | 
|  | # The emitter patches up the sources & targets to include the | 
|  | # autogenerated files as targets and isa parser itself as a source. | 
|  | def isa_desc_emitter(target, source, env): | 
|  | # List the isa parser as a source. | 
|  | source += [ | 
|  | isa_parser, | 
|  | Value("ExecContext"), | 
|  | ] | 
|  |  | 
|  | # Specify different targets depending on if we're running the ISA | 
|  | # parser for its dependency information, or for the generated files. | 
|  | # (As an optimization, the ISA parser detects the useless second run | 
|  | # and skips doing any work, if the first run was performed, since it | 
|  | # always generates all its files). The way we track this in SCons is the | 
|  | # <arch>_isa_outputs value in the environment (env). If it's unset, we | 
|  | # don't know what the dependencies are so we ask for generated/inc.d to | 
|  | # be generated so they can be acquired. If we know what they are, then | 
|  | # it's because we've already processed inc.d and then claim that our | 
|  | # outputs (targets) will be thus. | 
|  | isa = env['TARGET_ISA'] | 
|  | key = '%s_isa_outputs' % isa | 
|  | if key in env: | 
|  | targets = [ os.path.join('generated', f) for f in env[key] ] | 
|  | else: | 
|  | targets = [ os.path.join('generated','inc.d') ] | 
|  |  | 
|  | def prefix(s): | 
|  | return os.path.join(target[0].dir.up().abspath, s) | 
|  |  | 
|  | return [ prefix(t) for t in targets ], source | 
|  |  | 
|  | ARCH_DIR = Dir('.') | 
|  |  | 
|  | # import ply here because SCons screws with sys.path when performing actions. | 
|  | import ply | 
|  |  | 
|  | def isa_desc_action_func(target, source, env): | 
|  | # Add the current directory to the system path so we can import files | 
|  | sys.path[0:0] = [ ARCH_DIR.srcnode().abspath ] | 
|  | import isa_parser | 
|  |  | 
|  | # Skip over the ISA description itself and the parser to the CPU models. | 
|  | models = [ s.get_contents() for s in source[2:] ] | 
|  | parser = isa_parser.ISAParser(target[0].dir.abspath) | 
|  | parser.parse_isa_desc(source[0].abspath) | 
|  | isa_desc_action = MakeAction(isa_desc_action_func, Transform("ISA DESC", 1)) | 
|  |  | 
|  | # Also include the CheckerCPU as one of the models if it is being | 
|  | # enabled via command line. | 
|  | isa_desc_builder = Builder(action=isa_desc_action, emitter=isa_desc_emitter) | 
|  |  | 
|  | env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) | 
|  |  | 
|  | # The ISA is generated twice: the first time to find out what it generates, | 
|  | # and the second time to make scons happy by telling the ISADesc builder | 
|  | # what it will make before it builds it. | 
|  | def scan_isa_deps(target, source, env): | 
|  | # Process dependency file generated by the ISA parser -- | 
|  | # add the listed files to the dependency tree of the build. | 
|  | source = source[0] | 
|  | archbase = source.dir.up().path | 
|  |  | 
|  | try: | 
|  | depfile = open(source.abspath, 'r') | 
|  | except: | 
|  | print "scan_isa_deps: Can't open ISA deps file '%s' in %s" % \ | 
|  | (source.path,os.getcwd()) | 
|  | raise | 
|  |  | 
|  | # Scan through the lines | 
|  | targets = {} | 
|  | for line in depfile: | 
|  | # Read the dependency line with the format | 
|  | # <target file>: [ <dependent file>* ] | 
|  | m = re.match(r'^\s*([^:]+\.([^\.:]+))\s*:\s*(.*)', line) | 
|  | assert(m) | 
|  | targ, extn = m.group(1,2) | 
|  | deps = m.group(3).split() | 
|  |  | 
|  | files = [ targ ] + deps | 
|  | for f in files: | 
|  | targets[f] = True | 
|  | # Eliminate unnecessary re-generation if we already generated it | 
|  | env.Precious(os.path.join(archbase, 'generated', f)) | 
|  |  | 
|  | files = [ os.path.join(archbase, 'generated', f) for f in files ] | 
|  |  | 
|  | if extn == 'cc': | 
|  | Source(os.path.join(archbase,'generated', targ)) | 
|  | depfile.close() | 
|  | env[env['TARGET_ISA'] + '_isa_outputs'] = targets.keys() | 
|  |  | 
|  | isa = env.ISADesc(os.path.join(archbase,'isa','main.isa')) | 
|  | for t in targets: | 
|  | env.Depends('#all-isas', isa) | 
|  |  | 
|  | env.Append(BUILDERS = {'ScanISA' : | 
|  | Builder(action=MakeAction(scan_isa_deps, | 
|  | Transform("NEW DEPS", 1)))}) | 
|  |  | 
|  | DebugFlag('IntRegs') | 
|  | DebugFlag('FloatRegs') | 
|  | DebugFlag('CCRegs') | 
|  | DebugFlag('MiscRegs') | 
|  | CompoundFlag('Registers', [ 'IntRegs', 'FloatRegs', 'CCRegs', 'MiscRegs' ]) |