2020-04-28 17:00:19 +08:00
|
|
|
# Copyright (c) 2020 Synopsys.
|
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2020-10-07 22:12:42 +03:00
|
|
|
'''Runners for Synopsys Metaware Debugger(mdb).'''
|
2020-04-28 17:00:19 +08:00
|
|
|
|
|
|
|
|
|
|
|
import os
|
2024-11-20 15:54:37 +01:00
|
|
|
import shutil
|
2020-04-28 17:00:19 +08:00
|
|
|
from os import path
|
2020-12-11 09:56:53 -08:00
|
|
|
|
2024-11-20 15:54:37 +01:00
|
|
|
from runners.core import RunnerCaps, ZephyrBinaryRunner
|
2020-04-28 17:00:19 +08:00
|
|
|
|
2020-12-11 09:56:53 -08:00
|
|
|
|
2020-10-07 22:12:42 +03:00
|
|
|
# normally we should create class with common functionality inherited from
|
|
|
|
# ZephyrBinaryRunner and inherit MdbNsimBinaryRunner and MdbHwBinaryRunner
|
|
|
|
# from it. However as we do lookup for runners with
|
|
|
|
# ZephyrBinaryRunner.__subclasses__() such sub-sub-classes won't be found.
|
|
|
|
# So, we move all common functionality to helper functions instead.
|
2023-03-16 19:16:35 +00:00
|
|
|
def is_simulation_run(mdb_runner):
|
2020-10-07 22:12:42 +03:00
|
|
|
return mdb_runner.nsim_args != ''
|
|
|
|
|
2023-03-16 19:16:35 +00:00
|
|
|
def is_hostlink_used(mdb_runner):
|
|
|
|
return mdb_runner.build_conf.getboolean('CONFIG_UART_HOSTLINK')
|
|
|
|
|
|
|
|
def is_flash_cmd_need_exit_immediately(mdb_runner):
|
|
|
|
if is_simulation_run(mdb_runner):
|
|
|
|
# for nsim, we can't run and quit immediately
|
|
|
|
return False
|
2024-11-20 09:18:43 +01:00
|
|
|
|
|
|
|
# if hostlink is used we can't run and quit immediately, as we still need MDB process
|
|
|
|
# attached to process hostlink IO
|
|
|
|
return not is_hostlink_used(mdb_runner)
|
2023-03-16 19:16:35 +00:00
|
|
|
|
2024-05-14 16:39:02 +01:00
|
|
|
def smp_core_order(mdb_runner, id):
|
|
|
|
if is_simulation_run(mdb_runner):
|
2024-11-20 16:54:12 +01:00
|
|
|
# for simulation targets we start cores in direct order
|
|
|
|
# (core 0 first, core 1 second, etc...)
|
|
|
|
# otherwise we face mismatch arcnum (code ID) with ARConnect ID
|
|
|
|
# and core ID in instruction traces
|
2024-05-14 16:39:02 +01:00
|
|
|
return id
|
|
|
|
else:
|
2024-11-20 16:54:12 +01:00
|
|
|
# for HW targets we want to start the primary core last,
|
|
|
|
# to avoid ARConnect initialization interfere
|
2024-05-14 16:39:02 +01:00
|
|
|
# with secondary cores startup - so we reverse start order
|
|
|
|
return mdb_runner.cores - 1 - id
|
|
|
|
|
2020-10-07 22:12:42 +03:00
|
|
|
def mdb_do_run(mdb_runner, command):
|
2023-05-17 21:46:52 +01:00
|
|
|
commander = "mdb64"
|
2020-10-07 22:12:42 +03:00
|
|
|
|
|
|
|
mdb_runner.require(commander)
|
|
|
|
|
2023-03-16 19:16:35 +00:00
|
|
|
mdb_basic_options = ['-nooptions', '-nogoifmain', '-toggle=include_local_symbols=1']
|
2020-10-07 22:12:42 +03:00
|
|
|
|
|
|
|
# remove previous .sc.project folder which has temporary settings
|
|
|
|
# for MDB. This is useful for troubleshooting situations with
|
|
|
|
# unexpected behavior of the debugger
|
|
|
|
mdb_cfg_dir = path.join(mdb_runner.build_dir, '.sc.project')
|
|
|
|
if path.exists(mdb_cfg_dir):
|
|
|
|
shutil.rmtree(mdb_cfg_dir)
|
|
|
|
|
|
|
|
# nsim
|
2023-03-16 19:16:35 +00:00
|
|
|
if is_simulation_run(mdb_runner):
|
2020-10-07 22:12:42 +03:00
|
|
|
mdb_target = ['-nsim', '@' + mdb_runner.nsim_args]
|
|
|
|
# hardware target
|
|
|
|
else:
|
|
|
|
if mdb_runner.jtag == 'digilent':
|
2023-02-01 18:31:09 +00:00
|
|
|
mdb_target = ['-digilent']
|
2024-11-20 09:37:45 +01:00
|
|
|
if mdb_runner.dig_device:
|
|
|
|
mdb_target += [mdb_runner.dig_device]
|
2020-10-07 22:12:42 +03:00
|
|
|
else:
|
|
|
|
# \todo: add support of other debuggers
|
2024-11-20 16:05:28 +01:00
|
|
|
raise ValueError(f'unsupported jtag adapter {mdb_runner.jtag}')
|
2020-10-07 22:12:42 +03:00
|
|
|
|
|
|
|
if command == 'flash':
|
2023-03-16 19:16:35 +00:00
|
|
|
if is_flash_cmd_need_exit_immediately(mdb_runner):
|
2020-10-07 22:12:42 +03:00
|
|
|
mdb_run = ['-run', '-cmd=-nowaitq run', '-cmd=quit', '-cl']
|
2023-03-16 19:16:35 +00:00
|
|
|
else:
|
|
|
|
mdb_run = ['-run', '-cl']
|
2020-10-07 22:12:42 +03:00
|
|
|
elif command == 'debug':
|
|
|
|
# use mdb gui to debug
|
|
|
|
mdb_run = ['-OKN']
|
|
|
|
|
|
|
|
if mdb_runner.cores == 1:
|
|
|
|
# single core's mdb command is different with multicores
|
2023-03-16 19:16:35 +00:00
|
|
|
mdb_cmd = [commander] + mdb_basic_options + mdb_target + mdb_run + [mdb_runner.elf_name]
|
2023-05-16 21:46:08 +01:00
|
|
|
elif 1 < mdb_runner.cores <= 12:
|
2020-10-07 22:12:42 +03:00
|
|
|
mdb_multifiles = '-multifiles='
|
|
|
|
for i in range(mdb_runner.cores):
|
2024-11-20 16:05:28 +01:00
|
|
|
mdb_sub_cmd = [commander] + [f'-pset={i + 1}', f'-psetname=core{i}']
|
2023-02-01 18:31:09 +00:00
|
|
|
# -prop=download=2 is used for SMP application debug, only the 1st core
|
|
|
|
# will download the shared image.
|
2024-11-20 09:37:45 +01:00
|
|
|
if i > 0:
|
|
|
|
mdb_sub_cmd += ['-prop=download=2']
|
2023-02-01 18:31:09 +00:00
|
|
|
mdb_sub_cmd += mdb_basic_options + mdb_target + [mdb_runner.elf_name]
|
2022-05-24 14:23:52 +04:00
|
|
|
mdb_runner.check_call(mdb_sub_cmd, cwd=mdb_runner.build_dir)
|
2024-11-20 16:54:12 +01:00
|
|
|
mdb_multifiles += f'{"" if i == 0 else ","}core{smp_core_order(mdb_runner, i)}'
|
2020-10-07 22:12:42 +03:00
|
|
|
|
|
|
|
# to enable multi-core aware mode for use with the MetaWare debugger,
|
|
|
|
# need to set the NSIM_MULTICORE environment variable to a non-zero value
|
2023-03-16 19:16:35 +00:00
|
|
|
if is_simulation_run(mdb_runner):
|
2020-10-07 22:12:42 +03:00
|
|
|
os.environ["NSIM_MULTICORE"] = '1'
|
2020-04-28 17:00:19 +08:00
|
|
|
|
2023-02-01 16:37:48 +00:00
|
|
|
mdb_cmd = [commander] + [mdb_multifiles] + mdb_run
|
2020-10-07 22:12:42 +03:00
|
|
|
else:
|
2024-11-20 16:05:28 +01:00
|
|
|
raise ValueError(f'unsupported cores {mdb_runner.cores}')
|
2020-10-07 22:12:42 +03:00
|
|
|
|
2023-02-01 12:54:50 +00:00
|
|
|
mdb_runner.call(mdb_cmd, cwd=mdb_runner.build_dir)
|
2020-10-07 22:12:42 +03:00
|
|
|
|
|
|
|
|
|
|
|
class MdbNsimBinaryRunner(ZephyrBinaryRunner):
|
|
|
|
'''Runner front-end for nSIM via mdb.'''
|
|
|
|
|
|
|
|
def __init__(self, cfg, cores=1, nsim_args=''):
|
2020-06-23 13:27:11 -07:00
|
|
|
super().__init__(cfg)
|
2020-10-07 22:12:42 +03:00
|
|
|
self.jtag = ''
|
2020-04-28 17:00:19 +08:00
|
|
|
self.cores = int(cores)
|
|
|
|
if nsim_args != '':
|
|
|
|
self.nsim_args = path.join(cfg.board_dir, 'support', nsim_args)
|
|
|
|
else:
|
|
|
|
self.nsim_args = ''
|
|
|
|
self.elf_name = cfg.elf_file
|
2020-10-07 22:12:42 +03:00
|
|
|
self.build_dir = cfg.build_dir
|
|
|
|
self.dig_device = ''
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def name(cls):
|
|
|
|
return 'mdb-nsim'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def capabilities(cls):
|
|
|
|
return RunnerCaps(commands={'flash', 'debug'})
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def do_add_parser(cls, parser):
|
|
|
|
parser.add_argument('--cores', default=1,
|
|
|
|
help='''choose the cores that target has, e.g.
|
|
|
|
--cores=1''')
|
|
|
|
parser.add_argument('--nsim_args', default='',
|
|
|
|
help='''if given, arguments for nsim simulator
|
|
|
|
through mdb which should be in
|
|
|
|
<board_dir>/support, e.g. --nsim-args=
|
|
|
|
mdb_em.args''')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def do_create(cls, cfg, args):
|
|
|
|
return MdbNsimBinaryRunner(
|
|
|
|
cfg,
|
|
|
|
cores=args.cores,
|
|
|
|
nsim_args=args.nsim_args)
|
|
|
|
|
|
|
|
def do_run(self, command, **kwargs):
|
|
|
|
mdb_do_run(self, command)
|
|
|
|
|
|
|
|
|
|
|
|
class MdbHwBinaryRunner(ZephyrBinaryRunner):
|
|
|
|
'''Runner front-end for mdb.'''
|
|
|
|
|
|
|
|
def __init__(self, cfg, cores=1, jtag='digilent', dig_device=''):
|
|
|
|
super().__init__(cfg)
|
|
|
|
self.jtag = jtag
|
|
|
|
self.cores = int(cores)
|
|
|
|
self.nsim_args = ''
|
|
|
|
self.elf_name = cfg.elf_file
|
2020-04-28 17:00:19 +08:00
|
|
|
if dig_device != '':
|
|
|
|
self.dig_device = '-prop=dig_device=' + dig_device
|
|
|
|
else:
|
|
|
|
self.dig_device = ''
|
2020-10-07 22:12:42 +03:00
|
|
|
self.build_dir = cfg.build_dir
|
2020-04-28 17:00:19 +08:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def name(cls):
|
2020-10-07 22:12:42 +03:00
|
|
|
return 'mdb-hw'
|
2020-04-28 17:00:19 +08:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def capabilities(cls):
|
|
|
|
return RunnerCaps(commands={'flash', 'debug'})
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def do_add_parser(cls, parser):
|
|
|
|
parser.add_argument('--jtag', default='digilent',
|
|
|
|
help='''choose the jtag interface for hardware
|
2022-03-16 21:07:43 +00:00
|
|
|
targets, e.g. --jtag=digilent for digilent
|
2020-10-07 22:12:42 +03:00
|
|
|
jtag adapter''')
|
2020-04-28 17:00:19 +08:00
|
|
|
parser.add_argument('--cores', default=1,
|
2020-10-07 22:12:42 +03:00
|
|
|
help='''choose the number of cores that target has,
|
|
|
|
e.g. --cores=1''')
|
2020-04-28 17:00:19 +08:00
|
|
|
parser.add_argument('--dig-device', default='',
|
2024-06-21 18:37:21 +10:00
|
|
|
help='''choose the specific digilent device to
|
2020-10-07 22:12:42 +03:00
|
|
|
connect, this is useful when multiple
|
2020-04-28 17:00:19 +08:00
|
|
|
targets are connected''')
|
|
|
|
|
|
|
|
@classmethod
|
2020-06-23 13:35:52 -07:00
|
|
|
def do_create(cls, cfg, args):
|
2020-10-07 22:12:42 +03:00
|
|
|
return MdbHwBinaryRunner(
|
2020-04-28 17:00:19 +08:00
|
|
|
cfg,
|
|
|
|
cores=args.cores,
|
|
|
|
jtag=args.jtag,
|
2020-10-07 22:12:42 +03:00
|
|
|
dig_device=args.dig_device)
|
2020-04-28 17:00:19 +08:00
|
|
|
|
|
|
|
def do_run(self, command, **kwargs):
|
2020-10-07 22:12:42 +03:00
|
|
|
mdb_do_run(self, command)
|