fastmodel: Implement inst count events in the IRIS thread contexts.
[gem5.git] / src / arch / arm / fastmodel / SConscript
1 # Copyright 2019 Google, Inc.
2 #
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.
13 #
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.
25 #
26 # Authors: Gabe Black
27
28 from __future__ import print_function
29
30 Import('*')
31
32 from m5.util.terminal import termcap
33 from m5.util.grammar import Grammar
34
35 from gem5_scons import Transform
36
37 import os.path
38
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' +
43 termcap.Normal)
44 env['USE_ARM_FASTMODEL'] = False
45 Return()
46
47 if not env['USE_ARM_FASTMODEL']:
48 Return()
49
50
51 systemc_home = Dir('#/src/systemc/ext/systemc_home')
52 env['ENV']['SYSTEMC_HOME'] = systemc_home.abspath
53
54 def extract_var(name):
55 if name not in env:
56 print(termcap.Red + termcap.Bold +
57 ('Error: %s is not set' % name) +
58 termcap.Normal)
59 Exit(1)
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]
64 return env[name]
65
66 pvlib_home, maxcore_home, armlmd_license_file = \
67 list(map(extract_var, ('PVLIB_HOME', 'MAXCORE_HOME',
68 'ARMLMD_LICENSE_FILE')))
69
70 pvlib_home = Dir(pvlib_home)
71 maxcore_home = Dir(maxcore_home)
72 armlmd_license_file = File(armlmd_license_file)
73
74
75 pvlib_flavor = env['PVLIB_FLAVOR']
76 pvlib_lib_dir = pvlib_home.Dir('lib').Dir(pvlib_flavor)
77
78 simulation_engine_name = 'libMAXCOREInitSimulationEngine.3.so'
79 simulation_engine_lib = pvlib_lib_dir.File(simulation_engine_name)
80
81
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.'''
86
87 static_name = env.subst('${LIBPREFIX}' + name + '${LIBSUFFIX}')
88
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)
93
94 return name
95
96
97 # Adjust the build environment to support building in Fast Models.
98
99 env.Append(CCFLAGS='-pthread')
100
101 cpppaths = (
102 pvlib_home.Dir('include/fmruntime'),
103 pvlib_home.Dir('include/fmruntime/eslapi'),
104 pvlib_home.Dir('Iris/include'),
105
106 systemc_home.Dir('include'),
107
108 maxcore_home.Dir('AMBA-PV/include'),
109 )
110 env.Append(CPPPATH=cpppaths)
111
112 lib_paths = (
113 pvlib_lib_dir,
114 pvlib_home.Dir('Iris').Dir(pvlib_flavor),
115 )
116 env.Append(LIBPATH=lib_paths)
117 env.Append(RPATH=lib_paths)
118
119 libs = (
120 'components',
121 'pvbus',
122 'armctmodel',
123 'fmruntime',
124 'IrisSupport',
125 'dl',
126 'rt',
127 )
128 env.Append(LIBS=list(staticify(env, lib) for lib in libs))
129
130
131 class ProjectFileParser(Grammar):
132 class Param(object):
133 def __init__(self, is_object):
134 self.is_object = is_object
135
136 def __str__(self):
137 return self._to_str(0)
138
139 class StringParam(Param):
140 def __init__(self, name, value):
141 super(ProjectFileParser.StringParam, self).__init__(
142 is_object=False)
143 self.name = name
144 self.value = value
145
146 def _to_str(self, indent):
147 indent_str = " " * indent
148 return indent_str + self.name + ' = \"' + self.value + '\"'
149
150 class ObjectParam(Param):
151 def __init__(self, type_name, name, params):
152 super(ProjectFileParser.ObjectParam, self).__init__(
153 is_object=True)
154 self.type_name = type_name
155 self.name = name
156 self.params = params
157
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 + "}"
167 return val
168
169 #########
170 # Lexer #
171 #########
172
173 tokens = (
174 # identifier
175 'ID',
176
177 # string literal
178 'STRLIT',
179
180 # = { } ;
181 'EQUALS',
182 'LBRACE',
183 'RBRACE',
184 'SEMI',
185 )
186
187 t_ID = r'[A-Za-z_]\w*'
188
189 def t_STRLIT(self, t):
190 r'(?m)"([^"])*"'
191 # strip off quotes
192 t.value = t.value[1:-1]
193 t.lexer.lineno += t.value.count('\n')
194 return t
195
196 t_EQUALS = r'='
197 t_LBRACE = r'\{'
198 t_RBRACE = r'\}'
199 t_SEMI = r';'
200
201 def t_NEWLINE(self, t):
202 r'\n+'
203 t.lexer.lineno += t.value.count('\n')
204
205 t_ignore = ' \t\x0c'
206
207 ##########
208 # Parser #
209 ##########
210
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])
214
215 def p_object_heading_0(self, t):
216 'object_heading : ID STRLIT'
217 t[0] = (t[1], t[2])
218
219 def p_object_heading_1(self, t):
220 'object_heading : ID'
221 t[0] = (t[1], None)
222
223 def p_params_0(self, t):
224 'params : '
225 t[0] = []
226
227 def p_params_1(self, t):
228 'params : param params'
229 t[0] = [t[1]] + t[2]
230
231 def p_param_0(self, t):
232 'param : ID EQUALS STRLIT SEMI'
233 t[0] = self.StringParam(t[1], t[3])
234
235 def p_param_1(self, t):
236 'param : object'
237 t[0] = t[1]
238
239
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('.')
244
245 parser = ProjectFileParser()
246 proj = parser.parse_file(project_file.srcnode().abspath)
247
248 # Top level component.
249 tlc = None
250 # Config name.
251 config_name = None
252
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':
257 tlc = param.value
258 elif param.name == 'ACTIVE_CONFIG_LINUX':
259 config_name = param.value
260
261 assert tlc is not None and config_name is not None
262
263 simgen_dir = project_file_dir.Dir(config_name)
264
265 def simgen_static(name):
266 return simgen_dir.File(env.subst(
267 '${LIBPREFIX}%s${LIBSUFFIX}' % name))
268
269 def simgen_shared(name):
270 return simgen_dir.File(env.subst(
271 '${SHLIBPREFIX}%s${SHLIBSUFFIX}' % name))
272
273 static_libs = [
274 'scx-%s-%s' % (tlc, config_name),
275 'scx',
276 ]
277 shared_libs = [
278 '%s-%s' % (tlc, config_name),
279 ]
280
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
288 # for it.
289 lib_nodes = static_lib_nodes + shared_lib_nodes
290
291 gen_dir = simgen_dir.Dir('gen')
292
293 header = gen_dir.File('scx_evs_%s.h' % tlc)
294
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]
300
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)
310
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)
316
317
318 class ArmFastModelBin(Executable):
319 def __init__(self, target, *components_and_sources):
320 def is_component(x):
321 return isinstance(x, ArmFastModelComponent)
322
323 def not_component(x):
324 return not is_component(x)
325
326 components = list(filter(is_component, components_and_sources))
327 sources = list(filter(not_component, components_and_sources))
328
329 self.components = components
330 super(ArmFastModelBin, self).__init__(target, *sources)
331
332 @classmethod
333 def declare_all(cls, env):
334 env = env.Clone()
335 env.Prepend(LIBS=env['STATIC_LIB'][0])
336 super(ArmFastModelBin, cls).declare_all(env)
337
338 def declare(self, env):
339 env = env.Clone()
340
341 sources = list(self.sources)
342 for f in self.filters:
343 sources += Source.all.apply_filter(f)
344
345 objs = self.srcs_to_objs(env, sources)
346 objs = objs + env['MAIN_OBJS']
347
348 for component in self.components:
349 component.prepare_env(env)
350
351 binary = super(ArmFastModelBin, self).declare(env, objs)[0]
352
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')))
359
360 Export('ArmFastModelComponent')
361 Export('ArmFastModelBin')
362
363 PySource('m5', 'arm_fast_model.py')
364 Source('fastmodel.cc')
365
366 SimObject('FastModel.py')
367 Source('amba_to_tlm_bridge.cc')
368 Source('amba_from_tlm_bridge.cc')
369
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
373 # directory.
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)
380
381 for header in gicv3_comms_headers:
382 Command(gic_protocol_dest.File(header), gic_protocol_src.File(header),
383 Copy('${TARGET}', '${SOURCE}'))
384
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}'))