1 # Copyright 2019 Google, Inc.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met: redistributions of source code must retain the above copyright
6 # notice, this list of conditions and the following disclaimer;
7 # redistributions in binary form must reproduce the above copyright
8 # notice, this list of conditions and the following disclaimer in the
9 # documentation and/or other materials provided with the distribution;
10 # neither the name of the copyright holders nor the names of its
11 # contributors may be used to endorse or promote products derived from
12 # this software without specific prior written permission.
14 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 from __future__ import print_function
32 from m5.util.terminal import termcap
33 from m5.util.grammar import Grammar
35 from gem5_scons import Transform
39 if env['USE_ARM_FASTMODEL']:
40 if not env['USE_SYSTEMC']:
41 print(termcap.Yellow + termcap.Bold +
42 'Warning: ARM Fast Models require systemc support' +
44 env['USE_ARM_FASTMODEL'] = False
47 if not env['USE_ARM_FASTMODEL']:
51 systemc_home = Dir('#/src/systemc/ext/systemc_home')
52 env['ENV']['SYSTEMC_HOME'] = systemc_home.abspath
54 def extract_var(name):
56 print(termcap.Red + termcap.Bold +
57 ('Error: %s is not set' % name) +
60 print('%s = %s' % (name, env[name]))
61 # Make sure the value of this variable shows up as an environment variable
62 # for commands scons runs.
63 env['ENV'][name] = env[name]
66 pvlib_home, maxcore_home, armlmd_license_file = \
67 list(map(extract_var, ('PVLIB_HOME', 'MAXCORE_HOME',
68 'ARMLMD_LICENSE_FILE')))
70 pvlib_home = Dir(pvlib_home)
71 maxcore_home = Dir(maxcore_home)
72 armlmd_license_file = File(armlmd_license_file)
75 pvlib_flavor = env['PVLIB_FLAVOR']
76 pvlib_lib_dir = pvlib_home.Dir('lib').Dir(pvlib_flavor)
78 simulation_engine_name = 'libMAXCOREInitSimulationEngine.3.so'
79 simulation_engine_lib = pvlib_lib_dir.File(simulation_engine_name)
82 def staticify(env, name):
83 ''' Check for a static version of the library named 'name', and if it
84 exists return a File node for it explicitly. Otherwise pass 'name'
85 through for normal processing.'''
87 static_name = env.subst('${LIBPREFIX}' + name + '${LIBSUFFIX}')
89 for path in env.Flatten(env['LIBPATH']):
90 full_name = Dir(path).File(static_name).get_abspath()
91 if os.path.isfile(full_name):
92 return File(full_name)
97 # Adjust the build environment to support building in Fast Models.
99 env.Append(CCFLAGS='-pthread')
102 pvlib_home.Dir('include/fmruntime'),
103 pvlib_home.Dir('include/fmruntime/eslapi'),
104 pvlib_home.Dir('Iris/include'),
106 systemc_home.Dir('include'),
108 maxcore_home.Dir('AMBA-PV/include'),
110 env.Append(CPPPATH=cpppaths)
114 pvlib_home.Dir('Iris').Dir(pvlib_flavor),
116 env.Append(LIBPATH=lib_paths)
117 env.Append(RPATH=lib_paths)
128 env.Append(LIBS=list(staticify(env, lib) for lib in libs))
131 class ProjectFileParser(Grammar):
133 def __init__(self, is_object):
134 self.is_object = is_object
137 return self._to_str(0)
139 class StringParam(Param):
140 def __init__(self, name, value):
141 super(ProjectFileParser.StringParam, self).__init__(
146 def _to_str(self, indent):
147 indent_str = " " * indent
148 return indent_str + self.name + ' = \"' + self.value + '\"'
150 class ObjectParam(Param):
151 def __init__(self, type_name, name, params):
152 super(ProjectFileParser.ObjectParam, self).__init__(
154 self.type_name = type_name
158 def _to_str(self, indent):
159 indent_str = " " * indent
160 val = indent_str + self.type_name
161 if self.name is not None:
162 val += ' "' + self.name + '"'
163 val += "\n" + indent_str + "{\n"
164 for param in self.params:
165 val += param._to_str(indent + 1) + "\n"
166 val += indent_str + "}"
187 t_ID = r'[A-Za-z_]\w*'
189 def t_STRLIT(self, t):
192 t.value = t.value[1:-1]
193 t.lexer.lineno += t.value.count('\n')
201 def t_NEWLINE(self, t):
203 t.lexer.lineno += t.value.count('\n')
211 def p_object(self, t):
212 'object : object_heading LBRACE params RBRACE'
213 t[0] = self.ObjectParam(t[1][0], t[1][1], t[3])
215 def p_object_heading_0(self, t):
216 'object_heading : ID STRLIT'
219 def p_object_heading_1(self, t):
220 'object_heading : ID'
223 def p_params_0(self, t):
227 def p_params_1(self, t):
228 'params : param params'
231 def p_param_0(self, t):
232 'param : ID EQUALS STRLIT SEMI'
233 t[0] = self.StringParam(t[1], t[3])
235 def p_param_1(self, t):
240 class ArmFastModelComponent(object):
241 def __init__(self, project_file, *extra_deps):
242 project_file = File(project_file)
243 project_file_dir = project_file.Dir('.')
245 parser = ProjectFileParser()
246 proj = parser.parse_file(project_file.srcnode().abspath)
248 # Top level component.
253 # Scan for particular properties of the project.
254 for param in proj.params:
255 if not param.is_object:
256 if param.name == 'TOP_LEVEL_COMPONENT':
258 elif param.name == 'ACTIVE_CONFIG_LINUX':
259 config_name = param.value
261 assert tlc is not None and config_name is not None
263 simgen_dir = project_file_dir.Dir(config_name)
265 def simgen_static(name):
266 return simgen_dir.File(env.subst(
267 '${LIBPREFIX}%s${LIBSUFFIX}' % name))
269 def simgen_shared(name):
270 return simgen_dir.File(env.subst(
271 '${SHLIBPREFIX}%s${SHLIBSUFFIX}' % name))
274 'scx-%s-%s' % (tlc, config_name),
278 '%s-%s' % (tlc, config_name),
281 static_lib_nodes = map(simgen_static, static_libs)
282 shared_lib_nodes = map(simgen_shared, shared_libs)
283 # We need to use the static libraries as files so that the linker
284 # doesn't use the shared versions of them instead. We need to use
285 # the shared libraries by name so that the linker will apply RPATH
286 # and be able to find them at run time. If a shared libary includes
287 # a path, the dynamic linker will apparently ignore RPATH when looking
289 lib_nodes = static_lib_nodes + shared_lib_nodes
291 gen_dir = simgen_dir.Dir('gen')
293 header = gen_dir.File('scx_evs_%s.h' % tlc)
295 self.headers = [header]
296 self.headerpaths = [gen_dir]
297 self.libs = static_lib_nodes + shared_libs
298 self.libpaths = [simgen_dir]
299 self.rpaths = [simgen_dir]
301 simgen_cmd = env.subst('${SIMGEN} -p %s --configuration %s -b ' +
302 '--verbose off --num-build-cpus 100 --build-dir %s') % \
303 (project_file.srcnode().abspath, config_name, simgen_dir.abspath)
304 if not GetOption('verbose'):
305 simgen_cmd += ' > /dev/null'
306 simgen_action = MakeAction(simgen_cmd, Transform('SIMGEN'))
307 sources = [project_file]
308 sources.extend(extra_deps)
309 env.Command(lib_nodes + self.headers, sources, simgen_action)
311 def prepare_env(self, env):
312 env.Append(LIBPATH=self.libpaths)
313 env.AddLocalRPATH(*self.rpaths)
314 env.Append(CPPPATH=self.headerpaths)
315 env.Prepend(LIBS=self.libs)
318 class ArmFastModelBin(Executable):
319 def __init__(self, target, *components_and_sources):
321 return isinstance(x, ArmFastModelComponent)
323 def not_component(x):
324 return not is_component(x)
326 components = list(filter(is_component, components_and_sources))
327 sources = list(filter(not_component, components_and_sources))
329 self.components = components
330 super(ArmFastModelBin, self).__init__(target, *sources)
333 def declare_all(cls, env):
335 env.Prepend(LIBS=env['STATIC_LIB'][0])
336 super(ArmFastModelBin, cls).declare_all(env)
338 def declare(self, env):
341 sources = list(self.sources)
342 for f in self.filters:
343 sources += Source.all.apply_filter(f)
345 objs = self.srcs_to_objs(env, sources)
346 objs = objs + env['MAIN_OBJS']
348 for component in self.components:
349 component.prepare_env(env)
351 binary = super(ArmFastModelBin, self).declare(env, objs)[0]
353 # We need a copy of the simulation engine lib alongside the executable
354 # so that the license check works properly.
355 local_engine = binary.File(simulation_engine_name)
356 Depends(binary, local_engine)
357 main.Command(local_engine, simulation_engine_lib,
358 MakeAction("cp ${SOURCE} ${TARGET}", Transform('COPY')))
360 Export('ArmFastModelComponent')
361 Export('ArmFastModelBin')
363 PySource('m5', 'arm_fast_model.py')
364 Source('fastmodel.cc')
366 SimObject('FastModel.py')
367 Source('amba_to_tlm_bridge.cc')
368 Source('amba_from_tlm_bridge.cc')
370 # HACK: Make sure the gic protocol headers are somewhere we can find them.
371 # These should start out alongside other headers fast model provides which we
372 # are already able to include, but unfortunately they're in the examples
374 gicv3_comms_headers = (
375 'gicv3_comms_base.h', 'gicv3_comms_if.h', 'gicv3_comms_sockets.h')
376 examples_common_dir = pvlib_home.Dir('examples/SystemCExport/Common')
377 gic_protocol_path = 'Protocols/GICv3Comms'
378 gic_protocol_dest = Dir(env['BUILDDIR']).Dir(gic_protocol_path)
379 gic_protocol_src = examples_common_dir.Dir(gic_protocol_path)
381 for header in gicv3_comms_headers:
382 Command(gic_protocol_dest.File(header), gic_protocol_src.File(header),
383 Copy('${TARGET}', '${SOURCE}'))
385 lisa_protocol_types_header_path = 'include/lisa_protocol_types.h'
386 lisa_protocol_types_header_target = \
387 gic_protocol_dest.File(lisa_protocol_types_header_path)
388 lisa_protocol_types_header_src = \
389 examples_common_dir.File(lisa_protocol_types_header_path)
390 Command(lisa_protocol_types_header_target, lisa_protocol_types_header_src,
391 Copy('${TARGET}', '${SOURCE}'))