Skip to content

Commit 0f04f12

Browse files
committed
Merge pull request #30 from ska-sa/devel
Devel merge to master for RTS release
2 parents a2b11ba + be31ea9 commit 0f04f12

19 files changed

+818
-529
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@
2525
# compiled python
2626
*.pyc
2727

28+
# pycharm files
29+
.idea/

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,10 @@ casperfpga
22
==========
33

44
Software control for CASPER FPGAs
5+
6+
7+
Release notes-ish
8+
-----------------
9+
10+
* [2015-05-19 Tue] Requires rootfs 8dff433-2015-05-18 (or newer?) for the
11+
updated ?tap-multicast-remove request

casperfpga

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
src

scripts/casperfpga_tengbe_coreinfo.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99
1010
@author: paulp
1111
"""
12-
import sys
13-
import time
1412
import argparse
15-
import signal
1613

1714
from casperfpga import utils
1815
from casperfpga import katcp_fpga

scripts/casperfpga_tengbe_snap.py

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
# pylint: disable-msg=C0103
44
# pylint: disable-msg=C0301
55
"""
6-
View the status of a given digitiser.
7-
8-
Created on Fri Jan 3 10:40:53 2014
6+
View the contents of a TenGBE RX or TX snapblock.
97
108
@author: paulp
119
"""
@@ -17,7 +15,7 @@
1715
from casperfpga import katcp_fpga
1816
from casperfpga import dcp_fpga
1917
from casperfpga import spead as casperspead
20-
from casperfpga import utils as casperutils
18+
from casperfpga import snap as caspersnap
2119

2220
parser = argparse.ArgumentParser(description='Display the contents of an FPGA''s 10Gbe buffers.',
2321
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
@@ -32,9 +30,23 @@
3230
parser.add_argument('-d', '--direction', dest='direction', action='store',
3331
default='tx', type=str,
3432
help='tx or rx stream')
33+
3534
parser.add_argument('-s', '--spead', dest='spead', action='store_true',
3635
default=False,
3736
help='try and decode spead in this 10Gbe stream')
37+
parser.add_argument('--spead_check', dest='spead_check', action='store_true',
38+
default=False, help='Check SPEAD packet format against '
39+
'supplied values.')
40+
parser.add_argument('--spead_version', dest='spead_version', action='store',
41+
default=4, type=int, help='SPEAD version to use')
42+
parser.add_argument('--spead_flavour', dest='spead_flavour', action='store',
43+
default='64,48', type=str, help='SPEAD flavour to use')
44+
parser.add_argument('--spead_packetlen', dest='spead_packetlen', action='store',
45+
default=640, type=int,
46+
help='SPEAD packet length (data portion only) to expect')
47+
parser.add_argument('--spead_numheaders', dest='spead_numheaders', action='store',
48+
default=8, type=int, help='number of SPEAD headers to expect')
49+
3850
parser.add_argument('--hex', dest='hex', action='store_true',
3951
default=False,
4052
help='show numbers in hex')
@@ -88,14 +100,27 @@
88100
ip_key = 'ip_in'
89101
eof_key = 'eof_in'
90102
coredata = fpga.tengbes[args.core].read_rxsnap()
91-
92103
fpga.disconnect()
93104

94105
if args.spead:
95-
spead_processor = casperspead.SpeadProcessor(4, '64,48', 640, 8)
96-
gbe_packets = casperutils.packetise_snapdata(coredata, eof_key)
106+
if args.spead_check:
107+
spead_processor = casperspead.SpeadProcessor(args.spead_version,
108+
args.spead_flavour,
109+
args.spead_packetlen,
110+
args.spead_numheaders)
111+
expected_packet_length = args.spead_packetlen + args.spead_numheaders + 1
112+
else:
113+
spead_processor = casperspead.SpeadProcessor(None, None, None, None)
114+
expected_packet_length = -1
115+
116+
gbe_packets = caspersnap.Snap.packetise_snapdata(coredata, eof_key)
97117
gbe_data = []
98118
for pkt in gbe_packets:
119+
if (expected_packet_length > -1) and \
120+
(len(pkt[data_key]) != expected_packet_length):
121+
raise RuntimeError('Gbe packet not correct length - '
122+
'should be {}. is {}'.format(expected_packet_length,
123+
len(pkt[data_key])))
99124
gbe_data.append(pkt[data_key])
100125
spead_processor.process_data(gbe_data)
101126
spead_data = []
@@ -104,7 +129,7 @@
104129
coredata[data_key] = spead_data
105130

106131
packet_counter = 0
107-
for ctr in range(0, len(coredata[coredata.keys()[0]])):
132+
for ctr in range(0, len(coredata[data_key])):
108133
if coredata[eof_key][ctr-1]:
109134
packet_counter = 0
110135
print '%5d,%3d' % (ctr, packet_counter),
@@ -116,16 +141,9 @@
116141
display_key = 'src_ip'
117142
else:
118143
raise RuntimeError('Unknown IP key?')
119-
print '%s(%s)' % (display_key, tengbe.ip2str(coredata[key][ctr])), '\t',
144+
print '%s(%s)' % (display_key, str(tengbe.IpAddress(coredata[key][ctr]))), '\t',
120145
elif (key == data_key) and args.spead:
121-
# new_spead_info, spead_stringdata = process_spead_word(spead_info, coredata[data_key][ctr], packet_counter)
122-
# if new_spead_info is not None:
123-
# spead_info = new_spead_info.copy()
124-
try:
125-
print '%s(%s)' % (key, coredata[data_key][ctr]), '\t',
126-
except IndexError:
127-
128-
print '%s(spead_pkt_incomplete)\t' % key,
146+
print '%s(%s)' % (key, coredata[data_key][ctr]), '\t',
129147
else:
130148
if args.hex:
131149
print '%s(0x%X)' % (key, coredata[key][ctr]), '\t',

scripts/casperfpga_tengbe_status.py

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -111,33 +111,20 @@ def get_tap_data(fpga):
111111
# sys.exit()
112112

113113
# work out tables for each fpga
114-
fpga_headers = []
115-
master_list = []
116-
for cnt, fpga in enumerate(fpgas):
114+
fpga_headers = ['tap_running', 'ip']
115+
for fpga in fpgas:
117116
gbedata = gbe_data[fpga.host]
118-
gbe0 = gbedata.keys()[0]
119-
core0_regs = [key.replace(gbe0, 'gbe') for key in gbedata[gbe0].keys()]
120-
if cnt == 0:
121-
master_list = core0_regs[:]
122117
for core in gbedata:
123118
core_regs = [key.replace(core, 'gbe') for key in gbedata[core].keys()]
124-
if sorted(core0_regs) != sorted(core_regs):
125-
raise RuntimeError('Not all GBE cores for FPGA %s have the same support registers. Problem.', fpga.host)
126-
fpga_headers.append(core0_regs)
127-
128-
# all_the_same = True
129-
# for cnt, fpga in enumerate(fpgas):
130-
# if sorted(master_list) != sorted(fpga_headers[cnt]):
131-
# all_the_same = False
132-
# raise RuntimeWarning('Warning: GBE cores across given hosts are NOT configured the same!')
133-
# if all_the_same:
134-
# fpga_headers = [fpga_headers[0]]
119+
for reg in core_regs:
120+
if reg not in fpga_headers:
121+
fpga_headers.append(reg)
122+
fpga_headers = [fpga_headers]
135123

136124
fpga_headers = [['tap_running', 'ip', 'gbe_rxctr', 'gbe_rxofctr', 'gbe_rxerrctr',
137125
'gbe_rxbadctr', 'gbe_txerrctr', 'gbe_txfullctr', 'gbe_txofctr',
138126
'gbe_txctr', 'gbe_txvldctr']]
139127

140-
141128
def exit_gracefully(sig, frame):
142129
print sig, frame
143130
scroll.screen_teardown()

setup.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
long_description=open('README.txt').read(),
1414
install_requires=[
1515
'katcp',
16-
'construct',
1716
'numpy',
1817
],
1918
provides=['casperfpga'],
@@ -22,4 +21,4 @@
2221
scripts=glob.glob('scripts/*')
2322
)
2423

25-
# end
24+
# end

src/attribute_container.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ class AttributeContainer(object):
66
"""
77

88
def __init__(self):
9-
self._next_item = 0
10-
self._items = []
9+
self.clear()
1110

1211
def __getitem__(self, item_to_get):
1312
"""
@@ -41,6 +40,11 @@ def __next__(self):
4140
def next(self): # Python 2 compat
4241
return self.__next__()
4342

43+
def clear(self):
44+
self.__dict__.clear()
45+
self._next_item = 0
46+
self._items = []
47+
4448
def names(self):
4549
return self._items
4650

src/bitfield.py

Lines changed: 34 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
import logging
2-
import construct
32

43
LOGGER = logging.getLogger(__name__)
54

65

76
class Bitfield(object):
8-
"""Wraps contruct's BitStruct class. It describes a chunk of memory that
9-
consists of a number of fields.
107
"""
11-
def __init__(self, name, width, fields=None):
8+
Describes a chunk of memory that consists of a number of Fields.
9+
"""
10+
def __init__(self, name, width_bits, fields=None):
1211
self.name = name
13-
self.width = width
12+
self.width_bits = width_bits
1413
self._fields = {}
15-
self.bitstruct = None
1614
if fields is not None:
1715
self.fields_add(fields)
1816
LOGGER.debug('New Bitfield(%s) with %i fields' % (self.name, len(self._fields)))
@@ -21,12 +19,14 @@ def __init__(self, name, width, fields=None):
2119
# return self._fields.keys()
2220

2321
def fields_clear(self):
24-
"""Reset the fields in this bitstruct.
22+
"""
23+
Reset the fields in this bitstruct.
2524
"""
2625
self._fields = {}
2726

2827
def fields_add(self, fields):
29-
"""Add a dictionary of Fields to this bitfield.
28+
"""
29+
Add a dictionary of Fields to this bitfield.
3030
"""
3131
if not isinstance(fields, dict):
3232
raise TypeError('fields should be a dictionary of Field objects.')
@@ -36,55 +36,34 @@ def fields_add(self, fields):
3636
self.field_add(newfield)
3737

3838
def field_add(self, newfield, auto_offset=False):
39-
"""Add a Field to this bitfield.
39+
"""
40+
Add a Field to this bitfield.
4041
"""
4142
if not isinstance(newfield, Field):
4243
raise TypeError('Expecting Field object.')
4344
# add it at the end of the current fields
4445
if auto_offset:
4546
width = 0
4647
for field in self._fields.itervalues():
47-
width += field.width
48+
width += field.width_bits
4849
newfield.offset = width
4950
self._fields[newfield.name] = newfield
50-
self._update_bitstruct()
51-
52-
def _update_bitstruct(self):
53-
"""
54-
Update this Bitfield's bitstruct after a field has been modified.
55-
"""
56-
# need it msb -> lsb
57-
# print 100 * '#'
58-
fields = sorted(self._fields.itervalues(), key=lambda x: x.offset, reverse=True)
59-
field_width_sum = sum(f.width for f in self._fields.itervalues())
60-
# print fields
61-
# print field_width_sum
62-
# print 100 * '#'
63-
bs = construct.BitStruct(self.name, construct.Padding(self.width - field_width_sum))
64-
for f in fields:
65-
if f.width == 1:
66-
newfield = construct.Flag(f.name)
67-
else:
68-
newfield = construct.BitField(f.name, f.width)
69-
bs.subcon.subcons = bs.subcon.subcons + (newfield,)
70-
self.bitstruct = bs
7151

7252
def field_names(self):
7353
return self._fields.keys()
7454

75-
def names(self):
76-
return self._fields.keys()
77-
7855
def field_get_by_name(self, fieldname):
79-
"""Get a field from this bitfield by its name.
56+
"""
57+
Get a field from this bitfield by its name.
8058
"""
8159
try:
8260
return self._fields[fieldname]
8361
except KeyError:
8462
return None
8563

8664
def fields_string_get(self):
87-
"""Get a string of all the field names.
65+
"""
66+
Get a string of all the field names.
8867
"""
8968
fieldstring = ''
9069
for field in self._fields.itervalues():
@@ -93,38 +72,43 @@ def fields_string_get(self):
9372
return fieldstring
9473

9574
def __str__(self):
96-
"""Return a string representation of this object.
9775
"""
98-
rv = self.name + '(' + str(self.width) + ',['
76+
Return a string representation of this object.
77+
"""
78+
rv = self.name + '(' + str(self.width_bits) + ',['
9979
rv = rv + self.fields_string_get() + '])'
10080
return rv
10181

10282

10383
class Field(object):
104-
"""A Field object is a number of bits somewhere in a Bitfield object.
10584
"""
106-
def __init__(self, name, numtype, width, binary_pt, lsb_offset):
85+
A Field object is a number of bits somewhere in a Bitfield object.
86+
"""
87+
def __init__(self, name, numtype, width_bits, binary_pt, lsb_offset):
10788
"""
108-
Initialise a field object.
109-
@param name The name of the field
110-
@param numtype A numerical description of the type - 0 is unsigned,
111-
1 is signed 2's comp and 2 is boolean
112-
@param width The width of the field, in bits
113-
@param binary_pt The binary point position, in bits
114-
@param lsb_offset The offset in the memory field, in bits - -1 means it hasn't been set yet.
89+
Initialise a Field object.
90+
:param name: The name of the field
91+
:param numtype: A numerical description of the type:
92+
0 is unsigned, 1 is signed 2's comp and 2 is boolean
93+
:param width: The width of the field, in bits
94+
:param binary_pt: The binary point position, in bits
95+
:param lsb_offset: The offset in the memory field, in bits:
96+
-1 means it hasn't been set yet.
97+
:return:
11598
"""
11699
if not isinstance(numtype, int):
117100
raise TypeError('Type must be an integer.')
118101
assert name.strip() != '', 'Cannot have a Field with empty name?!'
119102
self.name = name
120103
self.numtype = numtype
121-
self.width = width
104+
self.width_bits = width_bits
122105
self.binary_pt = binary_pt
123106
self.offset = lsb_offset
124107

125108
def __str__(self):
126-
return '%s(%i,%i,%i,%i)' % (self.name, self.offset, self.width, self.binary_pt, self.numtype)
109+
return '%s(%i,%i,%i,%i)' % (self.name, self.offset, self.width_bits,
110+
self.binary_pt, self.numtype)
127111

128112
def __repr__(self):
129-
return '%s(%i,%i,%i,%i)' % (self.name, self.offset, self.width, self.binary_pt, self.numtype)
113+
return str(self)
130114
# end

0 commit comments

Comments
 (0)