Skip to content

Commit 588e072

Browse files
author
Jason Manley
committed
Merge branch 'devel'
2 parents 0f04f12 + 39c17eb commit 588e072

File tree

7 files changed

+123
-30
lines changed

7 files changed

+123
-30
lines changed

src/attribute_container.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ def __next__(self):
4040
def next(self): # Python 2 compat
4141
return self.__next__()
4242

43+
def remove_attribute(self, attribute):
44+
"""
45+
Remove an attribute from this container by name.
46+
:param attribute: the name of the attribute to remove
47+
:return:
48+
"""
49+
self._items.pop(self._items.index(attribute))
50+
self.__delattr__(attribute)
51+
4352
def clear(self):
4453
self.__dict__.clear()
4554
self._next_item = 0

src/casperfpga.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
'xps:qdr': {'class': qdr.Qdr, 'container': 'qdrs'},
2424
'xps:sw_reg': {'class': register.Register, 'container': 'registers'},
2525
'xps:tengbe_v2': {'class': tengbe.TenGbe, 'container': 'tengbes'},
26-
'casper:snapshot': {'class': snap.Snap, 'container': 'snapshots'},}
26+
'casper:snapshot': {'class': snap.Snap, 'container': 'snapshots'},
27+
}
2728

2829

2930
# other devices - blocks that aren't memory devices, but about which we'd like to know
@@ -260,13 +261,13 @@ def get_rcs(self, rcs_block_name='rcs'):
260261
rv['compile_timestamp'] = lib & ((2 ** 31)-1)
261262
else:
262263
if lib & (1 << 30):
263-
#type is svn
264+
# type is svn
264265
rv['lib_rcs_type'] = 'svn'
265266
else:
266-
#type is git
267+
# type is git
267268
rv['lib_rcs_type'] = 'git'
268269
if lib & (1 << 28):
269-
#dirty bit
270+
# dirty bit
270271
rv['lib_dirty'] = True
271272
else:
272273
rv['lib_dirty'] = False
@@ -275,13 +276,13 @@ def get_rcs(self, rcs_block_name='rcs'):
275276
rv['app_last_modified'] = app & ((2 ** 31)-1)
276277
else:
277278
if app & (1 << 30):
278-
#type is svn
279+
# type is svn
279280
rv['app_rcs_type'] = 'svn'
280281
else:
281-
#type is git
282+
# type is git
282283
rv['app_rcs_type'] = 'git'
283284
if app & (1 << 28):
284-
#dirty bit
285+
# dirty bit
285286
rv['app_dirty'] = True
286287
else:
287288
rv['lib_dirty'] = False

src/katcp_fpga.py

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import threading
66
import Queue
77
import random
8+
import socket
9+
810

911
import async_requester
1012
from casperfpga import CasperFpga
@@ -17,8 +19,18 @@
1719
setattr(katcp.CallbackClient, 'MAX_MSG_SIZE',
1820
katcp.CallbackClient.MAX_MSG_SIZE * 10)
1921

22+
2023
class KatcpRequestError(RuntimeError):
21-
"""Exception that is raised when a KATCP request fails when it should not"""
24+
"""An error occurred processing a KATCP request."""
25+
26+
27+
class KatcpRequestInvalid(RuntimeError):
28+
"""An invalid KATCP request was made."""
29+
30+
31+
class KatcpRequestFail(RuntimeError):
32+
"""A valid KATCP request failed."""
33+
2234

2335
def sendfile(filename, targethost, port, result_queue, timeout=2):
2436
"""
@@ -29,7 +41,6 @@ def sendfile(filename, targethost, port, result_queue, timeout=2):
2941
:param result_queue: the result of the upload, nothing '' indicates success
3042
:return:
3143
"""
32-
import socket
3344
upload_socket = socket.socket()
3445
stime = time.time()
3546
connected = False
@@ -45,16 +56,16 @@ def sendfile(filename, targethost, port, result_queue, timeout=2):
4556
upload_socket.send(open(filename).read())
4657
except:
4758
result_queue.put('Could not send file to upload port.')
59+
else:
60+
result_queue.put('')
4861
finally:
4962
LOGGER.info('%s: upload thread complete at %.3f' %
5063
(targethost, time.time()))
51-
result_queue.put('')
52-
return
5364

5465

5566
class KatcpFpga(CasperFpga, async_requester.AsyncRequester, katcp.CallbackClient):
5667

57-
def __init__(self, host, port=7147, timeout=5.0, connect=True):
68+
def __init__(self, host, port=7147, timeout=20.0, connect=True):
5869
async_requester.AsyncRequester.__init__(self, host, self.callback_request, max_requests=100)
5970
katcp.CallbackClient.__init__(self, host, port, tb_limit=20, timeout=timeout,
6071
logger=LOGGER, auto_reconnect=True)
@@ -120,9 +131,21 @@ def katcprequest(self, name, request_timeout=-1.0, require_ok=True, request_args
120131
request = katcp.Message.request(name, *request_args)
121132
reply, informs = self.blocking_request(request, timeout=request_timeout)
122133
if (reply.arguments[0] != katcp.Message.OK) and require_ok:
123-
raise KatcpRequestError(
124-
'Request %s on host %s failed.\n\tRequest: %s\n\tReply: %s' %
125-
(request.name, self.host, request, reply))
134+
if reply.arguments[0] == katcp.Message.FAIL:
135+
raise KatcpRequestFail(
136+
'Request %s on host %s failed.\n\t'
137+
'Request: %s\n\tReply: %s' %
138+
(request.name, self.host, request, reply))
139+
elif reply.arguments[0] == katcp.Message.INVALID:
140+
raise KatcpRequestInvalid(
141+
'Invalid katcp request %s on host %s.\n\t'
142+
'Request: %s\n\tReply: %s' %
143+
(request.name, self.host, request, reply))
144+
else:
145+
raise KatcpRequestError(
146+
'Unknown error processing request %s on host '
147+
'%s.\n\tRequest: %s\n\tReply: %s' %
148+
(request.name, self.host, request, reply))
126149
return reply, informs
127150

128151
def listdev(self, getsize=False, getaddress=False):
@@ -342,6 +365,8 @@ def makerequest(result_queue):
342365
result_queue.put('Request to client %s returned, but not Message.OK.' % self.host)
343366
except:
344367
result_queue.put('Request to client %s failed.' % self.host)
368+
finally:
369+
LOGGER.debug('progremote thread done')
345370

346371
if port == -1:
347372
port = random.randint(2000, 2500)
@@ -482,9 +507,9 @@ def _read_design_info_from_host(self, device=None):
482507
"""
483508
LOGGER.debug('%s: reading designinfo' % self.host)
484509
if device is None:
485-
reply, informs = self.katcprequest(name='meta', request_timeout=5.0, require_ok=True)
510+
reply, informs = self.katcprequest(name='meta', request_timeout=10.0, require_ok=True)
486511
else:
487-
reply, informs = self.katcprequest(name='meta', request_timeout=5.0, require_ok=True,
512+
reply, informs = self.katcprequest(name='meta', request_timeout=10.0, require_ok=True,
488513
request_args=(device, ))
489514
if reply.arguments[0] != 'ok':
490515
raise RuntimeError('Could not read meta information from %s' % self.host)

src/qdr.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,9 @@ def apply_cals(self,in_delays,out_delays,clk_delay,verbosity=0):
294294

295295
def qdr_cal(self, fail_hard=True, verbosity=0):
296296
"""
297-
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.
297+
Calibrates a QDR controller, stepping input delays and (if that fails)
298+
output delays. Returns True if calibrated, raises a runtime
299+
exception if it doesn't.
298300
:param verbosity:
299301
:return:
300302
"""

src/register.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ def _write_common(self, **kwargs):
101101
new_values = {_field: None for _field in self.field_names()}
102102
for k in kwargs:
103103
if k not in new_values:
104-
raise ValueError('Field {} not found in register {}'.format(k, self.name))
104+
raise ValueError('Field {} not found in register {} on '
105+
'host {}'.format(k, self.name, self.parent.host))
105106
if kwargs[k] in ['pulse', 'toggle']:
106107
_read_necessary = True
107108
new_values[k] = kwargs[k]

src/tengbe.py

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,20 @@ def __init__(self, mac):
6363
self.mac_str = self.mac2str(mac_int)
6464
self.mac_int = mac_int
6565

66+
@classmethod
67+
def from_roach_hostname(cls, hostname, port_num):
68+
"""
69+
Make a MAC address object from a ROACH hostname
70+
"""
71+
if not hostname.startswith('roach'):
72+
raise RuntimeError('Only hostnames beginning with'
73+
'roach supported: %s' % hostname)
74+
digits = hostname.replace('roach', '')
75+
serial = [int(digits[ctr:ctr+2], 16) for ctr in range(0, 6, 2)]
76+
mac_str = 'fe:00:%02x:%02x:%02x:%02x' % (serial[0], serial[1],
77+
serial[2], port_num)
78+
return cls(mac_str)
79+
6680
def packed(self):
6781
mac = [0, 0]
6882
for byte in self.mac_str.split(':'):
@@ -140,6 +154,7 @@ def __str__(self):
140154
def __repr__(self):
141155
return 'IpAddress(%s)' % self.__str__()
142156

157+
143158
class TenGbe(Memory):
144159
"""
145160
To do with the CASPER ten GBE yellow block implemented on FPGAs,
@@ -354,11 +369,13 @@ def tx_okay(self, wait_time=1):
354369
# #self.parent.write_int(self.name, self.port, offset = port_location)
355370

356371
def dhcp_start(self):
357-
"""Configure this interface, then start a DHCP client on ALL interfaces"""
372+
"""
373+
Configure this interface, then start a DHCP client on ALL interfaces.
374+
"""
358375
if self.mac is None:
359376
# TODO get MAC from EEPROM serial number and assign here
360377
self.mac = '0'
361-
reply, _ = self.parent.katcprequest(name="tap-start", request_timeout=15,
378+
reply, _ = self.parent.katcprequest(name="tap-start", request_timeout=5,
362379
require_ok=True,
363380
request_args=(self.name, self.name, '0.0.0.0',
364381
str(self.port), str(self.mac), ))
@@ -371,7 +388,7 @@ def dhcp_start(self):
371388
if reply.arguments[0] != 'ok':
372389
raise RuntimeError('%s: failure disabling ARP.' % self.name)
373390

374-
reply, _ = self.parent.katcprequest(name="tap-dhcp", request_timeout=15,
391+
reply, _ = self.parent.katcprequest(name="tap-dhcp", request_timeout=30,
375392
require_ok=True,
376393
request_args=(self.name, ))
377394
if reply.arguments[0] != 'ok':
@@ -472,13 +489,9 @@ def multicast_receive(self, ip_str, group_size):
472489

473490
# mcast_group_string = ip_str + '+' + str(group_size)
474491
mcast_group_string = ip_str
475-
try:
476-
reply, _ = self.parent.katcprequest("tap-multicast-add", -1, True,
477-
request_args=(self.name, 'recv',
478-
mcast_group_string, ))
479-
except:
480-
raise RuntimeError("%s: tap-multicast-add does not seem to be "
481-
"supported on %s" % (self.name, self.parent.host))
492+
reply, _ = self.parent.katcprequest("tap-multicast-add", -1, True,
493+
request_args=(self.name, 'recv',
494+
mcast_group_string, ))
482495
if reply.arguments[0] == 'ok':
483496
return
484497
else:
@@ -503,6 +516,47 @@ def multicast_remove(self, ip_str):
503516
raise RuntimeError('%s: failed removing multicast address %s '
504517
'from tap device' % (self.name, IpAddress.str2ip(ip_str)))
505518

519+
def _fabric_enable_disable(self, target_val):
520+
word_bytes = list(struct.unpack('>4B', self.parent.read(self.name, 4, 0x20)))
521+
if word_bytes[1] == target_val:
522+
return
523+
word_bytes[1] = target_val
524+
word_packed = struct.pack('>4B', *word_bytes)
525+
self.parent.write(self.name, word_packed, 0x20)
526+
527+
def fabric_enable(self):
528+
"""
529+
Enable the core fabric
530+
:return:
531+
"""
532+
self._fabric_enable_disable(1)
533+
534+
def fabric_disable(self):
535+
"""
536+
Enable the core fabric
537+
:return:
538+
"""
539+
self._fabric_enable_disable(0)
540+
541+
def fabric_soft_reset_toggle(self):
542+
"""
543+
Toggle the fabric soft reset
544+
:return:
545+
"""
546+
word_bytes = list(struct.unpack('>4B', self.parent.read(self.name, 4, 0x20)))
547+
548+
def write_val(val):
549+
word_bytes[0] = val
550+
word_packed = struct.pack('>4B', *word_bytes)
551+
if val == 0:
552+
self.parent.write(self.name, word_packed, 0x20)
553+
else:
554+
self.parent.blindwrite(self.name, word_packed, 0x20)
555+
if word_bytes[0] == 1:
556+
write_val(0)
557+
write_val(1)
558+
write_val(0)
559+
506560
def get_10gbe_core_details(self, read_arp=False, read_cpu=False):
507561
"""
508562
Get 10GbE core details.

src/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ def jobfunc(resultq, fpga):
205205
break
206206
if len(returnval) != num_fpgas:
207207
print returnval
208-
raise RuntimeError('Given %d FPGAs, only got %d results, must have timed out.' % (num_fpgas, len(returnval)))
208+
raise RuntimeError('Given %d FPGAs, only got %d results, must '
209+
'have timed out.' % (num_fpgas, len(returnval)))
209210
return returnval
210211

211212

0 commit comments

Comments
 (0)