| # -*- 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' ]) |