9 # XLEN of the hart. May be overridden with --32 or --64 command line
13 # Will be autodetected (by running ExamineTarget) if left unset. Set to
17 # Path to linker script relative to the .py file where the target is
18 # defined. Defaults to <name>.lds.
19 link_script_path
= None
21 # Implements dmode in tdata1 as described in the spec. Harts that need
22 # this value set to False are not compliant with the spec (but still usable
23 # as long as running code doesn't try to mess with triggers set by an
25 honors_tdata1_hmode
= True
27 # Address where a r/w/x block of RAM starts, together with its size.
31 # Number of instruction triggers the hart supports.
32 instruction_hardware_breakpoint_count
= 0
34 # Defaults to target-<index>
37 # When reset, the PC must be at one of the values listed here.
38 # This is a list because on some boards the reset vector depends on
42 def extensionSupported(self
, letter
):
43 # target.misa is set by testlib.ExamineTarget
45 return self
.misa
& (1 << (ord(letter
.upper()) - ord('A')))
50 # pylint: disable=too-many-instance-attributes
52 # List of Hart object instances, one for each hart in the target.
55 # Name of the target. Defaults to the name of the class.
58 # GDB remotetimeout setting.
61 # Timeout waiting for the server to start up. This is different than the
62 # GDB timeout, which is how long GDB waits for commands to execute.
63 # The server_timeout is how long this script waits for the server to be
64 # ready for GDB connections.
65 server_timeout_sec
= 60
67 # Path to OpenOCD configuration file relative to the .py file where the
68 # target is defined. Defaults to <name>.cfg.
69 openocd_config_path
= None
71 # List of commands that should be executed in gdb after connecting but
72 # before starting the test.
75 # Supports mtime at 0x2004000
76 supports_clint_mtime
= True
78 # Implements custom debug registers like spike does. It seems unlikely any
79 # hardware will every do that.
80 implements_custom_test
= False
86 def __init__(self
, path
, parsed
):
89 self
.directory
= os
.path
.dirname(path
)
90 self
.server_cmd
= parsed
.server_cmd
91 self
.sim_cmd
= parsed
.sim_cmd
92 self
.temporary_binary
= None
93 Target
.isolate
= parsed
.isolate
95 self
.name
= type(self
).__name
__
96 # Default OpenOCD config file to <name>.cfg
97 if not self
.openocd_config_path
:
98 self
.openocd_config_path
= "%s.cfg" % self
.name
99 self
.openocd_config_path
= os
.path
.join(self
.directory
,
100 self
.openocd_config_path
)
101 for i
, hart
in enumerate(self
.harts
):
103 if not hasattr(hart
, 'id'):
106 hart
.name
= "%s-%d" % (self
.name
, i
)
107 # Default link script to <name>.lds
108 if not hart
.link_script_path
:
109 hart
.link_script_path
= "%s.lds" % self
.name
110 hart
.link_script_path
= os
.path
.join(self
.directory
,
111 hart
.link_script_path
)
114 """Create the target out of thin air, eg. start a simulator."""
118 """Start the debug server that gdb connects to, eg. OpenOCD."""
119 return testlib
.Openocd(server_cmd
=self
.server_cmd
,
120 config
=self
.openocd_config_path
,
121 timeout
=self
.server_timeout_sec
)
123 def compile(self
, hart
, *sources
):
124 binary_name
= "%s_%s-%d" % (
126 os
.path
.basename(os
.path
.splitext(sources
[0])[0]),
129 self
.temporary_binary
= tempfile
.NamedTemporaryFile(
130 prefix
=binary_name
+ "_")
131 binary_name
= self
.temporary_binary
.name
132 Target
.temporary_files
.append(self
.temporary_binary
)
133 march
= "rv%dima" % hart
.xlen
135 if hart
.extensionSupported(letter
):
137 testlib
.compile(sources
+
138 ("programs/entry.S", "programs/init.c",
139 "-DNHARTS=%d" % len(self
.harts
),
142 "-T", hart
.link_script_path
,
145 "-DXLEN=%d" % hart
.xlen
,
150 def add_target_options(parser
):
151 parser
.add_argument("target", help=".py file that contains definition for "
152 "the target to test with.")
153 parser
.add_argument("--sim_cmd",
154 help="The command to use to start the actual target (e.g. "
155 "simulation)", default
="spike")
156 parser
.add_argument("--server_cmd",
157 help="The command to use to start the debug server (e.g. OpenOCD)")
159 xlen_group
= parser
.add_mutually_exclusive_group()
160 xlen_group
.add_argument("--32", action
="store_const", const
=32,
161 dest
="xlen", default
=0, help="Force the target to be 32-bit.")
162 xlen_group
.add_argument("--64", action
="store_const", const
=64,
163 dest
="xlen", default
=0, help="Force the target to be 64-bit.")
165 parser
.add_argument("--isolate", action
="store_true",
166 help="Try to run in such a way that multiple instances can run at "
167 "the same time. This may make it harder to debug a failure if it "
171 directory
= os
.path
.dirname(parsed
.target
)
172 filename
= os
.path
.basename(parsed
.target
)
173 module_name
= os
.path
.splitext(filename
)[0]
175 sys
.path
.append(directory
)
176 module
= importlib
.import_module(module_name
)
178 for name
in dir(module
):
179 definition
= getattr(module
, name
)
180 if isinstance(definition
, type) and issubclass(definition
, Target
):
181 found
.append(definition
)
182 assert len(found
) == 1, "%s does not define exactly one subclass of " \
183 "targets.Target" % parsed
.target
185 t
= found
[0](parsed
.target
, parsed
)
186 assert t
.harts
, "%s doesn't have any harts defined!" % t
.name
191 elif h
.xlen
!= parsed
.xlen
:
192 raise Exception("The target hart specified an XLEN of %d, but "\
193 "the command line specified an XLEN of %d. They must "\
194 "match." % (h
.xlen
, parsed
.xlen
))