SConscript (12109:f29e9c5418aa) SConscript (12222:6db0fc7407a5)
1# -*- mode:python -*-
2
3# Copyright (c) 2016 ARM Limited
4# All rights reserved.
5#
6# The license below extends only to copyright in the software and shall
7# not be construed as granting a license to any other intellectual
8# property including but not limited to intellectual property relating

--- 83 unchanged lines hidden (view full) ---

92# Include architecture-specific files.
93#
94#################################################################
95
96#
97# Build a SCons scanner for ISA files
98#
99import SCons.Scanner
1# -*- mode:python -*-
2
3# Copyright (c) 2016 ARM Limited
4# All rights reserved.
5#
6# The license below extends only to copyright in the software and shall
7# not be construed as granting a license to any other intellectual
8# property including but not limited to intellectual property relating

--- 83 unchanged lines hidden (view full) ---

92# Include architecture-specific files.
93#
94#################################################################
95
96#
97# Build a SCons scanner for ISA files
98#
99import SCons.Scanner
100import SCons.Tool
100
101
101isa_scanner = SCons.Scanner.Classic("ISAScan",
102 [".isa", ".ISA"],
103 "SRCDIR",
104 r'^\s*##include\s+"([\w/.-]*)"')
102scanner = SCons.Scanner.Classic("ISAScan",
103 [".isa", ".ISA"],
104 "SRCDIR",
105 r'^\s*##include\s+"([\w/.-]*)"')
105
106
106env.Append(SCANNERS = isa_scanner)
107env.Append(SCANNERS=scanner)
107
108
109# Tell scons that when it sees a cc.inc file, it should scan it for includes.
110SCons.Tool.SourceFileScanner.add_scanner('.cc.inc', SCons.Tool.CScanner)
111
108#
109# Now create a Builder object that uses isa_parser.py to generate C++
110# output from the ISA description (*.isa) files.
111#
112
112#
113# Now create a Builder object that uses isa_parser.py to generate C++
114# output from the ISA description (*.isa) files.
115#
116
113isa_parser = File('isa_parser.py')
117parser_py = File('isa_parser.py')
118micro_asm_py = File('micro_asm.py')
114
119
115# The emitter patches up the sources & targets to include the
116# autogenerated files as targets and isa parser itself as a source.
117def isa_desc_emitter(target, source, env):
118 # List the isa parser as a source.
119 source += [
120 isa_parser,
121 Value("ExecContext"),
122 ]
123
124 # Specify different targets depending on if we're running the ISA
125 # parser for its dependency information, or for the generated files.
126 # (As an optimization, the ISA parser detects the useless second run
127 # and skips doing any work, if the first run was performed, since it
128 # always generates all its files). The way we track this in SCons is the
129 # <arch>_isa_outputs value in the environment (env). If it's unset, we
130 # don't know what the dependencies are so we ask for generated/inc.d to
131 # be generated so they can be acquired. If we know what they are, then
132 # it's because we've already processed inc.d and then claim that our
133 # outputs (targets) will be thus.
134 isa = env['TARGET_ISA']
135 key = '%s_isa_outputs' % isa
136 if key in env:
137 targets = [ os.path.join('generated', f) for f in env[key] ]
138 else:
139 targets = [ os.path.join('generated','inc.d') ]
140
141 def prefix(s):
142 return os.path.join(target[0].dir.up().abspath, s)
143
144 return [ prefix(t) for t in targets ], source
145
146ARCH_DIR = Dir('.')
147
148# import ply here because SCons screws with sys.path when performing actions.
149import ply
150
120# import ply here because SCons screws with sys.path when performing actions.
121import ply
122
151def isa_desc_action_func(target, source, env):
152 # Add the current directory to the system path so we can import files
153 sys.path[0:0] = [ ARCH_DIR.srcnode().abspath ]
123def run_parser(target, source, env):
124 # Add the current directory to the system path so we can import files.
125 sys.path[0:0] = [ parser_py.dir.abspath ]
154 import isa_parser
155
126 import isa_parser
127
156 # Skip over the ISA description itself and the parser to the CPU models.
157 models = [ s.get_contents() for s in source[2:] ]
158 parser = isa_parser.ISAParser(target[0].dir.abspath)
159 parser.parse_isa_desc(source[0].abspath)
128 parser = isa_parser.ISAParser(target[0].dir.abspath)
129 parser.parse_isa_desc(source[0].abspath)
160isa_desc_action = MakeAction(isa_desc_action_func, Transform("ISA DESC", 1))
161
130
162# Also include the CheckerCPU as one of the models if it is being
163# enabled via command line.
164isa_desc_builder = Builder(action=isa_desc_action, emitter=isa_desc_emitter)
131desc_action = MakeAction(run_parser, Transform("ISA DESC", 1))
165
132
166env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
133IsaDescBuilder = Builder(action=desc_action)
167
134
168# The ISA is generated twice: the first time to find out what it generates,
169# and the second time to make scons happy by telling the ISADesc builder
170# what it will make before it builds it.
171def scan_isa_deps(target, source, env):
172 # Process dependency file generated by the ISA parser --
173 # add the listed files to the dependency tree of the build.
174 source = source[0]
175 archbase = source.dir.up().path
176
135
177 try:
178 depfile = open(source.abspath, 'r')
179 except:
180 print "scan_isa_deps: Can't open ISA deps file '%s' in %s" % \
181 (source.path,os.getcwd())
182 raise
136# ISAs should use this function to set up an IsaDescBuilder and not try to
137# set one up manually.
138def ISADesc(desc, decoder_splits=1, exec_splits=1):
139 '''Set up a builder for an ISA description.
183
140
184 # Scan through the lines
185 targets = {}
186 for line in depfile:
187 # Read the dependency line with the format
188 # <target file>: [ <dependent file>* ]
189 m = re.match(r'^\s*([^:]+\.([^\.:]+))\s*:\s*(.*)', line)
190 assert(m)
191 targ, extn = m.group(1,2)
192 deps = m.group(3).split()
141 The decoder_splits and exec_splits parameters let us determine what
142 files the isa parser is actually going to generate. This needs to match
143 what files are actually generated, and there's no specific check for that
144 right now.
193
145
194 files = [ targ ] + deps
195 for f in files:
196 targets[f] = True
197 # Eliminate unnecessary re-generation if we already generated it
198 env.Precious(os.path.join(archbase, 'generated', f))
146 If the parser itself is responsible for generating a list of its products
147 and their dependencies, then using that output to set up the right
148 dependencies. This is what we used to do. The problem is that scons
149 fundamentally doesn't support using a build product to affect its graph
150 of possible products, dependencies, builders, etc. There are a couple ways
151 to work around that limitation.
199
152
200 files = [ os.path.join(archbase, 'generated', f) for f in files ]
153 One option is to compute dependencies while the build phase of scons is
154 running. That method can be quite complicated and cumbersome, because we
155 have to make sure our modifications are made before scons tries to
156 consume them. There's also no guarantee that this mechanism will work since
157 it subverts scons expectations and changes things behind its back. This
158 was implemented previously and constrained the builds parallelism
159 significantly.
201
160
202 if extn == 'cc':
203 Source(os.path.join(archbase,'generated', targ))
204 depfile.close()
205 env[env['TARGET_ISA'] + '_isa_outputs'] = targets.keys()
161 Another option would be to recursively call scons to have it update the
162 list of products/dependencies during the setup phase of this invocation of
163 scons. The problem with that is that it would be very difficult to make
164 the sub-invocation of scons observe the options passed to the primary one
165 in all possible cases, or to even determine conclusively what the name of
166 the scons executable is in the first place.
206
167
207 isa = env.ISADesc(os.path.join(archbase,'isa','main.isa'))
208 for t in targets:
209 env.Depends('#all-isas', isa)
168 Possible future changes to the isa parser might make it easier to
169 determine what files it would generate, perhaps because there was a more
170 direct correspondence between input files and output files. Or, if the
171 parser could run quickly and determine what its output files would be
172 without having do actually generate those files, then it could be run
173 unconditionally without slowing down all builds or touching the output
174 files unnecessarily.
175 '''
176 generated_dir = File(desc).dir.up().Dir('generated')
177 def gen_file(name):
178 return generated_dir.File(name)
210
179
211env.Append(BUILDERS = {'ScanISA' :
212 Builder(action=MakeAction(scan_isa_deps,
213 Transform("NEW DEPS", 1)))})
180 gen = []
181 def add_gen(name):
182 gen.append(gen_file(name))
214
183
184 # Tell scons about the various files the ISA parser will generate.
185 add_gen('decoder-g.cc.inc')
186 add_gen('decoder-ns.cc.inc')
187 add_gen('decode-method.cc.inc')
188
189 add_gen('decoder.hh')
190 add_gen('decoder-g.hh.inc')
191 add_gen('decoder-ns.hh.inc')
192
193 add_gen('exec-g.cc.inc')
194 add_gen('exec-ns.cc.inc')
195
196 add_gen('max_inst_regs.hh')
197
198
199 # These generated files are also top level sources.
200 def source_gen(name):
201 add_gen(name)
202 Source(gen_file(name))
203
204 source_gen('decoder.cc')
205
206 if decoder_splits == 1:
207 source_gen('inst-constrs.cc')
208 else:
209 for i in range(1, decoder_splits + 1):
210 source_gen('inst-constrs-%d.cc' % i)
211
212 if exec_splits == 1:
213 source_gen('generic_cpu_exec.cc')
214 else:
215 for i in range(1, exec_splits + 1):
216 source_gen('generic_cpu_exec_%d.cc' % i)
217
218 # Actually create the builder.
219 sources = [desc, parser_py, micro_asm_py]
220 IsaDescBuilder(target=gen, source=sources, env=env)
221 return gen
222
223Export('ISADesc')
224
215DebugFlag('IntRegs')
216DebugFlag('FloatRegs')
217DebugFlag('VecRegs')
218DebugFlag('CCRegs')
219DebugFlag('MiscRegs')
220CompoundFlag('Registers', [ 'IntRegs', 'FloatRegs', 'CCRegs', 'MiscRegs' ])
225DebugFlag('IntRegs')
226DebugFlag('FloatRegs')
227DebugFlag('VecRegs')
228DebugFlag('CCRegs')
229DebugFlag('MiscRegs')
230CompoundFlag('Registers', [ 'IntRegs', 'FloatRegs', 'CCRegs', 'MiscRegs' ])