Skip to content

Commit 0d0593a

Browse files
committed
Flip-flopped on whether to do anything special with register arrays
1 parent 07ae6ef commit 0d0593a

File tree

1 file changed

+55
-78
lines changed

1 file changed

+55
-78
lines changed

cmdebug/svd_gdb.py

Lines changed: 55 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import struct
2323
import pkg_resources
2424

25-
from typing import Tuple, List, Optional
25+
from typing import Tuple, List, Optional, Union
2626

2727
sys.path.append('.')
2828
#from cmdebug.svd import SVDFile
@@ -35,8 +35,8 @@
3535
32: "I",
3636
}
3737

38-
def _reg_address(reg: svd_model.SVDRegister) -> int:
39-
assert reg.parent is not None and reg.parent._address_block is not None, f"Cannot get address for parentless register {reg.name}"
38+
def _reg_address(reg: Union[svd_model.SVDRegister, svd_model.SVDRegisterArray]) -> int:
39+
assert reg.parent is not None, f"Cannot get address for parentless register {reg.name}"
4040
return reg.parent._base_address + reg.address_offset
4141

4242
def _field_accessible(field: svd_model.SVDField, mode: str) -> bool:
@@ -52,6 +52,28 @@ def _field_readable(field: svd_model.SVDField) -> bool:
5252
def _field_writeable(field: svd_model.SVDField) -> bool:
5353
return _field_accessible(field, "write")
5454

55+
def _reg_accessible(reg: Union[svd_model.SVDRegister, svd_model.SVDRegisterArray], mode: str) -> bool:
56+
if reg._access is not None:
57+
return mode in reg._access
58+
elif reg.parent._access is not None:
59+
return mode in reg.parent._access
60+
return False
61+
62+
def _reg_readable(reg: Union[svd_model.SVDRegister, svd_model.SVDRegisterArray]) -> bool:
63+
return _reg_accessible(reg, "read")
64+
65+
def _reg_writeable(reg: Union[svd_model.SVDRegister, svd_model.SVDRegisterArray]) -> bool:
66+
return _reg_accessible(reg, "write")
67+
68+
def _get_regs_by_addresss(peripheral: svd_model.SVDPeripheral) -> List[Tuple[str, svd_model.SVDRegister, int]]:
69+
reg_list: List[Tuple[str, svd_model.SVDRegister, int]] = []
70+
for r in peripheral.registers:
71+
# Assign parent for the lookup, since we know it and for some reason registers derivered from a register array don't have a parent set
72+
r.parent = peripheral
73+
reg_list.append((r.name, r, _reg_address(r)))
74+
75+
return sorted(reg_list, key=lambda x: x[2])
76+
5577
class LoadSVD(gdb.Command):
5678
""" A command to load an SVD file and to create the command for inspecting
5779
that object
@@ -128,30 +150,32 @@ def __init__(self, svd_device: svd_model.SVDDevice):
128150
gdb.Command.__init__(self, "svd", gdb.COMMAND_DATA)
129151
self.svd_device = svd_device
130152

131-
def _print_registers(self, container_name, form: str, registers: List[svd_model.SVDRegister]):
132-
if len(registers) == 0:
133-
return
153+
def _print_registers(self, container_name, form: str, peripheral: svd_model.SVDPeripheral):
134154
gdb.write(f"Registers in {container_name}:\n")
135-
reg_list: List[Tuple[str, str, str]] = []
136-
for r in registers:
137-
if r._access is not None and "read" in r._access:
155+
156+
reg_list = _get_regs_by_addresss(peripheral)
157+
reg_list_str: List[Tuple[str, str, str]] = []
158+
159+
for name, r, addr in reg_list:
160+
if _reg_readable(r):
138161
try:
139-
data = self.read(_reg_address(r), r._size)
162+
data = self.read(addr, r._size)
140163
data_str = self.format(data, form, r._size)
141164
if form == 'a':
142165
data_str += " <" + re.sub(r'\s+', ' ',
143-
gdb.execute("info symbol {}".format(data), True,
144-
True).strip()) + ">"
166+
gdb.execute("info symbol {}".format(data), True,
167+
True).strip()) + ">"
145168
except gdb.MemoryError:
146169
data_str = "(error reading)"
147170
else:
148171
data_str = "(not readable)"
172+
149173
desc = re.sub(r'\s+', ' ', r.description)
150-
reg_list.append((r.name, data_str, desc))
174+
reg_list_str.append((name, data_str, desc))
151175

152-
column1_width = max(len(reg[0]) for reg in reg_list) + 2 # padding
153-
column2_width = max(len(reg[1]) for reg in reg_list)
154-
for reg in reg_list:
176+
column1_width = max(len(reg[0]) for reg in reg_list_str) + 2 # padding
177+
column2_width = max(len(reg[1]) for reg in reg_list_str)
178+
for reg in reg_list_str:
155179
gdb.write("\t{}:{}{}".format(reg[0], "".ljust(column1_width - len(reg[0])), reg[1].rjust(column2_width)))
156180
if reg[2] != reg[0]:
157181
gdb.write(" {}".format(reg[2]))
@@ -221,7 +245,7 @@ def invoke(self, args, from_tty):
221245
gdb.write("\td(default):decimal, x: hex, o: octal, b: binary\n")
222246
gdb.write("\n")
223247
gdb.write(
224-
"Both prefix matching and case-insensitive matching is supported for peripherals, registers, clusters and fields.\n")
248+
"Both prefix matching and case-insensitive matching is supported for peripherals, registers, and fields.\n")
225249
return
226250

227251
if not len(s[0]):
@@ -248,84 +272,38 @@ def invoke(self, args, from_tty):
248272
peripheral = sorted(matching_peripherals, key=lambda x: x.name)[0]
249273

250274
if len(s) == 1:
251-
self._print_registers(peripheral.name, form, peripheral.registers)
252-
if peripheral._register_arrays:
253-
clusters_iter = peripheral._register_arrays
254-
gdb.write("Clusters in %s:\n" % peripheral.name)
255-
reg_list: List[Tuple[str, str, str]] = []
256-
for r in clusters_iter:
257-
desc = re.sub(r'\s+', ' ', r.description)
258-
reg_list.append((r.name, "", desc))
259-
260-
column1_width = max(len(reg[0]) for reg in reg_list) + 2 # padding
261-
column2_width = max(len(reg[1]) for reg in reg_list)
262-
for reg in reg_list:
263-
gdb.write(
264-
"\t{}:{}{}".format(reg[0], "".ljust(column1_width - len(reg[0])), reg[1].rjust(column2_width)))
265-
if reg[2] != reg[0]:
266-
gdb.write(" {}".format(reg[2]))
267-
gdb.write("\n")
275+
self._print_registers(peripheral.name, form, peripheral)
268276
return
269277

270-
cluster = None
271278
if len(s) == 2:
272-
gdb.write(f"{[r.name for r in peripheral.registers]}\n")
273-
matching_clusters = []
274-
if peripheral._register_arrays is not None:
275-
matching_clusters = [c for c in peripheral._register_arrays if c.name.lower().startswith(s[1].lower())]
276-
277279
matching_registers = []
278280
if peripheral.registers is not None:
279-
matching_registers = [r for r in peripheral._registers if r.name.lower().startswith(s[1].lower())]
281+
matching_registers = [r for r in peripheral.registers if r.name.lower().startswith(s[1].lower())]
280282

281-
if matching_clusters:
282-
# Warn if this matches more than one
283-
if len(matching_clusters) > 1:
284-
matching_names = ", ".join([c.name for c in matching_clusters])
285-
gdb.write(f'Warning: {s[1]} could prefix match any of: {matching_names}\n')
286-
287-
cluster = matching_clusters[0]
288-
container = peripheral.name + ' > ' + cluster.name
289-
self._print_registers(container, form, cluster.registers)
290-
elif matching_registers:
283+
if matching_registers:
291284
# Warn if this matches more than one
292285
if len(matching_registers) > 1:
293286
matching_names = ", ".join([r.name for r in matching_registers])
294287
gdb.write(f'Warning: {s[1]} could prefix match any of: {matching_names}\n')
295288

296-
register = sorted(matching_registers)[0]
289+
register = sorted(matching_registers, key=lambda x: x.name)[0]
297290
container = peripheral.name + ' > ' + register.name
291+
register.parent = peripheral
298292
self._print_register_fields(container, form, register)
299293

300294
else:
301-
gdb.write(f"Register/cluster {s[1]} in peripheral {peripheral.name} does not exist!\n")
295+
gdb.write(f"Register {s[1]} in peripheral {peripheral.name} does not exist!\n")
302296
return
303297

304298
if len(s) == 3:
305-
# Must be reading from a register within a cluster
306-
307-
matching_clusters = []
308-
if peripheral._register_arrays is not None:
309-
matching_clusters = [c for c in peripheral._register_arrays if c.name.lower().startswith(s[1].lower())]
310-
311-
if not matching_clusters:
312-
gdb.write(f"Cluster {s[1]} in peripheral {peripheral.name} does not exist!\n")
313-
return
314-
315-
# Warn if this matches more than one
316-
if len(matching_clusters) > 1:
317-
matching_names = ", ".join([c.name for c in matching_clusters])
318-
gdb.write(f'Aborting: {s[1]} could prefix match any of: {matching_names}\n')
319-
return
320-
321-
cluster = matching_clusters[0]
299+
# Must be reading from a register
322300

323301
matching_registers = []
324-
if peripheral._registers is not None:
325-
matching_registers = [r for r in peripheral._registers if r.name.lower().startswith(s[2].lower())]
302+
if peripheral.registers is not None:
303+
matching_registers = [r for r in peripheral.registers if r.name.lower().startswith(s[2].lower())]
326304

327305
if not matching_registers:
328-
gdb.write(f"Register {s[2]} in cluster {cluster.name} in peripheral {peripheral.name} does not exist!\n")
306+
gdb.write(f"Register {s[2]} in peripheral {peripheral.name} does not exist!\n")
329307
return
330308

331309
# Warn if this matches more than one
@@ -336,15 +314,15 @@ def invoke(self, args, from_tty):
336314

337315
register = matching_registers[0]
338316

339-
container = ' > '.join([peripheral.name, cluster.name, register.name])
317+
container = ' > '.join([peripheral.name, register.name])
340318
self._print_register_fields(container, form, register)
341319
return
342320

343321
if len(s) == 4:
344322

345323
matching_registers = []
346-
if peripheral._registers is not None:
347-
matching_registers = [r for r in peripheral._registers if r.name.lower().startswith(s[1].lower())]
324+
if peripheral.registers is not None:
325+
matching_registers = [r for r in peripheral.registers if r.name.lower().startswith(s[1].lower())]
348326

349327
if not matching_registers:
350328
gdb.write(f"Register {s[1]} in peripheral {peripheral.name} does not exist!\n")
@@ -430,8 +408,7 @@ def complete(self, text, word):
430408
if len(reg) and reg[0] == '&':
431409
reg = reg[1:]
432410

433-
regs = peripheral.registers + peripheral._register_arrays
434-
matching_regs = [r for r in regs if r.name.lower().startswith(reg.lower())]
411+
matching_regs = [r for r in peripheral.registers if r.name.lower().startswith(reg.lower())]
435412

436413
if len(matching_regs) == 0:
437414
return []

0 commit comments

Comments
 (0)