Commit 588e0728 authored by Jason Manley's avatar Jason Manley
Browse files

Merge branch 'devel'

parents 0f04f12e 39c17eb2
......@@ -40,6 +40,15 @@ class AttributeContainer(object):
def next(self): # Python 2 compat
return self.__next__()
def remove_attribute(self, attribute):
"""
Remove an attribute from this container by name.
:param attribute: the name of the attribute to remove
:return:
"""
self._items.pop(self._items.index(attribute))
self.__delattr__(attribute)
def clear(self):
self.__dict__.clear()
self._next_item = 0
......
......@@ -23,7 +23,8 @@ CASPER_MEMORY_DEVICES = {
'xps:qdr': {'class': qdr.Qdr, 'container': 'qdrs'},
'xps:sw_reg': {'class': register.Register, 'container': 'registers'},
'xps:tengbe_v2': {'class': tengbe.TenGbe, 'container': 'tengbes'},
'casper:snapshot': {'class': snap.Snap, 'container': 'snapshots'},}
'casper:snapshot': {'class': snap.Snap, 'container': 'snapshots'},
}
# other devices - blocks that aren't memory devices, but about which we'd like to know
......@@ -260,13 +261,13 @@ class CasperFpga(object):
rv['compile_timestamp'] = lib & ((2 ** 31)-1)
else:
if lib & (1 << 30):
#type is svn
# type is svn
rv['lib_rcs_type'] = 'svn'
else:
#type is git
# type is git
rv['lib_rcs_type'] = 'git'
if lib & (1 << 28):
#dirty bit
# dirty bit
rv['lib_dirty'] = True
else:
rv['lib_dirty'] = False
......@@ -275,13 +276,13 @@ class CasperFpga(object):
rv['app_last_modified'] = app & ((2 ** 31)-1)
else:
if app & (1 << 30):
#type is svn
# type is svn
rv['app_rcs_type'] = 'svn'
else:
#type is git
# type is git
rv['app_rcs_type'] = 'git'
if app & (1 << 28):
#dirty bit
# dirty bit
rv['app_dirty'] = True
else:
rv['lib_dirty'] = False
......
......@@ -5,6 +5,8 @@ import os
import threading
import Queue
import random
import socket
import async_requester
from casperfpga import CasperFpga
......@@ -17,8 +19,18 @@ if hasattr(katcp.CallbackClient, 'MAX_MSG_SIZE'):
setattr(katcp.CallbackClient, 'MAX_MSG_SIZE',
katcp.CallbackClient.MAX_MSG_SIZE * 10)
class KatcpRequestError(RuntimeError):
"""Exception that is raised when a KATCP request fails when it should not"""
"""An error occurred processing a KATCP request."""
class KatcpRequestInvalid(RuntimeError):
"""An invalid KATCP request was made."""
class KatcpRequestFail(RuntimeError):
"""A valid KATCP request failed."""
def sendfile(filename, targethost, port, result_queue, timeout=2):
"""
......@@ -29,7 +41,6 @@ def sendfile(filename, targethost, port, result_queue, timeout=2):
:param result_queue: the result of the upload, nothing '' indicates success
:return:
"""
import socket
upload_socket = socket.socket()
stime = time.time()
connected = False
......@@ -45,16 +56,16 @@ def sendfile(filename, targethost, port, result_queue, timeout=2):
upload_socket.send(open(filename).read())
except:
result_queue.put('Could not send file to upload port.')
else:
result_queue.put('')
finally:
LOGGER.info('%s: upload thread complete at %.3f' %
(targethost, time.time()))
result_queue.put('')
return
class KatcpFpga(CasperFpga, async_requester.AsyncRequester, katcp.CallbackClient):
def __init__(self, host, port=7147, timeout=5.0, connect=True):
def __init__(self, host, port=7147, timeout=20.0, connect=True):
async_requester.AsyncRequester.__init__(self, host, self.callback_request, max_requests=100)
katcp.CallbackClient.__init__(self, host, port, tb_limit=20, timeout=timeout,
logger=LOGGER, auto_reconnect=True)
......@@ -120,9 +131,21 @@ class KatcpFpga(CasperFpga, async_requester.AsyncRequester, katcp.CallbackClient
request = katcp.Message.request(name, *request_args)
reply, informs = self.blocking_request(request, timeout=request_timeout)
if (reply.arguments[0] != katcp.Message.OK) and require_ok:
raise KatcpRequestError(
'Request %s on host %s failed.\n\tRequest: %s\n\tReply: %s' %
(request.name, self.host, request, reply))
if reply.arguments[0] == katcp.Message.FAIL:
raise KatcpRequestFail(
'Request %s on host %s failed.\n\t'
'Request: %s\n\tReply: %s' %
(request.name, self.host, request, reply))
elif reply.arguments[0] == katcp.Message.INVALID:
raise KatcpRequestInvalid(
'Invalid katcp request %s on host %s.\n\t'
'Request: %s\n\tReply: %s' %
(request.name, self.host, request, reply))
else:
raise KatcpRequestError(
'Unknown error processing request %s on host '
'%s.\n\tRequest: %s\n\tReply: %s' %
(request.name, self.host, request, reply))
return reply, informs
def listdev(self, getsize=False, getaddress=False):
......@@ -342,6 +365,8 @@ class KatcpFpga(CasperFpga, async_requester.AsyncRequester, katcp.CallbackClient
result_queue.put('Request to client %s returned, but not Message.OK.' % self.host)
except:
result_queue.put('Request to client %s failed.' % self.host)
finally:
LOGGER.debug('progremote thread done')
if port == -1:
port = random.randint(2000, 2500)
......@@ -482,9 +507,9 @@ class KatcpFpga(CasperFpga, async_requester.AsyncRequester, katcp.CallbackClient
"""
LOGGER.debug('%s: reading designinfo' % self.host)
if device is None:
reply, informs = self.katcprequest(name='meta', request_timeout=5.0, require_ok=True)
reply, informs = self.katcprequest(name='meta', request_timeout=10.0, require_ok=True)
else:
reply, informs = self.katcprequest(name='meta', request_timeout=5.0, require_ok=True,
reply, informs = self.katcprequest(name='meta', request_timeout=10.0, require_ok=True,
request_args=(device, ))
if reply.arguments[0] != 'ok':
raise RuntimeError('Could not read meta information from %s' % self.host)
......
......@@ -294,7 +294,9 @@ class Qdr(Memory):
def qdr_cal(self, fail_hard=True, verbosity=0):
"""
Calibrates a QDR controller, stepping input delays and (if that fails) output delays. Returns True if calibrated, raises a runtime exception if it doesn't.
Calibrates a QDR controller, stepping input delays and (if that fails)
output delays. Returns True if calibrated, raises a runtime
exception if it doesn't.
:param verbosity:
:return:
"""
......
......@@ -101,7 +101,8 @@ class Register(Memory):
new_values = {_field: None for _field in self.field_names()}
for k in kwargs:
if k not in new_values:
raise ValueError('Field {} not found in register {}'.format(k, self.name))
raise ValueError('Field {} not found in register {} on '
'host {}'.format(k, self.name, self.parent.host))
if kwargs[k] in ['pulse', 'toggle']:
_read_necessary = True
new_values[k] = kwargs[k]
......
......@@ -63,6 +63,20 @@ class Mac(object):
self.mac_str = self.mac2str(mac_int)
self.mac_int = mac_int
@classmethod
def from_roach_hostname(cls, hostname, port_num):
"""
Make a MAC address object from a ROACH hostname
"""
if not hostname.startswith('roach'):
raise RuntimeError('Only hostnames beginning with'
'roach supported: %s' % hostname)
digits = hostname.replace('roach', '')
serial = [int(digits[ctr:ctr+2], 16) for ctr in range(0, 6, 2)]
mac_str = 'fe:00:%02x:%02x:%02x:%02x' % (serial[0], serial[1],
serial[2], port_num)
return cls(mac_str)
def packed(self):
mac = [0, 0]
for byte in self.mac_str.split(':'):
......@@ -140,6 +154,7 @@ class IpAddress(object):
def __repr__(self):
return 'IpAddress(%s)' % self.__str__()
class TenGbe(Memory):
"""
To do with the CASPER ten GBE yellow block implemented on FPGAs,
......@@ -354,11 +369,13 @@ class TenGbe(Memory):
# #self.parent.write_int(self.name, self.port, offset = port_location)
def dhcp_start(self):
"""Configure this interface, then start a DHCP client on ALL interfaces"""
"""
Configure this interface, then start a DHCP client on ALL interfaces.
"""
if self.mac is None:
# TODO get MAC from EEPROM serial number and assign here
self.mac = '0'
reply, _ = self.parent.katcprequest(name="tap-start", request_timeout=15,
reply, _ = self.parent.katcprequest(name="tap-start", request_timeout=5,
require_ok=True,
request_args=(self.name, self.name, '0.0.0.0',
str(self.port), str(self.mac), ))
......@@ -371,7 +388,7 @@ class TenGbe(Memory):
if reply.arguments[0] != 'ok':
raise RuntimeError('%s: failure disabling ARP.' % self.name)
reply, _ = self.parent.katcprequest(name="tap-dhcp", request_timeout=15,
reply, _ = self.parent.katcprequest(name="tap-dhcp", request_timeout=30,
require_ok=True,
request_args=(self.name, ))
if reply.arguments[0] != 'ok':
......@@ -472,13 +489,9 @@ class TenGbe(Memory):
# mcast_group_string = ip_str + '+' + str(group_size)
mcast_group_string = ip_str
try:
reply, _ = self.parent.katcprequest("tap-multicast-add", -1, True,
request_args=(self.name, 'recv',
mcast_group_string, ))
except:
raise RuntimeError("%s: tap-multicast-add does not seem to be "
"supported on %s" % (self.name, self.parent.host))
reply, _ = self.parent.katcprequest("tap-multicast-add", -1, True,
request_args=(self.name, 'recv',
mcast_group_string, ))
if reply.arguments[0] == 'ok':
return
else:
......@@ -503,6 +516,47 @@ class TenGbe(Memory):
raise RuntimeError('%s: failed removing multicast address %s '
'from tap device' % (self.name, IpAddress.str2ip(ip_str)))
def _fabric_enable_disable(self, target_val):
word_bytes = list(struct.unpack('>4B', self.parent.read(self.name, 4, 0x20)))
if word_bytes[1] == target_val:
return
word_bytes[1] = target_val
word_packed = struct.pack('>4B', *word_bytes)
self.parent.write(self.name, word_packed, 0x20)
def fabric_enable(self):
"""
Enable the core fabric
:return:
"""
self._fabric_enable_disable(1)
def fabric_disable(self):
"""
Enable the core fabric
:return:
"""
self._fabric_enable_disable(0)
def fabric_soft_reset_toggle(self):
"""
Toggle the fabric soft reset
:return:
"""
word_bytes = list(struct.unpack('>4B', self.parent.read(self.name, 4, 0x20)))
def write_val(val):
word_bytes[0] = val
word_packed = struct.pack('>4B', *word_bytes)
if val == 0:
self.parent.write(self.name, word_packed, 0x20)
else:
self.parent.blindwrite(self.name, word_packed, 0x20)
if word_bytes[0] == 1:
write_val(0)
write_val(1)
write_val(0)
def get_10gbe_core_details(self, read_arp=False, read_cpu=False):
"""
Get 10GbE core details.
......
......@@ -205,7 +205,8 @@ def threaded_fpga_operation(fpga_list, timeout, target_function):
break
if len(returnval) != num_fpgas:
print returnval
raise RuntimeError('Given %d FPGAs, only got %d results, must have timed out.' % (num_fpgas, len(returnval)))
raise RuntimeError('Given %d FPGAs, only got %d results, must '
'have timed out.' % (num_fpgas, len(returnval)))
return returnval
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment