Skip to content

Commit 2dcffca

Browse files
committed
Merge pull request #48 from ska-sa/devel
Merge devel into master
2 parents 0d2eb8a + cafad72 commit 2dcffca

File tree

11 files changed

+909
-531
lines changed

11 files changed

+909
-531
lines changed

scripts/casperfpga_tengbe_status.py

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,25 @@
2323
except ImportError:
2424
corr2 = None
2525

26-
parser = argparse.ArgumentParser(description='Display TenGBE interface information about a MeerKAT fpga host.',
27-
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
28-
parser.add_argument('--hosts', dest='hosts', type=str, action='store', default='',
29-
help='comma-delimited list of hosts, or a corr2 config file')
30-
parser.add_argument('-p', '--polltime', dest='polltime', action='store', default=1, type=int,
31-
help='time at which to poll data, in seconds')
32-
parser.add_argument('-r', '--reset', dest='resetctrs', action='store_true', default=False,
33-
help='reset the GBE debug counters')
34-
parser.add_argument('--comms', dest='comms', action='store', default='katcp', type=str,
35-
help='katcp (default) or dcp?')
36-
parser.add_argument('--loglevel', dest='log_level', action='store', default='',
37-
help='log level to use, default None, options INFO, DEBUG, ERROR')
26+
parser = argparse.ArgumentParser(
27+
description='Display TenGBE interface information about a MeerKAT '
28+
'fpga host.',
29+
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
30+
parser.add_argument(
31+
'--hosts', dest='hosts', type=str, action='store', default='',
32+
help='comma-delimited list of hosts, or a corr2 config file')
33+
parser.add_argument(
34+
'-p', '--polltime', dest='polltime', action='store', default=1, type=int,
35+
help='time at which to poll data, in seconds')
36+
parser.add_argument(
37+
'-r', '--reset', dest='resetctrs', action='store_true', default=False,
38+
help='reset the GBE debug counters')
39+
parser.add_argument(
40+
'--comms', dest='comms', action='store', default='katcp', type=str,
41+
help='katcp (default) or dcp?')
42+
parser.add_argument(
43+
'--loglevel', dest='log_level', action='store', default='',
44+
help='log level to use, default None, options INFO, DEBUG, ERROR')
3845
args = parser.parse_args()
3946
polltime = args.polltime
4047

@@ -68,7 +75,8 @@
6875
numgbes = len(fpga.tengbes)
6976
if numgbes < 1:
7077
raise RuntimeWarning('Host %s has no 10gbe cores', fpga.host)
71-
print '%s: found %i 10gbe core%s.' % (fpga.host, numgbes, '' if numgbes == 1 else 's')
78+
print '%s: found %i 10gbe core%s.' % (
79+
fpga.host, numgbes, '' if numgbes == 1 else 's')
7280

7381
if args.resetctrs:
7482
def reset_gbe_debug(fpga_):
@@ -121,9 +129,10 @@ def get_tap_data(fpga):
121129
fpga_headers.append(reg)
122130
fpga_headers = [fpga_headers]
123131

124-
fpga_headers = [['tap_running', 'ip', 'gbe_rxctr', 'gbe_rxofctr', 'gbe_rxerrctr',
125-
'gbe_rxbadctr', 'gbe_txerrctr', 'gbe_txfullctr', 'gbe_txofctr',
126-
'gbe_txctr', 'gbe_txvldctr']]
132+
fpga_headers = [['tap_running', 'ip', 'gbe_rxctr', 'gbe_rxofctr',
133+
'gbe_rxerrctr', 'gbe_rxbadctr', 'gbe_txerrctr',
134+
'gbe_txfullctr', 'gbe_txofctr', 'gbe_txctr', 'gbe_txvldctr']]
135+
127136

128137
def exit_gracefully(sig, frame):
129138
print sig, frame
@@ -146,22 +155,25 @@ def exit_gracefully(sig, frame):
146155
if keypress == -1:
147156
break
148157
elif keypress > 0:
149-
# if character == 'c':
150-
# for f in fpgas:
151-
# f.reset_counters()
158+
# if character == 'c':
159+
# for f in fpgas:
160+
# f.reset_counters()
152161
scroller.draw_screen()
153162
if time.time() > last_refresh + polltime:
154163
scroller.clear_buffer()
155-
scroller.add_line('Polling %i host%s every %s - %is elapsed.' %
156-
(len(fpgas), '' if len(fpgas) == 1 else 's',
157-
'second' if polltime == 1 else ('%i seconds' % polltime),
158-
time.time() - STARTTIME), 0, 0, absolute=True)
164+
scroller.add_line(
165+
'Polling %i host%s every %s - %is elapsed.' % (
166+
len(fpgas),
167+
'' if len(fpgas) == 1 else 's',
168+
'second' if polltime == 1 else ('%i seconds' % polltime),
169+
time.time() - STARTTIME), 0, 0, absolute=True)
159170
start_pos = 20
160171
pos_increment = 15
161172
if len(fpga_headers) == 1:
162173
scroller.add_line('Host', 0, 1, absolute=True)
163174
for reg in fpga_headers[0]:
164-
scroller.add_line(reg.rjust(pos_increment), start_pos, 1, absolute=True)
175+
scroller.add_line(
176+
reg.rjust(pos_increment), start_pos, 1, absolute=True)
165177
start_pos += pos_increment
166178
scroller.set_ypos(newpos=2)
167179
scroller.set_ylimits(ymin=2)
@@ -173,23 +185,32 @@ def exit_gracefully(sig, frame):
173185
fpga_data = gbe_data[fpga.host]
174186
scroller.add_line(fpga.host)
175187
for core, core_data in fpga_data.items():
176-
fpga_data[core]['tap_running'] =\
177-
{'data': {'reg': False if tap_data[fpga.host][core]['name'] == '' else True}}
178-
fpga_data[core]['ip'] = {'data': {'reg': tap_data[fpga.host][core]['ip']}}
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+
}
179198
start_pos = 20
180199
scroller.add_line(core, 5)
181200
for header_register in fpga_headers[0]:
182-
core_register_name = header_register.replace('gbe', core)
201+
core_regname = header_register.replace('gbe', core)
183202
if start_pos < 200:
184-
if core_register_name in core_data.keys():
185-
if not isinstance(core_data[core_register_name]['data']['reg'], str):
186-
regval = '%d' % core_data[core_register_name]['data']['reg']
203+
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']
187206
else:
188-
regval = core_data[core_register_name]['data']['reg']
207+
regval = core_data[core_regname]['data']['reg']
189208
else:
190209
regval = 'n/a'
191210
# all on the same line
192-
scroller.add_line(regval.rjust(pos_increment), start_pos, scroller.get_current_line() - 1)
211+
scroller.add_line(regval.rjust(pos_increment),
212+
start_pos,
213+
scroller.get_current_line() - 1)
193214
start_pos += pos_increment
194215
scroller.draw_screen()
195216
last_refresh = time.time()

src/bitfield.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,33 @@
33
LOGGER = logging.getLogger(__name__)
44

55

6+
def clean_fields(parent_name, parent_type, field_str):
7+
"""
8+
Take the Simulink string for a field and return a list
9+
:param parent_name: the BitField that will run this
10+
:param parent_type: register, snapshot, etc
11+
:param field_str: the string to be parsed
12+
:return:
13+
"""
14+
_fstr = field_str.replace('[', '').replace(']', '')
15+
_fstr = _fstr.strip().replace(', ', ',').replace(' ', ' ')
16+
if (_fstr.find(' ') > -1) and (_fstr.find(',') > -1):
17+
LOGGER.error('Parameter string %s contains spaces and commas '
18+
'as delimiters. This is confusing.' % field_str)
19+
if _fstr.find(' ') > -1:
20+
_flist = _fstr.split(' ')
21+
else:
22+
_flist = _fstr.split(',')
23+
_rv = []
24+
for _fname in _flist:
25+
if _fname.strip() == '':
26+
LOGGER.DEBUG('Throwing away empty field in %s %s' % (
27+
parent_type, parent_name))
28+
else:
29+
_rv.append(_fname)
30+
return _rv
31+
32+
633
class Bitfield(object):
734
"""
835
Describes a chunk of memory that consists of a number of Fields.
@@ -13,7 +40,8 @@ def __init__(self, name, width_bits, fields=None):
1340
self._fields = {}
1441
if fields is not None:
1542
self.fields_add(fields)
16-
LOGGER.debug('New Bitfield(%s) with %i fields' % (self.name, len(self._fields)))
43+
LOGGER.debug('New Bitfield(%s) with %i fields' % (self.name,
44+
len(self._fields)))
1745

1846
# def __dir__(self):
1947
# return self._fields.keys()

src/casperfpga.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,19 @@ def deprogram(self):
8686
"""
8787
self.__reset_device_info()
8888

89+
def upload_to_ram_and_program(self, filename, port=-1, timeout=10,
90+
wait_complete=True):
91+
"""
92+
Upload an FPG file to RAM and then program the FPGA.
93+
:param filename: the file to upload
94+
:param port: the port to use on the rx end, -1 means a random port
95+
:param timeout: how long to wait, seconds
96+
:param wait_complete: wait for the transaction to complete, return
97+
after upload if False
98+
:return:
99+
"""
100+
raise NotImplementedError
101+
89102
def __reset_device_info(self):
90103
"""
91104
Reset information of devices this FPGA knows about.
@@ -250,9 +263,9 @@ def write_int(self, device_name, integer, blindwrite=False, word_offset=0):
250263
try:
251264
data = struct.pack('>i' if integer < 0 else '>I', integer)
252265
except Exception as ve:
253-
LOGGER.error('Writing integer %i failed with error %s' % (
266+
LOGGER.error('Writing integer %i failed with error: %s' % (
254267
integer, ve.message))
255-
raise ValueError('Writing integer %i failed with error %s' % (
268+
raise ValueError('Writing integer %i failed with error: %s' % (
256269
integer, ve.message))
257270
if blindwrite:
258271
self.blindwrite(device_name, data, word_offset*4)

src/katcp_fpga.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def __init__(self, host, port=7147, timeout=20.0, connect=True):
8282
if connect:
8383
self.connect()
8484
LOGGER.info('%s: port(%s) created%s.' %
85-
(self.host, port,' & connected' if connect else ''))
85+
(self.host, port, ' & connected' if connect else ''))
8686

8787
def connect(self, timeout=None):
8888
"""
@@ -106,7 +106,7 @@ def connect(self, timeout=None):
106106
self.start(daemon=True)
107107
connected = self.wait_connected(timeout)
108108
if not connected:
109-
raise RuntimeError('Connection to {} not established witin {}s'
109+
raise RuntimeError('Connection to {} not established within {}s'
110110
.format(self.bind_address_string, timeout))
111111
# check that an actual katcp command gets through
112112
got_ping = False
@@ -118,6 +118,15 @@ def connect(self, timeout=None):
118118
if not got_ping:
119119
raise RuntimeError('Could not connect to KATCP '
120120
'server %s' % self.host)
121+
122+
# set a higher write buffer size than standard
123+
try:
124+
if self._stream.max_write_buffer_size <= 262144:
125+
self._stream.max_buffer_size *= 2
126+
self._stream.max_write_buffer_size *= 2
127+
except AttributeError:
128+
LOGGER.warn('%s: no ._stream instance found.' % self.host)
129+
121130
LOGGER.info('%s: connection established' % self.host)
122131

123132
def disconnect(self):

src/memory.py

Lines changed: 35 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -35,78 +35,58 @@ def bin2fp(raw_word, bitwidth, bin_pt, signed):
3535
return quotient + (float(rem) / (2**bin_pt))
3636
raise RuntimeError
3737

38-
39-
def fp2fixed_int(num, bitwidth, bin_pt, signed):
38+
def fp2fixed(num, bitwidth, bin_pt, signed):
4039
"""
41-
Convert a given float to an integer representation of the fixed-point number
42-
described by the params.
43-
Provides the same output as a Xilinx block in Simulink would if you cast
44-
it to an unsigned int.
40+
Convert a floating point number to its fixed point equivalent.
41+
:param num:
42+
:param bitwidth:
43+
:param bin_pt:
44+
:param signed:
45+
:return:
4546
"""
4647
_format = '%s%i.%i' % ('fix' if signed else 'ufix', bitwidth, bin_pt)
47-
LOGGER.debug('Converting %f to %s' % (num, _format))
4848
if bin_pt >= bitwidth:
4949
raise ValueError('Cannot have bin_pt >= bitwidth')
5050
if bin_pt < 0:
5151
raise ValueError('bin_pt < 0 makes no sense')
5252
if (not signed) and (num < 0):
53-
raise ValueError('Cannot represent %f in %s' % (num, _format))
53+
raise ValueError('Cannot represent negative number (%f) in %s' % (
54+
num, _format))
5455
if num == 0:
5556
return 0
56-
left_bits = bitwidth - bin_pt
57+
scaled = num * (2**bin_pt)
58+
scaled = round(scaled)
5759
if signed:
58-
left_limits = -1 * 2**(left_bits-1), 2**(left_bits-1) - 1
60+
_nbits = bitwidth - 1
61+
limits = [-1 * (2**_nbits), (2**_nbits) - 1]
5962
else:
60-
left_limits = 0, 2**left_bits - 1
61-
negnum = num < 0
62-
_original_num = num
63-
num = abs(num)
64-
right, left = np.modf(num)
65-
left = int(left)
66-
right = int(right*(2**bin_pt))
67-
# left = int(num)
68-
if left > left_limits[1]:
69-
raise ValueError('Cannot represent %f in %s' % (_original_num, _format))
70-
# right = int(round((abs(num) % 1) * (2**bin_pt)))
71-
assert left >= 0 and right >= 0
72-
_lsbin = bin(left)[2:]
73-
_lsbin = '0'*(left_bits-len(_lsbin)) + _lsbin
74-
if bin_pt == 0:
75-
_rsbin = ''
76-
else:
77-
_rsbin = bin(right)[2:]
78-
_rsbin = '0'*(bin_pt-len(_rsbin)) + _rsbin
79-
rv = int(_lsbin + _rsbin, 2)
80-
if negnum:
81-
rv = 2**bitwidth - rv
82-
LOGGER.debug(' returning %i' % rv)
83-
return rv
84-
63+
limits = [0, (2**bitwidth) - 1]
64+
scaled = min(limits[1], max(limits[0], scaled))
65+
unscaled = scaled / ((2**bin_pt) * 1.0)
66+
return unscaled
8567

86-
def bin2fp_old(bits, mantissa=8, exponent=7, signed=False):
68+
def cast_fixed(fpnum, bitwidth, bin_pt):
8769
"""
88-
Convert a raw fixed-point number to a float based on a given
89-
mantissa and exponent.
70+
Represent a fixed point number as an unsigned number, like the Xilinx
71+
reinterpret block.
72+
:param fpnum:
73+
:param bitwidth:
74+
:param bin_pt:
75+
:return:
9076
"""
91-
if bits == 0:
77+
if fpnum == 0:
9278
return 0
93-
if exponent >= mantissa:
94-
raise TypeError('Unsupported fixed format: %i.%i' % (mantissa, exponent))
95-
if not signed:
96-
if exponent == 0:
97-
if mantissa <= 63:
98-
return int(bits)
99-
else:
100-
# print bits, mantissa, exponent
101-
return long(bits)
102-
else:
103-
return float(bits) / (2**exponent)
104-
if bits >= 2**(mantissa-1):
105-
rnum = float(bits - (1 << mantissa)) / (2**exponent)
106-
else:
107-
rnum = float(bits) / (2**exponent)
108-
return rnum
79+
val = int(fpnum * (2**bin_pt))
80+
if fpnum < 0:
81+
val += 2**bitwidth
82+
return val
10983

84+
def fp2fixed_int(num, bitwidth, bin_pt, signed):
85+
"""
86+
Compatability function, rather use the other functions explicitly.
87+
"""
88+
val = fp2fixed(num, bitwidth, bin_pt, signed)
89+
return cast_fixed(val, bitwidth, bin_pt)
11090

11191
class Memory(bitfield.Bitfield):
11292
"""

0 commit comments

Comments
 (0)