Skip to content
Snippets Groups Projects
Commit 7ccb07c6 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Use methods from pi-apertif_system.py to access DB output.

parent 138005d0
Branches
No related tags found
No related merge requests found
...@@ -32,16 +32,20 @@ ...@@ -32,16 +32,20 @@
The test verifies the read data and runs independently per PN on the correlator. The test does not access The test verifies the read data and runs independently per PN on the correlator. The test does not access
the telescopes, but some --tel must be specified because --tel and --pol are used to derive the active the telescopes, but some --tel must be specified because --tel and --pol are used to derive the active
telescope paths (TP) which will result in non-zero visibility data. The assumption is that the telescopes telescope paths (TP) which will result in non-zero visibility data. The assumption is that the selected
are receiving (any noise) and outputting beamlets. --tel telescopes are receiving (sky) noise and are outputting beamlets.
Usage: Usage:
# -v 5 or 6 for debugging # use verbosity level -v 5 or 6 for debugging, or -v 0, 1, 2 or 3 for regression test
# -v 0, 1, 2 or 3 for regression test
# At central correlator verify expected result via DB # First start the dishes and central boards
> python $RADIOHDL/applications/apertif/commissioning/main.py --app apertif-dev --tel a --pol 0,1 --unb 0,1 > python $RADIOHDL/applications/apertif/commissioning/main.py --app apertif-dev --tel a --pol 0,1 --unb 0,1
> python $RADIOHDL/applications/apertif/commissioning/tests/verify_correlator_db_output.py -v 3 --tel a --unb 0 --fn 0:3 --bn 0:3 --beamlets 0 --channels 0
# Set dish BF weights to have one SP per CB for all beamlets and rely on the measured sky noise to provide ADC input
> ssh lcu-rta "python $UPE/peripherals/pi_apertif_system.py -v 3 --unb 0:7 --fn 0:3 --cmd 62 --cbeams 0:36 --pol 0,1 --subbands 0:511 --globalsp 56 --weight 32767,0"
# At central correlator verify expected visibility packet result via DB output
> python $RADIOHDL/applications/apertif/commissioning/tests/verify_correlator_db_output.py -v 3 --tel a --unb 0,1 --fn 0:3 --bn 0:3 --beamlets 0 --channels 0
""" """
############################################################################### ###############################################################################
...@@ -53,39 +57,11 @@ import test_case ...@@ -53,39 +57,11 @@ import test_case
import node_io import node_io
import pi_diag_data_buffer import pi_diag_data_buffer
import unb_apertif as apr import unb_apertif as apr
import pi_apertif_system as pi_apr
N_dish = 12 N_vis = pi_apr.N_vis # = 300
N_pol = 2 M_blk = pi_apr.M_blk # = 88 or 120
N_tp = N_pol * N_dish # = 24 N_chan_x = pi_apr.N_chan_x # = 64
N_vis = N_tp * (N_tp + 1) / 2
N_band = 16
N_slot = 1024
N_clk = 256
N_blk = 176 # 8b mode
Q_interleave = 2
M_blk = N_blk / Q_interleave # = 88
N_int_x = 800000
N_chan_x = 64
N_chan_x_w = cm.ceil_log2(N_chan_x)
nof_bn = 4 # Number of back node FPGAs (BN) per UniBoard
nof_fn = 4 # Number of front node FPGAs (FN) per UniBoard
nof_pn = 8 # Number of processing node FPGAs per UniBoard, = nof_fn + nof_bn
nof_10g = 3 # Number of external 10G links per PN on UniBoard
c_dbSize = 1024
c_dbPattern = [13]*c_dbSize
c_baseSrcMac = 0x002286080000
c_wcudata = 1 # is 1 if Data Write is 'wcudata1', else is 2 if DataWriter is 'wcudata2', as defined in central_commands.sh
if c_wcudata==1:
c_baseDstMacEth01 = 0xe41d2de42690
c_baseDstMacEth23 = 0xe41d2dbc3cd0
else:
c_baseDstMacEth01 = 0xe41d2dbc3dc0
c_baseDstMacEth23 = 0xe41d2de40d30
c_expIdMarker = 65
c_expIdVersion = 2
############################################################################### ###############################################################################
# Instantiations # Instantiations
...@@ -97,192 +73,59 @@ activeDishes = apr.get_active_dishes(tc.telStrList) ...@@ -97,192 +73,59 @@ activeDishes = apr.get_active_dishes(tc.telStrList)
activePolarizations = tc.polNrs activePolarizations = tc.polNrs
activeTp = apr.get_active_telescope_paths(activeDishes, activePolarizations) activeTp = apr.get_active_telescope_paths(activeDishes, activePolarizations)
activeVis = apr.get_active_visibilities(activeTp) activeVis = apr.get_active_visibilities(activeTp)
activeAutoVis = apr.get_auto_visibilities(activeTp)
# Declaring an object of this class is equivalent to func_apertif_unb1_correlator_packet_info() in VHDL. # Declaring an object of this class is equivalent to func_apertif_unb1_correlator_packet_info() in VHDL.
corrPacketInfo = apr.CorrelatorPacketInfo(N_vis) corrPacketInfo = apr.CorrelatorPacketInfo(N_vis)
# One or more beamlet and channel indices to select the visibility packets # One or more beamlet indices to select the channel visibility packets
beamlets = tc.beamlets beamletIndices = tc.beamlets
if not cm.exist_all_elements_from_a_in_b(beamlets, range(M_blk)): if not cm.exist_all_elements_from_a_in_b(beamletIndices, range(M_blk)):
tc.append_log(tc.V_ERRORS, 'Specified --beamlets %s must fit in range(%d)' % (tc.beamlets, M_blk)) tc.append_log(tc.V_ERRORS, 'Specified --beamlets %s must fit in range(%d)' % (beamletIndices, M_blk))
tc.set_result('FAILED') tc.set_result('FAILED')
sys.exit() sys.exit()
channels = tc.channels channelIndices = tc.channels
if not cm.exist_all_elements_from_a_in_b(channels, range(N_chan_x)): if not cm.exist_all_elements_from_a_in_b(channelIndices, range(N_chan_x)):
tc.append_log(tc.V_ERRORS, 'Specified --channels %s must fit in range(%d)' % (tc.channels, N_chan_x)) tc.append_log(tc.V_ERRORS, 'Specified --channels %s must fit in range(%d)' % (channelIndices, N_chan_x))
tc.set_result('FAILED') tc.set_result('FAILED')
sys.exit() sys.exit()
tc.append_log(3, '>>>') tc.append_log(3, '>>>')
tc.append_log(1, '>>> Title : Test case to verify visibility packet header and zero/non-zero payload of correlator DB OUTPUT for %s' % tc.unb_nodes_string()) tc.append_log(1, '>>> Title : Test case to verify visibility packet header and zero/non-zero payload of correlator DB OUTPUT for %s' % tc.unb_nodes_string())
tc.append_log(3, '>>> . beamlet(s) : %s (from range(M_blk) = [0:%d])' % (beamlets, M_blk-1)) tc.append_log(3, '>>> . beamlet(s) : %s (from index range(M_blk) = [0:%d])' % (beamletIndices, M_blk-1))
tc.append_log(3, '>>> . channel(s) : %s (from range(N_chan_x) = [0:%d])' % (channels, N_chan_x-1)) tc.append_log(3, '>>> . channel(s) : %s (from index range(N_chan_x) = [0:%d])' % (channelIndices, N_chan_x-1))
tc.append_log(3, '')
tc.append_log(3, '>>> . activeDishes : %s is %s from %s' % (activeDishes, tc.telStrList, apr.wsrtTelescopes))
tc.append_log(3, '>>> . activePolarizations : %s is %s' % (activePolarizations, tc.to_pol_xy(tc.polNrs)))
tc.append_log(3, '>>> . activeTp : %s' % activeTp)
tc.append_log(3, '>>> . activeVis : %s' % activeVis)
tc.append_log(3, '>>> . activeAutoVis : %s' % activeAutoVis)
tc.append_log(3, '>>>') tc.append_log(3, '>>>')
tc.append_log(3, '') tc.append_log(3, '')
io = node_io.NodeIO(tc.nodeImages, tc.base_ip) io = node_io.NodeIO(tc.nodeImages, tc.base_ip)
# Create one DB object for all PN # Create correlator output object
db_output = pi_diag_data_buffer.PiDiagDataBuffer(tc, io, instanceName='OUTPUT', nofStreams=1, ramSizePerStream=c_dbSize, version=0) rsub = pi_apr.declare_reorder_subbands(tc, io)
rbeam = pi_apr.declare_reorder_beamlets(tc, io)
corDb = pi_apr.CorrelatorOutputDataBuffer(tc, io, rsub, rbeam, dbSize=1024) # assume minimum DB size that can fit 1 visibility packet
for bui in beamlets:
for ch in channels:
############################################################################### ###############################################################################
# Stimuli # Stimuli
# Overwrite DB data to be able to recognize new data # Setup and read DB output to capture the visibility packets
db_output.overwrite_all_data_buffers(data=c_dbPattern, vLevel=9) for bui in beamletIndices:
for chi in channelIndices:
# Use start of packet address for DB sync delay corDb.read_correlator_db_output(bui, chi)
sopAddr = ((bui * N_chan_x) + ch) * corrPacketInfo.vis_packet_size
dbSyncDelay = sopAddr
db_output.write_sync_delay(data=dbSyncDelay)
db_output.read_sync_delay()
# when dbSyncDelay=0 then the DB is written every sync
# else need to arm the DB using write access strobe to capture once at next sync + dbSyncDelay + latency(14)
if dbSyncDelay>0:
# Wait unit DB is ready to arm
tc.sleep(2)
db_output.write_arm_reg(data=1)
# Wait unit DB have been filled
tc.sleep(2)
# Read DB on all PN
dbOutputReadData = db_output.read_data_buffer(nofColumns=tc.nofCol)
###############################################################################
# Verification per PN
for ni,nr in enumerate(tc.nodeNrs): # loop PN
# Get read packet data
rdData = dbOutputReadData[ni]
# Get packet info # Verify visibility packet headers
unb = nr / nof_pn # = range(N_band) = 0:15 = [0:127] / 8 corDb.verify_correlator_db_output_headers(beamletIndices, channelIndices)
pn = nr % nof_pn # = range(nof_pn) = 0:7 = [0:127] % 8
reportStr = 'unb = %2d, pn = %d, bui = %3d, ch = %2d : ' % (unb, pn, bui, ch)
###################################################################
# Verify header fields
# Beamlet mapping as specified in SP-062 table 6 (SC1), 9 (SC4): # Verify visibility payload data
#
# u bi dest bui
# 0 0 0 FN0 0 2 ...
# 1 0 1 FN1 256 258 ...
# 2 0 2 FN2 512 514 ...
# 3 0 3 FN3 768 770 ...
# 0 1 4 BN0 1 3 ...
# 1 1 5 BN1 257 259 ...
# 2 1 6 BN2 513 515 ...
# 3 1 7 BN3 769 771 ...
# #
# Beamlet mapping as implemented in Apertif X due to reordered_sosi_arr wiring in node_apertif_unb1_correlator_mesh.vhd: # A visibility packet contains all N_vis = 300 complex visibilities for one (beamlet, channel):
#
# u bi dest bui
# 0 0 0 FN0 0 2 ...
# 1 0 1 FN1 1 3 ...
# 2 0 2 FN2 256 258 ...
# 3 0 3 FN3 257 259 ...
# 0 1 4 BN0 512 514 ...
# 1 1 5 BN1 513 515 ...
# 2 1 6 BN2 768 770 ...
# 3 1 7 BN3 769 771 ...
expBeamlet = N_slot * unb # offset for UniBoard band
expBeamlet = expBeamlet + N_clk * (pn / Q_interleave) + (pn % Q_interleave) # offset for Local PN
expBeamlet = expBeamlet + bui * Q_interleave # offset serial beamlets
expChannel = cm.reverse_bits(ch, N_chan_x_w)
expChannel = cm.invert_msbit(expChannel, N_chan_x_w)
# Header fields
# 0 gap(16) + ETH dst mac hi(16)
# 1 ETH dst mac lo
# 2 ETH src mac hi
# 3 ETH src mac lo(16) + type(16)
# 4 IP
# 5 IP
# 6 IP
# 7 IP src addr
# 8 IP dst addr
# 9 UDP src port(16) + dst port(16)
# 10 UDP total len(16) + checksum(16)
# 11 ID marker(8) + version(8) + beamlet(16)
# 12 ID channel(16) + rsvd(16)
# 13 ID timestamp hi
# 14 ID timestamp lo
# 15 FLAG
# 16 FLAG
# 17 FLAG
# 18 FLAG
# 19 FLAG
# 20 FLAG
# . dst mac as defined in central_commands.sh
if unb< 4: expDstMac = c_baseDstMacEth01
elif unb< 8: expDstMac = c_baseDstMacEth01 + 1
elif unb<12: expDstMac = c_baseDstMacEth23
elif unb<16: expDstMac = c_baseDstMacEth23 + 1
rdDstMac = cm.to_unsigned(rdData[0], 16) << 32
rdDstMac += cm.to_unsigned(rdData[1], 32)
if rdDstMac == expDstMac:
tc.append_log(tc.V_INFO_DETAILS, reportStr + 'destination MAC = 0x%012X is OK' % rdDstMac)
else:
tc.append_log(tc.V_ERRORS, reportStr + 'read destination MAC is wrong (read 0x%012X != 0x%012X expected)' % (rdDstMac, expDstMac))
tc.set_result('FAILED')
# . src mac
expSrcMac = c_baseSrcMac + unb * 256 + pn
rdSrcMac = cm.to_unsigned(rdData[2], 32) << 16
rdSrcMac += cm.to_unsigned(rdData[3], 32) >> 16
if rdSrcMac == expSrcMac:
tc.append_log(tc.V_INFO_DETAILS, reportStr + 'source MAC = 0x%012X is OK' % rdSrcMac)
else:
tc.append_log(tc.V_ERRORS, reportStr + 'read source MAC is wrong (read 0x%012X != 0x%012X expected)' % (rdSrcMac, expSrcMac))
tc.set_result('FAILED')
# . ID marker
rdIdMarker = cm.to_unsigned(rdData[11], 32) >> 24
if rdIdMarker == c_expIdMarker:
tc.append_log(tc.V_INFO_DETAILS, reportStr + 'ID marker = %d is OK' % rdIdMarker)
else:
tc.append_log(tc.V_ERRORS, reportStr + 'read ID marker is wrong (read %d != %d expected)' % (rdIdMarker, c_expIdMarker))
tc.set_result('FAILED')
# . ID version
rdIdVersion = cm.to_unsigned(rdData[11], 24) >> 16
if rdIdVersion == c_expIdVersion:
tc.append_log(tc.V_INFO_DETAILS, reportStr + 'ID version = %d is OK' % rdIdVersion)
else:
tc.append_log(tc.V_ERRORS, reportStr + 'read ID version is wrong (read %d != %d expected)' % (rdIdVersion, c_expIdVersion))
tc.set_result('FAILED')
# . beamlet
rdBeamlet = cm.to_unsigned(rdData[11], 16)
if rdBeamlet == expBeamlet:
tc.append_log(tc.V_INFO_DETAILS, reportStr + 'beamlet = %d is OK' % rdBeamlet)
else:
tc.append_log(tc.V_ERRORS, reportStr + 'read beamlet is wrong (read %d != %d expected)' % (rdBeamlet, expBeamlet))
tc.set_result('FAILED')
# . channel
rdChannel = cm.to_unsigned(rdData[12], 32) >> 16
if rdChannel == expChannel:
tc.append_log(tc.V_INFO_DETAILS, reportStr + 'channel = %d is OK' % rdChannel)
else:
tc.append_log(tc.V_ERRORS, reportStr + 'read channel is wrong (read %d != %d expected)' % (rdChannel, expChannel))
tc.set_result('FAILED')
# . timestamp (= bsn)
rdBsn = cm.to_unsigned(rdData[13], 32) << 32
rdBsn += cm.to_unsigned(rdData[14], 32)
tc.append_log(tc.V_INFO_DETAILS, reportStr + 'read BSN = %d' % rdBsn)
###################################################################
# Verify payload data
#
# A visibility packet contains all N_vis = 300 visibilities for one (beamlet, channel):
# - The visibilities for which at least one TP is inactive must be zero, because for those TP the # - The visibilities for which at least one TP is inactive must be zero, because for those TP the
# firmware forces the data to zero. # firmware forces the data to zero.
# - If both TP in a visibility are active, then the visibility can be non-zero. The visibility # - If both TP in a visibility are active, then the visibility can be non-zero. The visibility
...@@ -298,18 +141,13 @@ for bui in beamlets: ...@@ -298,18 +141,13 @@ for bui in beamlets:
# #
# 24 + 23 + 22 ... + 1 = 300 visibilities # 24 + 23 + 22 ... + 1 = 300 visibilities
# #
# The visibilities are stored in two 32b words: real, imag, so in total 600 words payload. for gn in tc.nodeNrs: # loop active PN
rdPayload = rdData[corrPacketInfo.vis_header_size:corrPacketInfo.vis_header_size+N_vis*cm.c_nof_complex] unb, pn = apr.correlator_gn_to_unb_pn(gn)
rdVisibilities = [] for bui in beamletIndices: # loop serial beamlets
even = True for chi in channelIndices: # loop serial channels
for data in rdPayload: reportStr = 'unb = %2d, pn = %d, bui = %3d, chi = %2d : ' % (unb, pn, bui, chi)
dataNtoh = cm.reverse_word(data) # change endianess
if even: rdVisibilities = corDb.dbOutputVisibilities[gn][bui][chi]
visReal = cm.to_signed(dataNtoh, 32)
else:
visImag = cm.to_signed(dataNtoh, 32)
rdVisibilities.append(complex(visReal, visImag))
even = not even
# Find the TP for all read visibilities that are non-zero # Find the TP for all read visibilities that are non-zero
nonZeroVisibilities = cm.find_indices_where_ne(rdVisibilities, 0) nonZeroVisibilities = cm.find_indices_where_ne(rdVisibilities, 0)
...@@ -319,9 +157,12 @@ for bui in beamlets: ...@@ -319,9 +157,12 @@ for bui in beamlets:
nonZeroPolarizations = apr.tp_to_pol_indices(nonZeroTp) nonZeroPolarizations = apr.tp_to_pol_indices(nonZeroTp)
nonZeroAutoVisibilities = apr.get_auto_visibilities(nonZeroTp) nonZeroAutoVisibilities = apr.get_auto_visibilities(nonZeroTp)
# Verify that the active TP yield non-zero visibilities # Verify that only the active TP yield non-zero visibilities
# . Assume the BF weights have been set to select at least one ADC input per CB then the input (sky) noise at the ADC # . Assume the BF weights have been set to select at least one ADC input per CB then the input (sky) noise at the ADC
# will contribute to all channels, so the visibilities for the TP pairs of active TP will then be none zero. # will contribute to all channels, so the visibilities for the TP pairs of active TP will then be none zero.
for vi in nonZeroVisibilities:
tc.append_log(tc.V_INFO_DETAILS, reportStr + 'Non zero correlation[%d] = %s' % (vi, rdVisibilities[vi]))
if activeTp == nonZeroTp: if activeTp == nonZeroTp:
tc.append_log(tc.V_INFO_DETAILS, reportStr + 'Non zero TP = %s : polarizations = %s and dishes = %s are OK' % (nonZeroTp, nonZeroPolarizations, nonZeroDishes)) tc.append_log(tc.V_INFO_DETAILS, reportStr + 'Non zero TP = %s : polarizations = %s and dishes = %s are OK' % (nonZeroTp, nonZeroPolarizations, nonZeroDishes))
else: else:
...@@ -333,7 +174,10 @@ for bui in beamlets: ...@@ -333,7 +174,10 @@ for bui in beamlets:
for ai in nonZeroAutoVisibilities: for ai in nonZeroAutoVisibilities:
atp2 = apr.visibilities_to_tp_pairs(ai) atp2 = apr.visibilities_to_tp_pairs(ai)
atp = atp2[0][0] # get tp from list with one tuple(tp, tp), both tp in tuple are the same index for auto correlation visibility atp = atp2[0][0] # get tp from list with one tuple(tp, tp), both tp in tuple are the same index for auto correlation visibility
if not (rdVisibilities[ai].real>0 and rdVisibilities[ai].imag==0): if rdVisibilities[ai].real>0 and rdVisibilities[ai].imag==0:
tc.append_log(tc.V_INFO_DETAILS, reportStr + 'Auto correlation[%d] = %s' % (ai, rdVisibilities[ai]))
else:
tc.append_log(tc.V_ERRORS, reportStr + 'Auto correlation[%d] = %s is wrong' % (ai, rdVisibilities[ai]))
atpFail.append(atp) atpFail.append(atp)
#print ai, atp2, atp, rdVisibilities[ai] #print ai, atp2, atp, rdVisibilities[ai]
if len(atpFail)==0: if len(atpFail)==0:
...@@ -348,3 +192,4 @@ for bui in beamlets: ...@@ -348,3 +192,4 @@ for bui in beamlets:
tc.set_section_id('') tc.set_section_id('')
tc.append_log(tc.V_RESULT, '>>> Test result: %s' % tc.get_result()) tc.append_log(tc.V_RESULT, '>>> Test result: %s' % tc.get_result())
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment