Commit 0d2eb8ac authored by Jason Manley's avatar Jason Manley
Browse files

Merge pull request #43 from ska-sa/devel

Merge devel with master
parents 588e0728 01419c7c
__author__ = 'paulp'
class AttributeContainer(object):
"""An iterable class to make registers, snapshots, etc more accessible.
"""
def __init__(self):
self._items = []
self.clear()
def __getitem__(self, item_to_get):
......@@ -18,27 +15,13 @@ class AttributeContainer(object):
def __setattr__(self, name, value):
try:
if name != '_next_item':
self._items.append(name)
self._items.append(name)
except AttributeError:
pass
object.__setattr__(self, name, value)
def __iter__(self):
return self
def __next__(self):
try:
item_name = self._items[self._next_item]
except:
self._next_item = 0
raise StopIteration
else:
self._next_item += 1
return getattr(self, item_name)
def next(self): # Python 2 compat
return self.__next__()
return (getattr(self, n) for n in self._items)
def remove_attribute(self, attribute):
"""
......@@ -51,7 +34,6 @@ class AttributeContainer(object):
def clear(self):
self.__dict__.clear()
self._next_item = 0
self._items = []
def names(self):
......@@ -65,6 +47,5 @@ class AttributeContainer(object):
def __repr__(self):
keys = self.__dict__.keys()
keys.pop(keys.index('_next_item'))
keys.pop(keys.index('_items'))
return str(keys)
......@@ -17,18 +17,19 @@ from utils import parse_fpg
LOGGER = logging.getLogger(__name__)
# known CASPER memory-accessible devices and their associated classes and containers
# known CASPER memory-accessible devices and their associated
# classes and containers
CASPER_MEMORY_DEVICES = {
'xps:bram': {'class': sbram.Sbram, 'container': 'sbrams'},
'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'},
'xps:bram': {'class': sbram.Sbram, 'container': 'sbrams'},
'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'},
}
# other devices - blocks that aren't memory devices, but about which we'd like to know
# tagged in the simulink diagram
# other devices - blocks that aren't memory devices, but about which we'd
# like to know tagged in the simulink diagram
CASPER_OTHER_DEVICES = {
'casper:bitsnap': 'bitsnap',
'casper:dec_fir': 'dec_fir',
......@@ -79,7 +80,8 @@ class CasperFpga(object):
def deprogram(self):
"""
The child class will deprogram the FPGA, we just reset out device information
The child class will deprogram the FPGA, we just reset out
device information
:return:
"""
self.__reset_device_info()
......@@ -106,13 +108,14 @@ class CasperFpga(object):
def test_connection(self):
"""
Write to and read from the scratchpad to test the connection to the FPGA.
Write to and read from the scratchpad to test the connection to the FPGA
"""
for val in [0xa5a5a5, 0x000000]:
self.write_int('sys_scratchpad', val)
rval = self.read_int('sys_scratchpad')
if rval != val:
raise RuntimeError('%s: cannot write scratchpad? %i != %i' % (self.host, rval, val))
raise RuntimeError('%s: cannot write scratchpad? %i != %i' %
(self.host, rval, val))
return True
# def __getattribute__(self, name):
......@@ -136,13 +139,13 @@ class CasperFpga(object):
last_dram_page = -1
dram_indirect_page_size = (64*1024*1024)
#read_chunk_size = (1024*1024)
# read_chunk_size = (1024*1024)
LOGGER.debug('%s: reading a total of %8i bytes from offset %8i...' %
(self.host, size, offset))
while n_reads < size:
dram_page = (offset + n_reads) / dram_indirect_page_size
local_offset = (offset + n_reads) % dram_indirect_page_size
#local_reads = min(read_chunk_size, size-n_reads, dram_indirect_page_size-(offset%dram_indirect_page_size))
# local_reads = min(read_chunk_size, size-n_reads, dram_indirect_page_size-(offset%dram_indirect_page_size))
local_reads = min(size - n_reads, dram_indirect_page_size - (offset % dram_indirect_page_size))
if last_dram_page != dram_page:
self.write_int('dram_controller', dram_page)
......@@ -201,12 +204,14 @@ class CasperFpga(object):
if new_data != data:
unpacked_wrdata = struct.unpack('>L', data[0:4])[0]
unpacked_rddata = struct.unpack('>L', new_data[0:4])[0]
LOGGER.error('%s: verification of write to %s at offset %d failed. Wrote 0x%08x... '
'but got back 0x%08x...' % (self.host, device_name, offset,
unpacked_wrdata, unpacked_rddata))
raise ValueError('%s: verification of write to %s at offset %d failed. Wrote 0x%08x... '
'but got back 0x%08x...' % (self.host, device_name, offset,
unpacked_wrdata, unpacked_rddata))
LOGGER.error('%s: verification of write to %s at offset %d failed. '
'Wrote 0x%08x... but got back 0x%08x...' %
(self.host, device_name, offset,
unpacked_wrdata, unpacked_rddata))
raise ValueError('%s: verification of write to %s at offset %d '
'failed. Wrote 0x%08x... but got back 0x%08x...' %
(self.host, device_name, offset,
unpacked_wrdata, unpacked_rddata))
def read_int(self, device_name, word_offset=0):
"""
......@@ -242,52 +247,61 @@ class CasperFpga(object):
# careful of packing input data into 32 bit - check range: if
# negative, must be signed int; if positive over 2^16, must be unsigned
# int.
data = struct.pack('>i' if integer < 0 else '>I', integer)
try:
data = struct.pack('>i' if integer < 0 else '>I', integer)
except Exception as ve:
LOGGER.error('Writing integer %i failed with error %s' % (
integer, ve.message))
raise ValueError('Writing integer %i failed with error %s' % (
integer, ve.message))
if blindwrite:
self.blindwrite(device_name, data, word_offset*4)
else:
self.write(device_name, data, word_offset*4)
LOGGER.debug('%s: write_int %8x to register %s at word offset %d okay%s.' %
(self.host, integer, device_name,
word_offset, ' (blind)' if blindwrite else ''))
def get_rcs(self, rcs_block_name='rcs'):
"""Retrieves and decodes a revision control block."""
raise NotImplementedError
rv = {'user': self.read_uint(rcs_block_name + '_user')}
app = self.read_uint(rcs_block_name+'_app')
lib = self.read_uint(rcs_block_name+'_lib')
if lib & (1 << 31):
rv['compile_timestamp'] = lib & ((2 ** 31)-1)
else:
if lib & (1 << 30):
# type is svn
rv['lib_rcs_type'] = 'svn'
else:
# type is git
rv['lib_rcs_type'] = 'git'
if lib & (1 << 28):
# dirty bit
rv['lib_dirty'] = True
else:
rv['lib_dirty'] = False
rv['lib_rev'] = lib & ((2 ** 28)-1)
if app & (1 << 31):
rv['app_last_modified'] = app & ((2 ** 31)-1)
else:
if app & (1 << 30):
# type is svn
rv['app_rcs_type'] = 'svn'
else:
# type is git
rv['app_rcs_type'] = 'git'
if app & (1 << 28):
# dirty bit
rv['app_dirty'] = True
else:
rv['lib_dirty'] = False
rv['app_rev'] = app & ((2 ** 28)-1)
return rv
LOGGER.debug('%s: write_int %8x to register %s at word offset %d '
'okay%s.' % (self.host, integer, device_name,
word_offset,
' (blind)' if blindwrite else ''))
# def get_rcs(self, rcs_block_name='rcs'):
# """
# Retrieves and decodes a revision control block.
# """
# raise NotImplementedError
# rv = {'user': self.read_uint(rcs_block_name + '_user')}
# app = self.read_uint(rcs_block_name+'_app')
# lib = self.read_uint(rcs_block_name+'_lib')
# if lib & (1 << 31):
# rv['compile_timestamp'] = lib & ((2 ** 31)-1)
# else:
# if lib & (1 << 30):
# # type is svn
# rv['lib_rcs_type'] = 'svn'
# else:
# # type is git
# rv['lib_rcs_type'] = 'git'
# if lib & (1 << 28):
# # dirty bit
# rv['lib_dirty'] = True
# else:
# rv['lib_dirty'] = False
# rv['lib_rev'] = lib & ((2 ** 28)-1)
# if app & (1 << 31):
# rv['app_last_modified'] = app & ((2 ** 31)-1)
# else:
# if app & (1 << 30):
# # type is svn
# rv['app_rcs_type'] = 'svn'
# else:
# # type is git
# rv['app_rcs_type'] = 'git'
# if app & (1 << 28):
# # dirty bit
# rv['app_dirty'] = True
# else:
# rv['lib_dirty'] = False
# rv['app_rev'] = app & ((2 ** 28)-1)
# return rv
def __create_memory_devices(self, device_dict, memorymap_dict):
"""
......
This diff is collapsed.
......@@ -7,6 +7,7 @@ busses. Normally via KATCP.
import logging
import bitfield
import struct
import numpy as np
LOGGER = logging.getLogger(__name__)
......@@ -39,7 +40,8 @@ def fp2fixed_int(num, bitwidth, bin_pt, signed):
"""
Convert a given float to an integer representation of the fixed-point number
described by the params.
Provides the same output as a Xilinx block in Simulink would if you cast it to an unsigned int.
Provides the same output as a Xilinx block in Simulink would if you cast
it to an unsigned int.
"""
_format = '%s%i.%i' % ('fix' if signed else 'ufix', bitwidth, bin_pt)
LOGGER.debug('Converting %f to %s' % (num, _format))
......@@ -59,10 +61,13 @@ def fp2fixed_int(num, bitwidth, bin_pt, signed):
negnum = num < 0
_original_num = num
num = abs(num)
left = int(num)
right, left = np.modf(num)
left = int(left)
right = int(right*(2**bin_pt))
# left = int(num)
if left > left_limits[1]:
raise ValueError('Cannot represent %f in %s' % (_original_num, _format))
right = int(round((abs(num) % 1) * (2**bin_pt)))
# right = int(round((abs(num) % 1) * (2**bin_pt)))
assert left >= 0 and right >= 0
_lsbin = bin(left)[2:]
_lsbin = '0'*(left_bits-len(_lsbin)) + _lsbin
......
......@@ -67,6 +67,42 @@ def parse_fpg(filename):
return create_meta_dictionary(metalist), memorydict
def pull_info_from_fpg(fpg_file, parameter):
"""
Pull available parameters about x-engine or f-engine from .fpg file.
Available options for x-engine: 'x_fpga_clock', 'xeng_outbits', 'xeng_accumulation_len'
Available options for f-engine: 'n_chans', 'quant_format', 'spead_flavour'
:param fpg_file: bit file path
:param parameter: parameter string
:return: pattern value (string)
"""
match = []
fpg_dict = parse_fpg(fpg_file)
if parameter == 'x_fpga_clock':
match = str(int(fpg_dict[0]['XSG_core_config']['clk_rate'])*10**6)
if parameter == 'xeng_outbits':
match = fpg_dict[0]['sys0_vacc']['n_bits']
if parameter == 'xeng_accumulation_len':
match = fpg_dict[0]['sys0_xeng']['acc_len']
if parameter == 'spead_flavour':
match1 = fpg_dict[0]['pack_spead_pack0']['spead_msw']
match2 = fpg_dict[0]['pack_spead_pack0']['spead_lsw']
s = ','
match = s.join([match1, match2])
if parameter == 'quant_format':
match1 = fpg_dict[0]['snap_quant0']['io_widths']
match2 = fpg_dict[0]['snap_quant0']['io_bps']
s = '.'
match = s.join([match1[1], match2[1]])
if parameter == 'n_chans':
match1 = int(fpg_dict[0]['pfb_fft_wideband_real_fft_biplex_real_4x']['fftsize'])
match2 = int(fpg_dict[0]['pfb_fft_wideband_real_fft_biplex_real_4x']['n_inputs'])
match = match2*2**match1
if match is []:
raise RuntimeError('Parameter %s does not match any field in fpg file.' % parameter)
return match
def program_fpgas(fpga_list, progfile, timeout=10):
"""
Program more than one FPGA at the same time.
......
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