Skip to content

Commit 0edc8d4

Browse files
authored
Merge pull request #50 from ska-sa/devel
Merge devel into master for AR1.3
2 parents 2dcffca + ce42306 commit 0edc8d4

File tree

6 files changed

+334
-151
lines changed

6 files changed

+334
-151
lines changed

scripts/casperfpga_tengbe_coreinfo.py

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,28 @@
1919
except ImportError:
2020
corr2 = None
2121

22-
parser = argparse.ArgumentParser(description='Display TenGBE interface information about a MeerKAT fpga host.',
23-
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
24-
parser.add_argument('--hosts', dest='hosts', type=str, action='store', default='',
25-
help='comma-delimited list of hosts, or a corr2 config file')
26-
parser.add_argument('-c', '--core', dest='core', action='store', default='all', type=str,
27-
help='which core to query')
28-
parser.add_argument('--arp', dest='arp', action='store_true', default=False,
29-
help='print the ARP table')
30-
parser.add_argument('--cpu', dest='cpu', action='store_true', default=False,
31-
help='print the CPU details')
32-
parser.add_argument('--comms', dest='comms', action='store', default='katcp', type=str,
33-
help='katcp (default) or dcp?')
34-
parser.add_argument('--loglevel', dest='log_level', action='store', default='',
35-
help='log level to use, default None, options INFO, DEBUG, ERROR')
22+
parser = argparse.ArgumentParser(
23+
description='Display TenGBE interface information '
24+
'about a MeerKAT fpga host.',
25+
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
26+
parser.add_argument(
27+
'--hosts', dest='hosts', type=str, action='store', default='',
28+
help='comma-delimited list of hosts, or a corr2 config file')
29+
parser.add_argument(
30+
'-c', '--core', dest='core', action='store', default='all', type=str,
31+
help='which core to query')
32+
parser.add_argument(
33+
'--arp', dest='arp', action='store_true', default=False,
34+
help='print the ARP table')
35+
parser.add_argument(
36+
'--cpu', dest='cpu', action='store_true', default=False,
37+
help='print the CPU details')
38+
parser.add_argument(
39+
'--comms', dest='comms', action='store', default='katcp', type=str,
40+
help='katcp (default) or dcp?')
41+
parser.add_argument(
42+
'--loglevel', dest='log_level', action='store', default='',
43+
help='log level to use, default None, options INFO, DEBUG, ERROR')
3644
args = parser.parse_args()
3745

3846
if args.log_level != '':
@@ -65,8 +73,9 @@
6573
numgbes = len(fpga.tengbes)
6674
if numgbes < 1:
6775
raise RuntimeWarning('Host %s has no 10gbe cores', fpga.host)
68-
print '%s: found %i 10gbe core%s.' % (fpga.host, numgbes, '' if numgbes == 1 else 's')
69-
76+
print '%s: found %i 10gbe core%s.' % (fpga.host,
77+
numgbes,
78+
'' if numgbes == 1 else 's')
7079

7180
for fpga in fpgas:
7281
if args.core == 'all':
@@ -77,7 +86,8 @@
7786
print '%s:' % fpga.host
7887
print 50*'#'
7988
for core in cores:
80-
fpga.tengbes[core].print_10gbe_core_details(arp=args.arp, cpu=args.cpu, refresh=True)
89+
fpga.tengbes[core].print_10gbe_core_details(arp=args.arp, cpu=args.cpu,
90+
refresh=True)
8191

8292
# handle exits cleanly
8393
utils.threaded_fpga_function(fpgas, 10, 'disconnect')

scripts/casperfpga_tengbe_status.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,15 @@ def get_gbe_data(fpga):
9898
"""
9999
returndata = {}
100100
for gbecore in fpga.tengbes:
101-
returndata[gbecore.name] = gbecore.read_counters()
101+
ctr_data = gbecore.read_counters()
102+
for regname in ctr_data:
103+
regdata = ctr_data[regname]
104+
try:
105+
if ('timestamp' in regdata.keys()) and ('data' in regdata.keys()):
106+
ctr_data[regname] = regdata['data']['reg']
107+
except AttributeError:
108+
pass
109+
returndata[gbecore.name] = ctr_data
102110
return returndata
103111

104112

@@ -112,9 +120,14 @@ def get_tap_data(fpga):
112120
return data
113121

114122
# get gbe and tap data
115-
tap_data = utils.threaded_fpga_operation(fpgas, 10, get_tap_data)
116-
gbe_data = utils.threaded_fpga_operation(fpgas, 10, get_gbe_data)
117-
# print gbe_data['roach020956']['gbe0'].keys()
123+
tap_data = utils.threaded_fpga_operation(fpgas, 15, get_tap_data)
124+
gbe_data = utils.threaded_fpga_operation(fpgas, 15, get_gbe_data)
125+
# for fpga in gbe_data:
126+
# fpga_data = gbe_data[fpga]
127+
# print fpga, ':'
128+
# for gbe in fpga_data:
129+
# print gbe, ':'
130+
# print fpga_data[gbe]
118131
# utils.threaded_fpga_function(fpgas, 10, 'disconnect')
119132
# sys.exit()
120133

@@ -185,26 +198,19 @@ def exit_gracefully(sig, frame):
185198
fpga_data = gbe_data[fpga.host]
186199
scroller.add_line(fpga.host)
187200
for core, core_data in fpga_data.items():
188-
fpga_data[core]['tap_running'] = {
189-
'data': {
190-
'reg': not(tap_data[fpga.host][core]['name'] == '')
191-
}
192-
}
193-
fpga_data[core]['ip'] = {
194-
'data': {
195-
'reg': tap_data[fpga.host][core]['ip']
196-
}
197-
}
201+
tap_running = tap_data[fpga.host][core]['name'] == ''
202+
fpga_data[core]['tap_running'] = not tap_running
203+
fpga_data[core]['ip'] = tap_data[fpga.host][core]['ip']
198204
start_pos = 20
199205
scroller.add_line(core, 5)
200206
for header_register in fpga_headers[0]:
201207
core_regname = header_register.replace('gbe', core)
202208
if start_pos < 200:
203209
if core_regname in core_data.keys():
204-
if not isinstance(core_data[core_regname]['data']['reg'], str):
205-
regval = '%d' % core_data[core_regname]['data']['reg']
210+
if not isinstance(core_data[core_regname], str):
211+
regval = '%d' % core_data[core_regname]
206212
else:
207-
regval = core_data[core_regname]['data']['reg']
213+
regval = core_data[core_regname]
208214
else:
209215
regval = 'n/a'
210216
# all on the same line

src/casperfpga.py

Lines changed: 75 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,20 @@ def __init__(self, host):
6262
:return:
6363
"""
6464
self.host = host
65+
66+
# this is just for code introspection
67+
self.devices = None
68+
self.memory_devices = None
69+
self.other_devices = None
70+
self.sbrams = None
71+
self.qdrs = None
72+
self.registers = None
73+
self.tengbes = None
74+
self.snapshots = None
75+
self.system_info = None
76+
self.rcs_info = None
77+
# /just for introspection
78+
6579
self.__reset_device_info()
6680
LOGGER.debug('%s: now a CasperFpga' % self.host)
6781

@@ -319,16 +333,19 @@ def write_int(self, device_name, integer, blindwrite=False, word_offset=0):
319333
def __create_memory_devices(self, device_dict, memorymap_dict):
320334
"""
321335
Create memory devices from dictionaries of design information.
322-
:param device_dict: raw dictionary of information from tagged blocks in Simulink design, keyed on device name
323-
:param memorymap_dict: dictionary of information that would have been in coreinfo.tab - memory bus information
336+
:param device_dict: raw dictionary of information from tagged
337+
blocks in Simulink design, keyed on device name
338+
:param memorymap_dict: dictionary of information that would have been
339+
in coreinfo.tab - memory bus information
324340
:return:
325341
"""
326342
# create and add memory devices to the memory device dictionary
327343
for device_name, device_info in device_dict.items():
328344
if device_name == '':
329-
raise NameError('There\'s a problem somewhere, got a blank device name?')
345+
raise NameError('There\'s a problem somewhere, got a blank '
346+
'device name?')
330347
if device_name in self.memory_devices.keys():
331-
raise NameError('Memory device %s already exists.' % device_name)
348+
raise NameError('Memory device %s already exists' % device_name)
332349
# get the class from the known devices, if it exists there
333350
tag = device_info['tag']
334351
try:
@@ -338,16 +355,20 @@ def __create_memory_devices(self, device_dict, memorymap_dict):
338355
pass
339356
else:
340357
if not callable(known_device_class):
341-
raise TypeError('%s is not a callable Memory class - that\'s a problem.' % known_device_class)
342-
new_device = known_device_class.from_device_info(self, device_name, device_info, memorymap_dict)
358+
raise TypeError('%s is not a callable Memory class - '
359+
'that\'s a problem.' % known_device_class)
360+
new_device = known_device_class.from_device_info(
361+
self, device_name, device_info, memorymap_dict)
343362
if new_device.name in self.memory_devices.keys():
344-
raise NameError('Device called %s of type %s already exists in devices list.' %
345-
(new_device.name, type(new_device)))
363+
raise NameError(
364+
'Device called %s of type %s already exists in '
365+
'devices list.' % (new_device.name, type(new_device)))
346366
self.devices[device_name] = new_device
347367
self.memory_devices[device_name] = new_device
348368
container = getattr(self, known_device_container)
349369
setattr(container, device_name, new_device)
350-
assert id(getattr(container, device_name)) == id(new_device) == id(self.memory_devices[device_name])
370+
assert id(getattr(container, device_name)) == id(new_device)
371+
assert id(new_device) == id(self.memory_devices[device_name])
351372
# allow created devices to update themselves with full device info
352373
# link control registers, etc
353374
for name, device in self.memory_devices.items():
@@ -359,46 +380,53 @@ def __create_memory_devices(self, device_dict, memorymap_dict):
359380
def __create_other_devices(self, device_dict):
360381
"""
361382
Store non-memory device information in a dictionary
362-
:param device_dict: raw dictionary of information from tagged blocks in Simulink design, keyed on device name
383+
:param device_dict: raw dictionary of information from tagged
384+
blocks in Simulink design, keyed on device name
363385
:return:
364386
"""
365387
for device_name, device_info in device_dict.items():
366388
if device_name == '':
367-
raise NameError('There\'s a problem somewhere, got a blank device name?')
389+
raise NameError('There\'s a problem somewhere, got a '
390+
'blank device name?')
368391
if device_name in self.other_devices.keys():
369392
raise NameError('Other device %s already exists.' % device_name)
370393
if device_info['tag'] in CASPER_OTHER_DEVICES.keys():
371394
self.devices[device_name] = device_info
372395
self.other_devices[device_name] = device_info
373396

374397
def device_names_by_container(self, container_name):
375-
"""Return a list of devices in a certain container.
376398
"""
377-
return [devname for devname, container in self.memory_devices.iteritems() if container == container_name]
399+
Return a list of devices in a certain container.
400+
"""
401+
return [devname for devname, container
402+
in self.memory_devices.iteritems()
403+
if container == container_name]
378404

379405
def devices_by_container(self, container):
380-
"""Get devices using container type.
406+
"""
407+
Get devices using container type.
381408
"""
382409
return getattr(self, container)
383410

384411
def get_system_information(self, filename=None, fpg_info=None):
385412
"""
386413
Get information about the design running on the FPGA.
387-
If filename is given, get it from there, otherwise query the host via KATCP.
414+
If filename is given, get it from file, otherwise query the host via KATCP.
388415
:param filename: fpg filename
389416
:param fpg_info: a tuple containing device_info and coreinfo dictionaries
390417
:return: <nothing> the information is populated in the class
391418
"""
392419
if (filename is None) and (fpg_info is None):
393-
raise RuntimeError('Either filename or parsed fpg data must be given.')
420+
raise RuntimeError('Either filename or parsed fpg data '
421+
'must be given.')
394422
if filename is not None:
395423
device_dict, memorymap_dict = parse_fpg(filename)
396424
else:
397425
device_dict = fpg_info[0]
398426
memorymap_dict = fpg_info[1]
399427
# add system registers
400428
device_dict.update(self.__add_sys_registers())
401-
# reset current devices and create new ones from the new design information
429+
# reset current devices, create new ones from the new design information
402430
self.__reset_device_info()
403431
self.__create_memory_devices(device_dict, memorymap_dict)
404432
self.__create_other_devices(device_dict)
@@ -424,11 +452,38 @@ def estimate_fpga_clock(self):
424452
secondpass += (2**32)
425453
return (secondpass - firstpass) / 2000000.0
426454

455+
def check_tx_raw(self, wait_time=0.2, checks=10):
456+
"""
457+
Check to see whether this host is transmitting packets without
458+
error on all its GBE interfaces.
459+
:param wait_time: seconds to wait between checks
460+
:param checks: times to run check
461+
:return:
462+
"""
463+
for gbecore in self.tengbes:
464+
if not gbecore.tx_okay(wait_time=wait_time, checks=checks):
465+
return False
466+
return True
467+
468+
def check_rx_raw(self, wait_time=0.2, checks=10):
469+
"""
470+
Check to see whether this host is receiving packets without
471+
error on all its GBE interfaces.
472+
:param wait_time: seconds to wait between checks
473+
:param checks: times to run check
474+
:return:
475+
"""
476+
for gbecore in self.tengbes:
477+
if not gbecore.rx_okay(wait_time=wait_time, checks=checks):
478+
return False
479+
return True
480+
427481
@staticmethod
428482
def __add_sys_registers():
429-
standard_reg = {'tag': 'xps:sw_reg', 'mode': 'one value', 'io_dir': 'To Processor',
430-
'io_delay': '1', 'sample_period': '1', 'sim_port': 'off', 'show_format': 'off',
431-
'names': 'reg', 'bitwidths': '32', 'arith_types': '0', 'bin_pts': '0'}
483+
standard_reg = {'tag': 'xps:sw_reg', 'io_dir': 'To Processor',
484+
'io_delay': '1', 'sample_period': '1', 'names': 'reg',
485+
'bitwidths': '32', 'bin_pts': '0', 'arith_types': '0',
486+
'sim_port': 'off', 'show_format': 'off', }
432487
sys_registers = {'sys_board_id': standard_reg.copy(),
433488
'sys_rev': standard_reg.copy(),
434489
'sys_rev_rcs': standard_reg.copy(),

src/katcp_fpga.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,15 @@ def _read_design_info_from_host(self, device=None):
598598
metalist = []
599599
for inform in informs:
600600
if len(inform.arguments) < 4:
601-
raise ValueError('Incorrect number of meta inform '
601+
if len(inform.arguments) == 3:
602+
LOGGER.warn('Incorrect number of meta inform '
603+
'arguments, missing value '
604+
'field: %s' % str(inform.arguments))
605+
inform.arguments.append('-1')
606+
else:
607+
LOGGER.error('FEWER than THREE meta inform '
602608
'arguments: %s' % str(inform.arguments))
609+
continue
603610
for arg in inform.arguments:
604611
arg = arg.replace('\_', ' ')
605612
name = inform.arguments[0]

0 commit comments

Comments
 (0)