Skip to content

Commit

Permalink
Merge pull request #50 from ska-sa/devel
Browse files Browse the repository at this point in the history
Merge devel into master for AR1.3
  • Loading branch information
jmanley authored Jun 21, 2016
2 parents 2dcffca + ce42306 commit 0edc8d4
Show file tree
Hide file tree
Showing 6 changed files with 334 additions and 151 deletions.
44 changes: 27 additions & 17 deletions scripts/casperfpga_tengbe_coreinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,28 @@
except ImportError:
corr2 = None

parser = argparse.ArgumentParser(description='Display TenGBE interface information about a MeerKAT fpga host.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--hosts', dest='hosts', type=str, action='store', default='',
help='comma-delimited list of hosts, or a corr2 config file')
parser.add_argument('-c', '--core', dest='core', action='store', default='all', type=str,
help='which core to query')
parser.add_argument('--arp', dest='arp', action='store_true', default=False,
help='print the ARP table')
parser.add_argument('--cpu', dest='cpu', action='store_true', default=False,
help='print the CPU details')
parser.add_argument('--comms', dest='comms', action='store', default='katcp', type=str,
help='katcp (default) or dcp?')
parser.add_argument('--loglevel', dest='log_level', action='store', default='',
help='log level to use, default None, options INFO, DEBUG, ERROR')
parser = argparse.ArgumentParser(
description='Display TenGBE interface information '
'about a MeerKAT fpga host.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument(
'--hosts', dest='hosts', type=str, action='store', default='',
help='comma-delimited list of hosts, or a corr2 config file')
parser.add_argument(
'-c', '--core', dest='core', action='store', default='all', type=str,
help='which core to query')
parser.add_argument(
'--arp', dest='arp', action='store_true', default=False,
help='print the ARP table')
parser.add_argument(
'--cpu', dest='cpu', action='store_true', default=False,
help='print the CPU details')
parser.add_argument(
'--comms', dest='comms', action='store', default='katcp', type=str,
help='katcp (default) or dcp?')
parser.add_argument(
'--loglevel', dest='log_level', action='store', default='',
help='log level to use, default None, options INFO, DEBUG, ERROR')
args = parser.parse_args()

if args.log_level != '':
Expand Down Expand Up @@ -65,8 +73,9 @@
numgbes = len(fpga.tengbes)
if numgbes < 1:
raise RuntimeWarning('Host %s has no 10gbe cores', fpga.host)
print '%s: found %i 10gbe core%s.' % (fpga.host, numgbes, '' if numgbes == 1 else 's')

print '%s: found %i 10gbe core%s.' % (fpga.host,
numgbes,
'' if numgbes == 1 else 's')

for fpga in fpgas:
if args.core == 'all':
Expand All @@ -77,7 +86,8 @@
print '%s:' % fpga.host
print 50*'#'
for core in cores:
fpga.tengbes[core].print_10gbe_core_details(arp=args.arp, cpu=args.cpu, refresh=True)
fpga.tengbes[core].print_10gbe_core_details(arp=args.arp, cpu=args.cpu,
refresh=True)

# handle exits cleanly
utils.threaded_fpga_function(fpgas, 10, 'disconnect')
Expand Down
40 changes: 23 additions & 17 deletions scripts/casperfpga_tengbe_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,15 @@ def get_gbe_data(fpga):
"""
returndata = {}
for gbecore in fpga.tengbes:
returndata[gbecore.name] = gbecore.read_counters()
ctr_data = gbecore.read_counters()
for regname in ctr_data:
regdata = ctr_data[regname]
try:
if ('timestamp' in regdata.keys()) and ('data' in regdata.keys()):
ctr_data[regname] = regdata['data']['reg']
except AttributeError:
pass
returndata[gbecore.name] = ctr_data
return returndata


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

# get gbe and tap data
tap_data = utils.threaded_fpga_operation(fpgas, 10, get_tap_data)
gbe_data = utils.threaded_fpga_operation(fpgas, 10, get_gbe_data)
# print gbe_data['roach020956']['gbe0'].keys()
tap_data = utils.threaded_fpga_operation(fpgas, 15, get_tap_data)
gbe_data = utils.threaded_fpga_operation(fpgas, 15, get_gbe_data)
# for fpga in gbe_data:
# fpga_data = gbe_data[fpga]
# print fpga, ':'
# for gbe in fpga_data:
# print gbe, ':'
# print fpga_data[gbe]
# utils.threaded_fpga_function(fpgas, 10, 'disconnect')
# sys.exit()

Expand Down Expand Up @@ -185,26 +198,19 @@ def exit_gracefully(sig, frame):
fpga_data = gbe_data[fpga.host]
scroller.add_line(fpga.host)
for core, core_data in fpga_data.items():
fpga_data[core]['tap_running'] = {
'data': {
'reg': not(tap_data[fpga.host][core]['name'] == '')
}
}
fpga_data[core]['ip'] = {
'data': {
'reg': tap_data[fpga.host][core]['ip']
}
}
tap_running = tap_data[fpga.host][core]['name'] == ''
fpga_data[core]['tap_running'] = not tap_running
fpga_data[core]['ip'] = tap_data[fpga.host][core]['ip']
start_pos = 20
scroller.add_line(core, 5)
for header_register in fpga_headers[0]:
core_regname = header_register.replace('gbe', core)
if start_pos < 200:
if core_regname in core_data.keys():
if not isinstance(core_data[core_regname]['data']['reg'], str):
regval = '%d' % core_data[core_regname]['data']['reg']
if not isinstance(core_data[core_regname], str):
regval = '%d' % core_data[core_regname]
else:
regval = core_data[core_regname]['data']['reg']
regval = core_data[core_regname]
else:
regval = 'n/a'
# all on the same line
Expand Down
95 changes: 75 additions & 20 deletions src/casperfpga.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ def __init__(self, host):
:return:
"""
self.host = host

# this is just for code introspection
self.devices = None
self.memory_devices = None
self.other_devices = None
self.sbrams = None
self.qdrs = None
self.registers = None
self.tengbes = None
self.snapshots = None
self.system_info = None
self.rcs_info = None
# /just for introspection

self.__reset_device_info()
LOGGER.debug('%s: now a CasperFpga' % self.host)

Expand Down Expand Up @@ -319,16 +333,19 @@ def write_int(self, device_name, integer, blindwrite=False, word_offset=0):
def __create_memory_devices(self, device_dict, memorymap_dict):
"""
Create memory devices from dictionaries of design information.
:param device_dict: raw dictionary of information from tagged blocks in Simulink design, keyed on device name
:param memorymap_dict: dictionary of information that would have been in coreinfo.tab - memory bus information
:param device_dict: raw dictionary of information from tagged
blocks in Simulink design, keyed on device name
:param memorymap_dict: dictionary of information that would have been
in coreinfo.tab - memory bus information
:return:
"""
# create and add memory devices to the memory device dictionary
for device_name, device_info in device_dict.items():
if device_name == '':
raise NameError('There\'s a problem somewhere, got a blank device name?')
raise NameError('There\'s a problem somewhere, got a blank '
'device name?')
if device_name in self.memory_devices.keys():
raise NameError('Memory device %s already exists.' % device_name)
raise NameError('Memory device %s already exists' % device_name)
# get the class from the known devices, if it exists there
tag = device_info['tag']
try:
Expand All @@ -338,16 +355,20 @@ def __create_memory_devices(self, device_dict, memorymap_dict):
pass
else:
if not callable(known_device_class):
raise TypeError('%s is not a callable Memory class - that\'s a problem.' % known_device_class)
new_device = known_device_class.from_device_info(self, device_name, device_info, memorymap_dict)
raise TypeError('%s is not a callable Memory class - '
'that\'s a problem.' % known_device_class)
new_device = known_device_class.from_device_info(
self, device_name, device_info, memorymap_dict)
if new_device.name in self.memory_devices.keys():
raise NameError('Device called %s of type %s already exists in devices list.' %
(new_device.name, type(new_device)))
raise NameError(
'Device called %s of type %s already exists in '
'devices list.' % (new_device.name, type(new_device)))
self.devices[device_name] = new_device
self.memory_devices[device_name] = new_device
container = getattr(self, known_device_container)
setattr(container, device_name, new_device)
assert id(getattr(container, device_name)) == id(new_device) == id(self.memory_devices[device_name])
assert id(getattr(container, device_name)) == id(new_device)
assert id(new_device) == id(self.memory_devices[device_name])
# allow created devices to update themselves with full device info
# link control registers, etc
for name, device in self.memory_devices.items():
Expand All @@ -359,46 +380,53 @@ def __create_memory_devices(self, device_dict, memorymap_dict):
def __create_other_devices(self, device_dict):
"""
Store non-memory device information in a dictionary
:param device_dict: raw dictionary of information from tagged blocks in Simulink design, keyed on device name
:param device_dict: raw dictionary of information from tagged
blocks in Simulink design, keyed on device name
:return:
"""
for device_name, device_info in device_dict.items():
if device_name == '':
raise NameError('There\'s a problem somewhere, got a blank device name?')
raise NameError('There\'s a problem somewhere, got a '
'blank device name?')
if device_name in self.other_devices.keys():
raise NameError('Other device %s already exists.' % device_name)
if device_info['tag'] in CASPER_OTHER_DEVICES.keys():
self.devices[device_name] = device_info
self.other_devices[device_name] = device_info

def device_names_by_container(self, container_name):
"""Return a list of devices in a certain container.
"""
return [devname for devname, container in self.memory_devices.iteritems() if container == container_name]
Return a list of devices in a certain container.
"""
return [devname for devname, container
in self.memory_devices.iteritems()
if container == container_name]

def devices_by_container(self, container):
"""Get devices using container type.
"""
Get devices using container type.
"""
return getattr(self, container)

def get_system_information(self, filename=None, fpg_info=None):
"""
Get information about the design running on the FPGA.
If filename is given, get it from there, otherwise query the host via KATCP.
If filename is given, get it from file, otherwise query the host via KATCP.
:param filename: fpg filename
:param fpg_info: a tuple containing device_info and coreinfo dictionaries
:return: <nothing> the information is populated in the class
"""
if (filename is None) and (fpg_info is None):
raise RuntimeError('Either filename or parsed fpg data must be given.')
raise RuntimeError('Either filename or parsed fpg data '
'must be given.')
if filename is not None:
device_dict, memorymap_dict = parse_fpg(filename)
else:
device_dict = fpg_info[0]
memorymap_dict = fpg_info[1]
# add system registers
device_dict.update(self.__add_sys_registers())
# reset current devices and create new ones from the new design information
# reset current devices, create new ones from the new design information
self.__reset_device_info()
self.__create_memory_devices(device_dict, memorymap_dict)
self.__create_other_devices(device_dict)
Expand All @@ -424,11 +452,38 @@ def estimate_fpga_clock(self):
secondpass += (2**32)
return (secondpass - firstpass) / 2000000.0

def check_tx_raw(self, wait_time=0.2, checks=10):
"""
Check to see whether this host is transmitting packets without
error on all its GBE interfaces.
:param wait_time: seconds to wait between checks
:param checks: times to run check
:return:
"""
for gbecore in self.tengbes:
if not gbecore.tx_okay(wait_time=wait_time, checks=checks):
return False
return True

def check_rx_raw(self, wait_time=0.2, checks=10):
"""
Check to see whether this host is receiving packets without
error on all its GBE interfaces.
:param wait_time: seconds to wait between checks
:param checks: times to run check
:return:
"""
for gbecore in self.tengbes:
if not gbecore.rx_okay(wait_time=wait_time, checks=checks):
return False
return True

@staticmethod
def __add_sys_registers():
standard_reg = {'tag': 'xps:sw_reg', 'mode': 'one value', 'io_dir': 'To Processor',
'io_delay': '1', 'sample_period': '1', 'sim_port': 'off', 'show_format': 'off',
'names': 'reg', 'bitwidths': '32', 'arith_types': '0', 'bin_pts': '0'}
standard_reg = {'tag': 'xps:sw_reg', 'io_dir': 'To Processor',
'io_delay': '1', 'sample_period': '1', 'names': 'reg',
'bitwidths': '32', 'bin_pts': '0', 'arith_types': '0',
'sim_port': 'off', 'show_format': 'off', }
sys_registers = {'sys_board_id': standard_reg.copy(),
'sys_rev': standard_reg.copy(),
'sys_rev_rcs': standard_reg.copy(),
Expand Down
9 changes: 8 additions & 1 deletion src/katcp_fpga.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,8 +598,15 @@ def _read_design_info_from_host(self, device=None):
metalist = []
for inform in informs:
if len(inform.arguments) < 4:
raise ValueError('Incorrect number of meta inform '
if len(inform.arguments) == 3:
LOGGER.warn('Incorrect number of meta inform '
'arguments, missing value '
'field: %s' % str(inform.arguments))
inform.arguments.append('-1')
else:
LOGGER.error('FEWER than THREE meta inform '
'arguments: %s' % str(inform.arguments))
continue
for arg in inform.arguments:
arg = arg.replace('\_', ' ')
name = inform.arguments[0]
Expand Down
Loading

0 comments on commit 0edc8d4

Please sign in to comment.