diff --git a/.gitattributes b/.gitattributes index f4f68e0047ea89dd925fbaeadd0389380bc47a99..90e8ece855f8ad1609d70a80813869d7c3e7010f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1149,6 +1149,51 @@ SHM/Components/WebInterface/testing/djstart/playpen/urls.py -text SHM/apache_config/httpd.conf -text SHM/apache_config/sites-enabled/001-shmprod -text SHM/apache_config/sites-enabled/002-shmdev -text +StationTest/README.txt -text +StationTest/bootstrap -text +StationTest/gold/prbs_dir_test.gold -text +StationTest/gold/rsp_version.gold -text +StationTest/gold/tbb_version.gold -text +StationTest/gold/xst.m -text +StationTest/gold/xst_160.gold -text +StationTest/gold/xst_200_even.gold -text +StationTest/gold/xst_200_odd.gold -text +StationTest/i2c_spu.py -text +StationTest/i2c_td.py -text +StationTest/modules/cli.py -text +StationTest/modules/mep.py -text +StationTest/modules/rsp.py -text +StationTest/modules/smbus.py -text +StationTest/modules/testcase.py -text +StationTest/modules/testlog.py -text +StationTest/prbs_dir_test.py -text +StationTest/prbs_test.py -text +StationTest/rmfiles.sh -text +StationTest/rsp_version.sh -text +StationTest/rsp_xc_160.sh -text +StationTest/rsp_xc_200.sh -text +StationTest/station_production.py -text +StationTest/subrack_production.py -text +StationTest/subracktest.sh -text +StationTest/tbb_prbs_tester.sh -text +StationTest/tbb_version.sh -text +StationTest/tc/bist.py -text +StationTest/tc/empty.py -text +StationTest/tc/hba_client.py -text +StationTest/tc/hba_server.py -text +StationTest/tc/prsg.py -text +StationTest/tc/rad_lanemode.py -text +StationTest/tc/rad_latency.py -text +StationTest/tc/serdes.py -text +StationTest/tc/spustat.py -text +StationTest/tc/status.py -text +StationTest/tc/sync_delay.py -text +StationTest/tc/tdstat.py -text +StationTest/verify.py -text +StationTest/xc_160_setup.sh -text +StationTest/xc_160_verify.sh -text +StationTest/xc_200_setup.sh -text +StationTest/xc_200_verify.sh -text SubSystems/CEPCU_MAC/lofarconf.in -text SubSystems/LCU_MAC/lofarconf.in -text SubSystems/MCU_MAC/lofarconf.in -text diff --git a/StationTest/Makefile.am b/StationTest/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..4c094293917318ca8992b2fca5f67f12454eba5c --- /dev/null +++ b/StationTest/Makefile.am @@ -0,0 +1,23 @@ +SUBDIRS = modules gold tc + +testdir = $(prefix)/stationtest +test_SCRIPTS = README.txt \ + i2c_spu.py \ + i2c_td.py \ + prbs_dir_test.py \ + prbs_test.py \ + rmfiles.sh \ + rsp_version.sh \ + rsp_xc_160.sh \ + rsp_xc_200.sh \ + subrack_production.py \ + subracktest.sh \ + tbb_prbs_tester.sh \ + tbb_version.sh \ + verify.py \ + xc_160_setup.sh \ + xc_160_verify.sh \ + xc_200_setup.sh \ + xc_200_verify.sh + +include $(top_srcdir)/Makefile.common diff --git a/StationTest/README.txt b/StationTest/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..fd5eb2f8951b9d52a10f7fb6160dc1358e1bf45a --- /dev/null +++ b/StationTest/README.txt @@ -0,0 +1,303 @@ +# +# Test scripts for LOFAR station regression, production and operation tests. +# +# 2 sep 2008 Eric Kooistra First working test environment. +# 31 oct 2008 Eric kooistra More readme info. +# Added subrack_production.py, smbus.py, spustat.py, +# tdstat.py, hba_client.py, hba_server.py +# + +################################################################################ +1) Introduction + +a) Purpose +This test suite uses scripts that call rsptcl and tbbctl to control a LOFAR +station. Most scripts are written in Python. The test suite offers modules +written in Python that allow easy access to rspctl and tbbctl, and that offer +pass/fail handling and logging. The test scripts allow focussing on a typical +function or interface of the station, therefore they can be used for: + +- regression tests (e.g. functional coverage tests) +- production tests (e.g. chip interface, board interface tests) +- stress tests (e.g. many HBA write, read accesses) +- operation sanity tests + +b) Why Python? +For tool interfacing TCL is the common script language, that is why the VHDL +developent using Modelsim uses TCL scripts. The problem with the remote station +TCL scripts is that they run under Windows using WinPCap to interface with the +Ethernet card. TCL is platform independent, but there is no easy equivalent for +WinPCAP under Linux. Hence it is not straigthforward to run the TCL testcases +environment also under Linux on the LCU. +Instead of using something like WinPCap the low level register access functions +--readblock and --writeblock were added to rspctl . This allows controlling the +RSP board via scripts. +Python was choosen as test script language, because it is a popular script +language and adopted at various levels within the LOFAR software development, +including operations. Based on my experience in translating TCL scripts into +Python equivalents I think that Python is a more natural and nicer language than +TCL. + + +################################################################################ +2) Test setup + +a) Directory structure + ./ : README.txt, Python scripts, bash scripts. Run from this directory. + modules/ : Python modules + gold/ : Golden result files for corresponding scripts, 'diff *.log *.gold' + should yield no difference for the test to pass + tc/ : Testcase scripts to be used with verify.py + +b) This test suite uses different types of test scripting: + + - Testcase Python scripts in tc/ called via verify.py + . e.g.: tc/status.py, tc/bist.py, tc/prsg.py + . verify.py offers argument parsing, test result logging + . Resembles TCL testcase structure used for gateware development tests + . Most scripts in tc/ are direct (manual) translations of the TCL test + scripts that were used for the gateware (VHDL) development, see + LOFAR-ASTRON-MEM-186. The Python / rspctl test scripts run rather slow, + about a factor 2 slower than a comparable TCL / C test script. + - Stand alone Python scripts + . e.g.: python i2c_spy.py + . suitable for simple tests without argument passing + - BASH shell scripts + . e.g.: ./rsp_version.sh + + All these individual test scripts can be combined: + . e.g. for production test, regression test + . e.g. subracktest.sh + +c) Environment setting + + The scripts run from ./ The search path needs to be set: + export PYTHONPATH=./modules + or absolute path + export PYTHONPATH=/home/lofartest/ptest/modules + or to add the path + export PYTHONPATH=$PYTHONPATH:./modules + or on older systems + PYTHONPATH=$PYTHONPATH:./modules + export PYTHONPATH + + If rspctl is called then there must be a directory ../log/ for rspctl.log. + This ../log/ can be a symbolic link. + + +d) RSPDriver.conf + +To allow the 'rspctl --readblock' and 'rspctl --writeblock' low level access +commands the RSP driver in /opt/lofar/etc/ must have: + + RSPDriver.READ_RAW_DATA = 1 + RSPDriver.WRITE_RAW_DATA = 1 + +For tests that access the SPU or TDS, the RSP driver regular accesses via TDSH +must be stopped via: + + RSPDriver.READWRITE_TDSSTATUS=0 + + +################################################################################ +3) Test modules: + +cli.py - Command line interface access +verify.py - Run one or more test scripts after parsing the arguments from the + command line +testcase.py - Testcase pass/fail control, timing and logging for testcases that + run with verify.py +testlog.py - Similar to testcase.py, provides pass/fail control, timing and + logging for standalone test scripts like subrack_production.py +mep.py - MEP interface for RSP board access via 'rspctl --readblock/ + rspctl --writeblock' +rsp.py - RSP board register access functions +smbus.py - SMBus (I2C) access functions + + +Remarks: + +a) To see all script options (both general and test case specific) do: + + python verify.py --help + + Remarks: + - via --brd a test can be ran for one RSP or multiple + - via --fpga a test can be ran on the BP, AP0, AP1, AP2, and/or AP3 in any + combination + - via --pol a test can be ran on RCU x and/or RCU y of the AP. + - There are 2 RCU per AP and 4 AP per RSP. In a station the RCUs are + numbered starting from 0. Hence e.g. RCU[64] = (rsp8, blp0, x) and + RCU[65] = (rsp8, blp0, y). + +b) Classes: + - mep.py defines class MepMessage + - testcase.py defines class Testcase + - testlog.py defines class Testlog + The other modules cli.py, rsp.py and smbus.py define plain functions. Classes + are a nice way of grouping constants and functions to an object, for mep.py + the object it the message string that can be manipulated and access through + the class functions. Similar smbus.py could have been written as a class to + with the protocol_list and protocol_result as objects. I do not know what is + the best approach and why. With smbus.py as a plain set of functions it is + also clear that the functions belong together, because they are called using + the module name as prefix. + +c) The 'rspctl --readblock' and 'rspctl --writeblock' are quite slow, due to: + - the double buffering in the RSP driver + - maybe rspctl excepts only one access per pps interval + - the hex translations in mep.py to adhere to the format ot rspctl + For scripts that only use these low level peek and poke rsptcl commands it + would be a great improvement to have a dedicated driver program that takes + care of these low level commands. This may be a driver program or some C + functions that can be used directly in Python. The scripts can then remain as + they are, only a different mep.py module needs to be added. + +d) Some scripts also use higher level rspctl commands, e.g. to set the RCU in + PSRG mode. + +e) Typically all RSP access goes via functions in rsp.py and smbus.py. Hence in + a test script it should never be necessary to call the low level rspctl + commands directly. + +f) I tried to follow the Python documentation rules. For example to read the + documentation in the module rsp.py do: + + python + >>> import rsp + >>> dir(rsp) + >>> print rsp.__doc__ + >>> print rsp.write_mem.__doc__ + +g) When command line options are needed I use the Python option parser. For the + test scripts all command line options need to be defined in testcase.py. + There are some general test script options (e.g. --brd) but there are also + test script specific options (e.g. --pid). The general testcase options are + passed on via the Testcase class, the specific options are passed on as + directly and all get prefix 'arg_' in verify.py to easily recognize them. + +h) For logging I followed the logging approach that was used for the RSP test + environment written in TCL. Python also has modules for logging thay may be + useful in future. + + +################################################################################ +4) Test scripts in tc/ + +a) The testcases in tc/ are ran using verify.py. The test results are reported + to the screen and also stored in tc/ in a *.log file with the same name. The + ammount of logging depends on the verbosity level set by option -v. + + To run a testcase with verify.py in ./ do: + + python verify.py --brd rsp0 --fp blp0 --te tc/prsg.py -v 21 + + To run a testcase for one subrack with 4 RSP do: + + python verify.py --brd rsp0,rsp1,rsp2,rsp3 --rep 1 -v 21 --te tc/serdes.py + + To run a testcase for a station with three subracks, so 12 RSP do: + + python verify.py --brd rsp0,rsp1,rsp2,rsp3,rsp4,rsp5,rsp6,rsp7,rsp8,rsp9, + rsp10,rsp11 --te tc/serdes.py + + Remarks: + - The default option parameter values are defined in verify.py + - For options with multiple parameters the parameters must form one continuous + string seperated by commas's. + +b) The following test scripts are available in tc/, they are more or less plain, + manual translations from TCL test cases: + + - empty.py = empty, can be used to try verify.py + - prsg.py = TC 5.10, capture RCU PSRG data + - serdes.py = TC 3.8, serdes ring test + - status.py = TC 11.1, read RSP status register + - spustat.py = TC 9.6, read SPU sensor status <=> 'rspctl --spustat' + - tdstat.py = TC 9.1, read TD sensor status <=> 'rspctl --tdstat' + - hba_client = TC 5.42, read or write to a HBA client register at the RCU + - hba_server = TC 5.43, read or write to a HBA server register at the tile + +c) 'rspctl --readblock' and 'rspctl --writeblock' + + If available high level rspctl options are used to set up things, e.g. like + the PRSG on an RCU. For other low level board control use the direct access + '--readblock' and '--writeblock' options of rspctl. The modules mep.py and + rsp.py provide easy interfacing with theses options. + +d) For help on the testcase usage and options do: + + python verify.py --help + +e) To delete temporary files do: + + ./rmfiles.sh + +f) Verbosity level (-v) + The testcases all adhere to the following verbosity level convention: + + -v 0 : show PASSED or FAILED + -v 1 : show testcase title + -v 2 : show testcase time + -v 11 : show '... went wrong' for each step or section in a testcase, plus + some more info like expected result and read result + -v 21 : show '... went OK' for each step or section in a testcase + -v 22 : show rspctl commands + -v 23 : show rspctl command return results + +g) Pass/fail + Default a testcase run using verify.py/testcase.py (or using testlog.py) gets + pass/fail status 'RUNONLY'. This is useful for test scripts that are + utilities. If the testcase checks for expected results then it one of the it + should first initialized the tc result to 'PASSED'. Subsequently each step in + the testcase that fails should also set the tc result to 'FAILED'. Once the + tc status is 'FAILED' it can not change anymore. + +h) Test scripts and the RSP driver + The test scripts use rspctl. Some test scripts do not affect the functional + behaviour of the RSP driver, however many scripts do. Due to the slow and + asynchronlous behaviour of teh test scripts it is often handy to disable the + external sync (pps). The scripts also enable the external sync again, but + if that does not recover normal rspctl behaviour then it may be necessary to + do a 'rspctl --rspclear' or restart the RSP driver via swlevel 1, swlevel 2. + + +################################################################################ +5) More examples + +a) HBA client access + To read the speed register of HBA client on RCU[65] do: + + python verify.py --brd rsp8 --fp blp0 --rep 1 -v 21 --te tc/hba_client.py + --client_access r --client_reg speed --data 1 + + The test will only signal pass if the --data value equals the read speed + value, hence for read the --data option is used as expected result. + +b) HBA server access + To read the delay settings for polarization X and Y of HBA server 2 on the + HBA tile of RCU[64]=X (power via X) and RCU[65]=Y (control via Y) do: + + python verify.py --brd rsp8 --fp blp0 --rep 1 -v 21 --te tc/hba_server.py + --server 2 --server_access uc --server_function gw + --server_reg delay_x --data 50,51 + + +################################################################################ +6) Standalone test scripts + +a) Subrack production tests + +The Python script subrack_production.py runs the subrack production test, it +requires a batch nr and a serial nr that will be used to name the log file. + + python subrack_production.py --help + python subrack_production.py -b 3 -s 2 + +This subrack_production.py replaces subracktest.sh. + +b) Various + + i2c_spu.py = uses 'rspctl --spustat' to verify SPU sensor status + i2c_td.py = uses 'rspctl --spustat' to verify TDS sensor status + diff --git a/StationTest/bootstrap b/StationTest/bootstrap new file mode 100755 index 0000000000000000000000000000000000000000..06f18cde1dbfd6912ef7d927c4d35d25c7137a62 --- /dev/null +++ b/StationTest/bootstrap @@ -0,0 +1,3 @@ +#!/bin/sh + +../../../autoconf_share/bootstrap ../../../autoconf_share diff --git a/StationTest/configure.in b/StationTest/configure.in new file mode 100644 index 0000000000000000000000000000000000000000..4fcf2bda2634d76ed941ff55daa69eeb44ebdda2 --- /dev/null +++ b/StationTest/configure.in @@ -0,0 +1,12 @@ +AC_INIT(README.txt) +AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE(Station, 1.0, no-define) + +AC_PROG_LIBTOOL + +AC_OUTPUT( + Makefile + gold/Makefile + modules/Makefile + tc/Makefile +) diff --git a/StationTest/gold/Makefile.am b/StationTest/gold/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..46aa24695c7dcfad3a14ecee01a2319f53a15a37 --- /dev/null +++ b/StationTest/gold/Makefile.am @@ -0,0 +1,9 @@ +testdir = $(prefix)/stationtest/gold +test_SCRIPTS = prbs_dir_test.gold \ + rsp_version.gold \ + tbb_version.gold \ + xst_160.gold \ + xst_200_even.gold \ + xst_200_odd.gold + +include $(top_srcdir)/Makefile.common diff --git a/StationTest/gold/prbs_dir_test.gold b/StationTest/gold/prbs_dir_test.gold new file mode 100644 index 0000000000000000000000000000000000000000..99aaecba65323dda3992932384284bc2510e3b79 --- /dev/null +++ b/StationTest/gold/prbs_dir_test.gold @@ -0,0 +1,68 @@ + + + PRSB test + +Frame nr 0 Station 1 RSP 0 RCU 0 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 0 RCU 1 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 0 RCU 2 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 0 RCU 3 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 0 RCU 4 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 0 RCU 5 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 0 RCU 6 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 0 RCU 7 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 1 RCU 8 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 1 RCU 9 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 1 RCU 10 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 1 RCU 11 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 1 RCU 12 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 1 RCU 13 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 1 RCU 14 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 1 RCU 15 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 2 RCU 16 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 2 RCU 17 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 2 RCU 18 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 2 RCU 19 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 2 RCU 20 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 2 RCU 21 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 2 RCU 22 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 2 RCU 23 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 3 RCU 24 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 3 RCU 25 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 3 RCU 26 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 3 RCU 27 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 3 RCU 28 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 3 RCU 29 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 3 RCU 30 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 +Frame nr 0 Station 1 RSP 3 RCU 31 Sample rate 200 MHz +Samples checked : 10239 PRBS errors: 0 diff --git a/StationTest/gold/rsp_version.gold b/StationTest/gold/rsp_version.gold new file mode 100644 index 0000000000000000000000000000000000000000..71915568991f8e6bf586340cfbe731800e1aad3a --- /dev/null +++ b/StationTest/gold/rsp_version.gold @@ -0,0 +1,4 @@ +RSP[ 0] RSP version = 4, BP version = 4.13, AP version = 4.13 +RSP[ 1] RSP version = 4, BP version = 4.13, AP version = 4.13 +RSP[ 2] RSP version = 4, BP version = 4.13, AP version = 4.13 +RSP[ 3] RSP version = 4, BP version = 4.13, AP version = 4.13 diff --git a/StationTest/gold/tbb_version.gold b/StationTest/gold/tbb_version.gold new file mode 100644 index 0000000000000000000000000000000000000000..6d3133946f03546a8b40db86c5e92e9767edb7a1 --- /dev/null +++ b/StationTest/gold/tbb_version.gold @@ -0,0 +1,11 @@ + +== TBB ====================================== ID and version information ==== + +TBBDriver software version 2.00 + +TBB ID Software Board TP0 MP0 MP1 MP2 MP3 +--- -- -------- ------- ------- ------- ------- ------- ------- + 0 0 V 2.0 V 0.2 V 1.6 V 1.6 V 1.6 V 1.6 V 1.6 + 1 2 V 2.0 V 0.2 V 1.6 V 1.6 V 1.6 V 1.6 V 1.6 + +== normal termination of tbbctl ============================================== diff --git a/StationTest/gold/xst.m b/StationTest/gold/xst.m new file mode 100644 index 0000000000000000000000000000000000000000..c6eee9a60977e6c7f437c99d72c9b8137f093d44 --- /dev/null +++ b/StationTest/gold/xst.m @@ -0,0 +1,29 @@ +% +% Utility to examine XST data +% + +%cd C:\svnroot\LOFAR\trunk\MAC\Test\Station\gold +close all +% golden XST data +fid = fopen('xst_160.gold','r') +data_gold = fread(fid,'double') +fclose(fid) +corr_gold = reshape(data_gold(1:2:end) + i * data_gold(2:2:end), [32,32]) +figure(1) +imagesc(abs(corr_gold)) +colorbar +figure(2) +imagesc(angle(corr_gold)) +colorbar + +% new XST data +fid = fopen('xst.dat','r') +data = fread(fid,'double') +fclose(fid) +corr = reshape(data(1:2:end) + i * data(2:2:end), [32,32]) +figure(3) +imagesc(abs(corr)) +colorbar +figure(4) +imagesc(angle(corr)) +colorbar diff --git a/StationTest/gold/xst_160.gold b/StationTest/gold/xst_160.gold new file mode 100644 index 0000000000000000000000000000000000000000..028a0359218d24ffea62e82480cd199f9fa46172 Binary files /dev/null and b/StationTest/gold/xst_160.gold differ diff --git a/StationTest/gold/xst_200_even.gold b/StationTest/gold/xst_200_even.gold new file mode 100644 index 0000000000000000000000000000000000000000..0b0b7fe23fded1d1acea55d98510d328fd959f7e Binary files /dev/null and b/StationTest/gold/xst_200_even.gold differ diff --git a/StationTest/gold/xst_200_odd.gold b/StationTest/gold/xst_200_odd.gold new file mode 100644 index 0000000000000000000000000000000000000000..5c689fb51c1a8c0819e177233ae009a03c0304ab Binary files /dev/null and b/StationTest/gold/xst_200_odd.gold differ diff --git a/StationTest/i2c_spu.py b/StationTest/i2c_spu.py new file mode 100644 index 0000000000000000000000000000000000000000..78293b5328cfb4499fb78de53364249732668cc8 --- /dev/null +++ b/StationTest/i2c_spu.py @@ -0,0 +1,64 @@ +"""Testcase for RSP - SPU I2C interface, read SPU sensor information +""" + +################################################################################ +# User imports +import cli + +print '' +print 'Read SPU sensor information to verify the RSP - SPU I2C interface' +print '' + +################################################################################ +# Command line + +appLev = False +cli.command('rm -f spustat.log',appLev) +cli.command('rspctl --spustat > spustat.log',appLev) + +################################################################################ +# Verify result + +f=open('spustat.log','r') +f.readline() # skip title line +data_str = f.readline() # keep measured data line +f.close() + +data_str = data_str.replace(' ','') # remove spaces +data_str = data_str.strip() # remove \n +data = data_str.split('|') # make a list of strings + +volt_5v = float(data[1]) +volt_8v = float(data[2]) +volt_48v = float(data[3]) +volt_3v3 = float(data[4]) +temp_pcb = int(data[5]) + +print '5 V = %5.2f V' % volt_5v +print '8 V = %5.2f V' % volt_8v +print '48 V = %5.2f V' % volt_48v +print '3.3 V = %5.2f V' % volt_3v3 +print 'Temp = %d degrees C' % temp_pcb +print '' + +tc_result = 1 +if volt_5v < 4.5 or volt_5v > 5.5: + print 'Value %f for 5 V is wrong' % volt_5v + tc_result = 0 +if volt_8v < 7.0 or volt_8v > 8.5: + print 'Value %f for 8 V is wrong' % volt_8v + tc_result = 0 +if volt_48v < 44 or volt_48v > 49: + print 'Value %f for 48 V is wrong' % volt_48v + tc_result = 0 +if volt_3v3 < 3.0 or volt_3v3 > 4.0: + print 'Value %f for 3.3 V is wrong' % volt_3v3 + tc_result = 0 +if temp_pcb < 10 or temp_pcb > 40: + print 'Value %f for PCB temperature is wrong' % temp_pcb + tc_result = 0 + +if tc_result == 0: + print 'RSP --> SPU I2C interface test went wrong' +else: + print 'RSP --> SPU I2C interface test went OK' diff --git a/StationTest/i2c_td.py b/StationTest/i2c_td.py new file mode 100644 index 0000000000000000000000000000000000000000..01b5d631bafb402fff37be65a1c31e0b6ad23345 --- /dev/null +++ b/StationTest/i2c_td.py @@ -0,0 +1,54 @@ +"""Testcase for RSP - TD I2C interface, read TD sensor information +""" + +################################################################################ +# User imports +import cli + +print '' +print 'Read TD sensor information to verify the RSP - TD I2C interface' +print '' + +################################################################################ +# Command line + +appLev = False +cli.command('rm -f tdstat.log',appLev) +cli.command('rspctl --tdstat > tdstat.log',appLev) + +################################################################################ +# Verify result + +f=open('tdstat.log','r') +f.readline() # skip title line +data_str = f.readline() # keep measured data line +f.close() + +data_str = data_str.replace(' ','') # remove spaces +data_str = data_str.strip() # remove \n +data = data_str.split('|') # make a list of strings + +volt_3v3 = float(data[6]) +volt_5v = float(data[7]) +temp_pcb = int(data[8]) + +print '3.3 V = %5.2f V' % volt_3v3 +print '5 V = %5.2f V' % volt_5v +print 'Temp = %d degrees C' % temp_pcb +print '' + +tc_result = 1 +if volt_3v3 < 3.0 and volt_5v > 4.0: + print 'Value %f for 3.3 V is wrong' % volt_3v3 + tc_result = 0 +if volt_5v < 4.5 and volt_5v > 5.5: + print 'Value %f for 5 V is wrong' % volt_5v + tc_result = 0 +if temp_pcb < 10 and temp_pcb > 40: + print 'Value %f for PCB temperature is wrong' % temp_pcb + tc_result = 0 + +if tc_result == 0: + print 'RSP --> TD I2C interface test went wrong' +else: + print 'RSP --> TD I2C interface test went OK' diff --git a/StationTest/modules/Makefile.am b/StationTest/modules/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..0d289bbe166c99550d2ac031f1a2b7be228670b9 --- /dev/null +++ b/StationTest/modules/Makefile.am @@ -0,0 +1,9 @@ +testdir = $(prefix)/stationtest/modules +test_SCRIPTS = cli.py \ + mep.py \ + rsp.py \ + smbus.py \ + testcase.py \ + testlog.py + +include $(top_srcdir)/Makefile.common diff --git a/StationTest/modules/cli.py b/StationTest/modules/cli.py new file mode 100644 index 0000000000000000000000000000000000000000..9cb9861031be8bcafa1567a2b8e6058a900acf42 --- /dev/null +++ b/StationTest/modules/cli.py @@ -0,0 +1,14 @@ +"""Command line interface access +""" + +################################################################################ +# System imports +import commands + +################################################################################ +# Functions + +def command(arg, p=False): + if p: + print arg + return commands.getoutput(arg) diff --git a/StationTest/modules/mep.py b/StationTest/modules/mep.py new file mode 100644 index 0000000000000000000000000000000000000000..92a3fb5ca8af152560e328ade0443f2e07a7edef --- /dev/null +++ b/StationTest/modules/mep.py @@ -0,0 +1,366 @@ +"""MEP interface for RSP board access via rspctl --readblock/--writeblock + + See also MepMessage.tcl. + + class MepMessage: + def swap2(self, h) + def swap3(self, h) + def swap4(self, h) + def packAddr(self, blpId, pid, regId) + def clearPayload(self) + def appendPayload(self, hexString) + def lenPayload(self) + def getPayload(self, offset, nof) + def packPayload(self, data, width) + def extractPayload(self, readData) + def unpackPayload(self, width, sign='+') + def setOffset(self, offset=0) + def incrOffset(self, offset=1) + def readUnsigned(self, width): + def readSigned(self, width): +""" + +class MepMessage: + c_blpid = {'blp0' : 1, + 'blp1' : 2, + 'blp2' : 4, + 'blp3' : 8} + + c_pid = {'rsr' :1, + 'rsu' :2, + 'diag' :3, + 'ss' :4, + 'bf' :5, + 'bst' :6, + 'sst' :7, + 'rcuh' :8, + 'cr' :9, + 'xst' :10, + 'cdo' :11, + 'bs' :12, + 'serdes':13, + 'tdsh' :14, + 'tbbi' :15, + 'cep' :16, + 'lcu' :17, + 'rad' :18} + + c_regid = {('rsr','status') : 0, + ('rsr','version') : 1, + ('rsr','timestamp') : 2, + ('rsu','flash') : 1, + ('rsu','erase') : 2, + ('rsu','reconfig') : 3, + ('rsu','sysctrl') : 4, + ('rsu','unprotect') : 5, + ('tdsh','protocol') : 0, + ('tdsh','result') : 1, + ('diag','setx') : 0, + ('diag','sety') : 1, + ('diag','wavex') : 2, + ('diag','wavey') : 3, + ('diag','bypass') : 4, + ('diag','result') : 5, + ('diag','selftest') : 6, + ('bs','psync') : 0, + ('ss','settings') : 0, + ('bf','coefxr') : 0, + ('bf','coefxi') : 1, + ('bf','coefyr') : 2, + ('bf','coefyi') : 3, + ('sst','power') : 0, + ('bst','power0') : 0, + ('bst','power1') : 1, + ('bst','power2') : 2, + ('bst','power3') : 3, + ('xst','r0') : 0, + ('xst','r1') : 1, + ('xst','r2') : 2, + ('xst','r3') : 3, + ('xst','r4') : 4, + ('xst','r5') : 5, + ('xst','r6') : 6, + ('xst','r7') : 7, + ('xst','r8') : 8, + ('xst','r9') : 9, + ('xst','r10') : 10, + ('xst','r11') : 11, + ('xst','r12') : 12, + ('xst','r13') : 13, + ('xst','r14') : 14, + ('xst','r15') : 15, + ('xst','r16') : 16, + ('xst','r17') : 17, + ('xst','r18') : 18, + ('xst','r19') : 19, + ('xst','r20') : 20, + ('xst','r21') : 21, + ('xst','r22') : 22, + ('xst','r23') : 23, + ('xst','r24') : 24, + ('xst','r25') : 25, + ('xst','r26') : 26, + ('xst','r27') : 27, + ('xst','r28') : 28, + ('xst','r29') : 29, + ('xst','r30') : 30, + ('xst','r31') : 31, + ('rcuh','settings') : 0, + ('rcuh','protocolx') : 1, + ('rcuh','resultx') : 2, + ('rcuh','protocoly') : 3, + ('rcuh','resulty') : 4, + ('cr','softrst') : 0, + ('cr','softsync') : 1, + ('cr','syncoff') : 2, + ('cr','syncdelay') : 3, + ('cdo','settings') : 0, + ('cdo','iphdr') : 1, + ('serdes','hdr') : 0, + ('serdes','data') : 1, + ('cep','hdr') : 0, + ('cep','data') : 1, + ('lcu','hdr') : 0, + ('lcu','data') : 1, + ('rad','settings') : 0, + ('rad','latency') : 1, + ('tbbi','settingsx') : 0, + ('tbbi','settingsy') : 1, + ('tbbi','selmemx') : 2, + ('tbbi','selmemy') : 3} + + c_hw = 2 # 2 hex digits per byte + + hexAddr = '' # rspctl --readblock/writeblock ADDR field as string of hex digits + hexPayload = '' # payload string of hex digits + offset = 0 # offset for read hexPayload in nof bytes + + def swap2(self, h): + """Byte swap hex string of two bytes + """ + return h[2:4] + h[0:2] + + def swap3(self, h): + """Byte swap hex string of three bytes + """ + return h[4:6] + h[2:4] + h[0:2] + + def swap4(self, h): + """Byte swap hex string of four bytes + """ + return h[6:8] + h[4:6] + h[2:4] + h[0:2] + + def packAddr(self, blpId, pid, regId): + """Construct string of hex digits for rspctl --readblock/writeblock ADDR field + + Input: + - blpId = list of 'rsp' for BP and/or one or more 'blp#' for AP# to address + - pid = process ID + - regId = register ID of the process + Output: + - self.hexAddr + Return: void + Example: + p=mep.MepMessage() + p.packAddr(['rsp', 'blp0', 'blp1'], 'diag', 'bypass') + """ + ap = 0 + bp = 0 + for i in blpId: + if i=='rsp': + bp = 1 + else: + ap += self.c_blpid[i] + self.hexAddr = '%02x%02x%02x%02x' % (ap, bp, self.c_pid[pid], self.c_regid[(pid,regId)]) + + def clearPayload(self): + """Clear hex payload string + """ + self.hexPayload = '' + + def appendPayload(self, hexString): + """Append hex string to the hex payload string + """ + self.hexPayload += hexString + + def lenPayload(self): + """Return length of the hex payload string in nof bytes + """ + return len(self.hexPayload)/self.c_hw + + def getPayload(self, offset, nof): + """Return hex payload string + + Input: + - offset = Offset in nof bytes + - nof = Nof bytes to get + Return: + - hex string + """ + return self.hexPayload[offset * self.c_hw : (offset + nof) * self.c_hw] + + def packPayload(self, data, width, append=False): + """Pack data list into hex payload string + + Input: + - data = list of numbers + - width = nof bytes per number + - append = when false clear hexPayload first, when true append the data + Output: + - self.hexPayload + Return: void + Example: + p=mep.MepMessage() + p.packPayload([3,-400,50],2) + """ + if append == False: + self.clearPayload() + if width==1: + for i in data: + self.appendPayload(('%02x' % i)[-2:]) # pad 0 for single hex digit, strip sign extension of negative long + elif width==2: + for i in data: + self.appendPayload(self.swap2(('%04x' % i)[-4:])) + else: # width==4: + for i in data: + self.appendPayload(self.swap4(('%08x' % i))) + + def extractPayload(self, readData, append=False): + """Extract hex payload string from rspctl read data + Input: + - readData = echo from rspctl command + - append = when false clear hexPayload first, when true append the read data + Output: + - self.hexPayload + Return: void + """ + if append == False: + self.clearPayload() + j = 1 + for i in range(len(readData)): + if readData[i] == '\n': + j = 0 # found new line + elif readData[i] != ':' and j == 5: + j = -1 # check data start of ':' at pos 5 + elif j > 5 and j < 55: + if readData[i] != ' ': # read the data + self.appendPayload(readData[i]) + if j >= 0: + j += 1 + + def unpackPayload(self, width, sign='+'): + """Unpack data list from hex payload string + + Input: + - self.hexPayload + - width = nof bytes per number + - sign = '+' for unsigned word list, '-' for signed word list + Return: + - list of numbers + Example: + p=mep.MepMessage() + p.packPayload([3,-400,50],2) + p.unpackPayload(2, '-'): + """ + umax = [0, 256, 65536, 0, 4294967296L] # sign convert constant + data = [] + if sign=='+': # unsigned + for i in range(0, self.lenPayload(), width): + d = self.getPayload(i, width) + if width==2: + d = self.swap2(d) + elif width==4: + d = self.swap4(d) + d = int(d,16) + data.append(d) + else: # signed + for i in range(0, self.lenPayload(), width): + d = self.getPayload(i, width) + if width==2: + d = self.swap2(d) + elif width==4: + d = self.swap4(d) + if int(d[0],16)<8: + d = int(d,16) + else: + d = int(d,16)-umax[width] + data.append(d) + return data + + def setOffset(self, offset=0): + """Set offset for read access in payload octets + + Input: + - offset = offset as nof bytes + Output: + - self.offset = offset as nof bytes + Return: void + """ + self.offset = offset + + def incrOffset(self, offset=1): + """Increment offset for read access in payload octets + + Input: + - offset = offset increment in nof bytes + Output: + - self.offset = offset incremented by offset nof bytes + Return: void + """ + self.offset += offset + + def readUnsigned(self, width): + """Read unsigned word from the hex payload string and increment offset + + Input: + - self.hexPayload + - width = nof bytes per number + - self.offset + Return: + - unsigned + Example: + p=mep.MepMessage() + p.packPayload([3,-400,50],2) + p.setOffset(2) + p.readUnsigned(payload, 2) + """ + d = self.getPayload(self.offset, width) + self.incrOffset(width) + if width==2: + d = self.swap2(d) + elif width==3: + d = self.swap3(d) + elif width==4: + d = self.swap4(d) + return int(d,16) + + def readSigned(self, width): + """Read signed from the hex payload string and increment offset + + Input: + - self.hexPayload + - width = nof bytes per number + - self.offset + Return: + - signed + Example: + p=mep.MepMessage() + p.packPayload([3,-400,50],2) + p.setOffset(1) + p.readSigned(payload, 2) + """ + umax = [0, 256, 65536, 0, 4294967296L] # sign convert constant + d = self.getPayload(self.offset, width) + self.incrOffset(width) + if width==2: + d = self.swap2(d) + elif width==3: + d = self.swap3(d) + elif width==4: + d = self.swap4(d) + if int(d[0],16)<8: + d = int(d,16) + else: + d = int(d,16)-umax[width] + return d + diff --git a/StationTest/modules/rsp.py b/StationTest/modules/rsp.py new file mode 100644 index 0000000000000000000000000000000000000000..a17f8cd8201d10b75328d81b98f46b08acccc28c --- /dev/null +++ b/StationTest/modules/rsp.py @@ -0,0 +1,1280 @@ +"""RSP board register access functions + + def rspctl(tc, arg) + + def i2bb(s) + def i2bbbb(s) + def calculate_next_sequence_value(in_word, seq='PRSG', width=12) + def reorder(data, index) + + def write_mem(tc, msg, pid, regid, data, blpId=['blp0'], rspId=['rsp0'], width=2, offset=0, bc=0) + def read_mem(tc, msg, pid, regid, nof, blpId=['blp0'], rspId=['rsp0'], sign='+', width=2, offset=0) + + def write_cr_syncoff(tc, msg, blpId=['blp0'], rspId=['rsp0']) + def write_cr_syncon(tc, msg, blpId=['blp0'], rspId=['rsp0']) + def write_cr_sync_delay(tc, msg, syncdelay=0, syncedge=0, blpId=['blp0'], rspId=['rsp0']) + def read_cr_sync_delay(tc, msg, blpId=['blp0'], rspId=['rsp0'], applev=21) + + def write_diag_bypass(tc, msg, bypass, blpId=['blp0'], rspId=['rsp0'], applev=21) + def read_diag_bypass(tc, msg, blpId=['blp0'], rspId=['rsp0'], applev=21) + def write_diag_selftest(tc, msg, selftest, blpId=['blp0'], rspId=['rsp0'], applev=21) + def read_diag_result_buffer(tc, msg, nof, width, blpId=['blp0'], rspId=['rsp0']) + + def write_rd_smbh_protocol_list(tc, msg, smbh, protocol_list, polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0']) + def overwrite_rd_smbh_protocol_results(tc, msg, smbh, polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0']) + + def write_rsu_altsync(tc, msg, rspId=['rsp0']) + + def overwrite_rsr(tc, msg, procid='all', value=255, rspId=['rsp0']) + def read_rsr(tc, msg, procid='all', rspId=['rsp0'], applev=21) + + def write_rad_settings(tc, msg, settings, rspId=['rsp0'], applev=21) + def read_rad_settings(tc, msg, rspId=['rsp0'], applev=21) + def read_rad_latency(tc, msg, rspId=['rsp0'], applev=21) + + def write_ss(tc, msg, ss_map, blpId=['blp0'], rspId=['rsp0']) + def read_ss(tc, msg, nof, blpId=['blp0'], rspId=['rsp0']) +""" + +################################################################################ +# System imports +import math + +# User imports +import cli +import mep +import smbus + + +################################################################################ +# Constansts (from constants.tcl) + +# From common(pkg).vhd +c_complex = 2 # factor 2 accounting for Re part and Im part of complex number +c_cpx = c_complex +c_phs = c_complex +c_pol = 2 # factor 2 accounting for X and Y polarization +c_pol_phs = c_pol * c_phs + +c_long = 4 + +c_rcu_version = 1 # ctrlreg[23:20] = "0001" in RCU i2cslave(rtl).vhd + +c_ext_clk_freq = 200000000 +c_rcu_clk_freq = c_ext_clk_freq + +c_nof_bp = 1 +c_nof_ap = 4 +c_nof_blp_per_ap = 1 +c_nof_blp = c_nof_ap * c_nof_blp_per_ap + +c_nof_subbands = 512 +c_slice_size = c_cpx * c_nof_subbands + +c_nof_lanes = 4 +c_nof_beamlets = 248 +c_nof_beamlets_per_lane = c_nof_beamlets / c_nof_lanes +c_nof_antennas = 96 +c_nof_crosslets_per_antenna = 1 +c_nof_crosslets = c_nof_antennas * c_nof_crosslets_per_antenna +c_nof_crosslets_per_lane = c_nof_crosslets / c_nof_lanes +c_nof_reflets = c_nof_crosslets_per_antenna +c_nof_reflets_ap = c_nof_crosslets_per_antenna * c_nof_ap +c_nof_beamlets_ap = c_nof_reflets_ap + c_nof_beamlets +c_nof_let_types = 2 + +c_rcu_dat_w = 12 +c_rcu_dat_mask = 2**c_rcu_dat_w - 1 +c_blp_out_dat_w = 18 +c_ring_data_dat_w = c_blp_out_dat_w+2 # = 20 + +c_diag_reg_wave_dat_w = 18 +c_diag_reg_wave_size_small_w = 11 +c_diag_reg_res_word_w = 4 +c_diag_reg_res_size = c_nof_beamlets_ap*c_pol_phs + +c_bf_reg_coef_w = 16 +c_beam_data_dat_w = 24 + +c_ring_dat_w = 14 + +c_tdsh_protocol_adr_w = 11 +c_tdsh_result_adr_w = 10 +c_rcuh_protocol_adr_w = 9 +c_rcuh_result_adr_w = 9 + +c_rad_nof_rx = 1+c_nof_let_types*c_nof_lanes # = 9 + +c_ei_status_rsp_tvolt_offset = 0 +c_ei_status_rsp_tvolt_size = 9 +c_ei_status_rsp_clk_offset = c_ei_status_rsp_tvolt_offset + c_ei_status_rsp_tvolt_size +c_ei_status_rsp_clk_size = 1 +c_ei_status_rsp_offset = 0 # = c_ei_status_rsp_tvolt_offset +c_ei_status_rsp_size = 12 # = c_ei_status_rsp_tvolt_size + c_ei_status_rsp_clk_size rounded to factor of 4 +c_ei_status_eth_offset = c_ei_status_rsp_offset + c_ei_status_rsp_size +c_ei_status_eth_size = 12 +c_ei_status_mep_offset = c_ei_status_eth_offset + c_ei_status_eth_size +c_ei_status_mep_size = 4 +c_ei_status_diag_offset = c_ei_status_mep_offset + c_ei_status_mep_size +c_ei_status_diag_size = 24 +c_ei_status_bs_offset = c_ei_status_diag_offset + c_ei_status_diag_size +c_ei_status_bs_size = 16 # For each AP +c_ei_status_rcuh_offset = c_ei_status_bs_offset + c_nof_blp * c_ei_status_bs_size +c_ei_status_rcuh_size = 12 # For each AP +c_ei_status_rsu_offset = c_ei_status_rcuh_offset + c_nof_blp * c_ei_status_rcuh_size +c_ei_status_rsu_size = 4 +c_ei_status_ado_offset = c_ei_status_rsu_offset + c_ei_status_rsu_size +c_ei_status_ado_size = 8 +c_ei_status_rad_offset = c_ei_status_ado_offset + c_nof_blp * c_ei_status_ado_size +c_ei_status_rad_size = 4 +c_ei_status_rsr_offset = 0 # = c_ei_status_rsp_tvolt_offset +c_ei_status_rsr_size = c_ei_status_rad_offset + c_rad_nof_rx * c_ei_status_rad_size + +c_ei_eth_err_noerr = 0 +c_ei_eth_err_preamblevalue = 1 +c_ei_eth_err_framedelimiter = 2 +c_ei_eth_err_preamblelength = 3 +c_ei_eth_err_headerlength = 4 +c_ei_eth_err_crc = 5 +c_ei_eth_err_oddnibblelength = 6 +c_ei_eth_err_framelength = 7 + +c_ei_mep_err_noerr = 0 +c_ei_mep_err_type = 1 +c_ei_mep_err_addr_blp = 2 +c_ei_mep_err_pid = 3 +c_ei_mep_err_regid = 4 +c_ei_mep_err_offset = 5 +c_ei_mep_err_size = 6 +c_ei_mep_err_ringcrc = 7 +c_ei_mep_err_timeout = 8 + +################################################################################ +# Derived constants (from constants.tcl) + +# - Calculate ADO scale factor based on word widths in ado(rtl).vhd and nof samples per sync interval for 200 MHz +dat_in_w = c_rcu_dat_w +nof_acc_w = math.ceil(math.log(c_rcu_clk_freq)/math.log(2)) +result_w = 32 +acc_w = dat_in_w + nof_acc_w +c_ado_scale = int(round(pow(2, acc_w - result_w))) + +# RSR status +c_rsr_ok = 0 +c_rsr_error = 1 +c_rsr_undefined = 2 + +c_cp_bp = 1 +c_cp_statusRdy = 0 +c_cp_statusVersion0 = 1 +c_cp_statusFpgaType = 2 +c_cp_statusImageType = 3 +c_cp_statusTrigLo = 4 +c_cp_statusTrigHi = 6 +c_cp_statusVersion1 = 7 +c_cp_version_w = 2 +c_cp_trig_w = c_cp_statusTrigHi-c_cp_statusTrigLo+1 +c_cp_trig_mask = (1 << c_cp_trig_w) - 1 +c_cp_trig_ButtonRst = 0 +c_cp_trig_TempRst = 1 +c_cp_trig_UserRst = 2 +c_cp_trig_WdRst = 4 + +# From diag(pkg).vhd +c_diag_dev_ri = 0 +c_diag_dev_rcux = 1 +c_diag_dev_rcuy = 2 +c_diag_dev_lcu = 3 +c_diag_dev_cep = 4 +c_diag_dev_serdes = 5 + +c_diag_mode_no_tst = 0 +c_diag_mode_loop_local = 1 +c_diag_mode_loop_line = 2 +c_diag_mode_loop_remote = 3 +c_diag_mode_tx = 4 +c_diag_mode_rx = 5 +c_diag_mode_tx_rx = 6 +# RI specific modes +c_diag_mode_bus = c_diag_mode_tx_rx +c_diag_mode_lane_all = 7 +c_diag_mode_lane_single = 8 +# Serdes specific loopback mode variants +c_diag_mode_loop_sys_diag = 9 +c_diag_mode_loop_par_diag = c_diag_mode_loop_local +c_diag_mode_loop_serial = 10 +c_diag_mode_loop_metal_line = c_diag_mode_loop_line +c_diag_mode_loop_par_line = 11 + +c_diag_duration_debug = 0 +c_diag_duration_quick = 1 +c_diag_duration_normal = 2 +c_diag_duration_extra = 3 + +c_diag_res_ok = 0 +c_diag_res_none = 1 +c_diag_res_sync_timeout = 2 +c_diag_res_data_timeout = 3 +c_diag_res_word_err = 4 +c_diag_res_illegal = 5 + +# RCU I2C bus +c_rcuh_i2c_addr_rcu = 1 +c_rcuh_i2c_addr_hba = 2 + +# I2C handler time resolution +c_msec = int(round(200e6 * 1e-3)) + +# HBA control +# +# In the client the registers are stored in order: SPEED, TBM, LED, DUMMY, VREF, STAT. +# - TBM = measured bit time +# - STAT = bit 0 contains the comparator state: 0 is high line input level, 1 for low line input level +# Reading 2 bytes from the SPEED register yields SPEED and TBM. Similar reading 2 bytes from VREF yields +# VREF and STAT. In fact note that reading 6 bytes from SPEED yields them all. +# +# In the server the measured bit time is also stored after YDELAY, so via get word from c_hba_sreg_ydelay +# one gets ydelay and the measured bit time. +c_hba_nof_servers = 16 # HBA nof servers + +c_hba_cmd_request = 0 # HBA client REQUEST register +c_hba_cmd_response = 1 # HBA client RESPONSE register +c_hba_cmd_led = 2 # HBA client LED register +c_hba_cmd_vref = 124 # HBA client VREF register (v10) +c_hba_cmd_speed = 127 # HBA client SPEED register (old) +#c_hba_cmd_speed = 125 # HBA client SPEED register (v10) +c_hba_cmd_version = 126 # HBA client VERSION register +c_hba_reg_request_sz = 38 # register size in octets +c_hba_reg_response_sz = 4 +c_hba_reg_led_sz = 1 +c_hba_reg_vref_sz = 1 +c_hba_reg_speed_sz = 1 +c_hba_reg_version_sz = 1 + +c_hba_f_set_byte = 2 # HBA server function codes +c_hba_f_get_byte = 3 +c_hba_f_set_word = 4 +c_hba_f_get_word = 5 +c_hba_bc_server = 0 # HBA server broadcast address +c_hba_sreg_xdelay = 0 # HBA server xdelay register address +c_hba_sreg_ydelay = 1 # HBA server ydelay register address +c_hba_sreg_version = 254 # HBA server version register address +c_hba_sreg_address = 255 # HBA server address register address + +# - Modem time (modem speed = 40 = 10 kbps, modem prescaler = 1): +# . Broadcast request: 38 msec seems minimum for set_word broadcast 16 servers +# . Unicast request : 11 msec seems minimum for set_word or get word +# - For modem prescaler = 2 the uc_wait = 20 just works at modem speed = 40 = 5.5 kbps, +# hence to be safe double the wait times. +# - Use hba_gap_wait as minimal wait after every I2C access to the client, before issueing a new I2C access +hba_prescaler = 1 +hba_prescaler = 2 +hba_bc_wait = 40*hba_prescaler # used with PROTOCOL_C_WAIT and WG_WAIT +hba_uc_wait = 16*hba_prescaler # used with PROTOCOL_C_WAIT and WG_WAIT +hba_gap_wait = 2 # used with PROTOCOL_C_WAIT and WG_WAIT +hba_bc_i2c = 40 # used with WG_WAIT, I2C signalling time +30 is enough at 200 M +hba_uc_i2c = 25 # used with WG_WAIT, I2C signalling time +20 is enough at 200 M +hba_reg_i2c = 5 # used with WG_WAIT, I2C signalling time +4 is enough at 50 kbps and 327 us comma per byte, + # so addr, cmd, 4 bytes = 6 bytes * 9 = 54 bits @ 50 kbps = 1.1 ms, 6 bytes * 327 us = 1.9 ms + +c_hba_vref_default = 0xEC # Reference default mid level setting +c_hba_speed_default = 40 + +# TDS timing distribution clock board +c_tds_clksel_10MHz_sma = 1 +c_tds_clksel_10MHz_infini = 1 * (not c_tds_clksel_10MHz_sma) +c_tds_clksel_160MHz = 0 +c_tds_clksel_200MHz = 1 * (not c_tds_clksel_160MHz) +c_tds_clksel_pps_sma = 0 +c_tds_clksel_pps_infini = 1 * (not c_tds_clksel_pps_sma) + +################################################################################ +# Other constants (not from constants.tcl) +c_eth_block = 1400 + +c_sens2v5 = 2.5/192 +c_sens3v3 = 3.3/192 +c_sens5v = 5.0/192 +c_sens12v = 12.0/192 + +################################################################################ +# Functions + +def rspctl(tc, arg, applev=22): + cmd = 'rspctl %s' % arg + if tc != None: + tc.appendLog(applev,cmd) # 22: show command line + res = cli.command(cmd) + tc.appendLog(applev+1,res) # 23: show command return + return res + else: + return cli.command(cmd) + + +def i2bb(s): + """ Convert list of integers into list of byte-bytes + Input: + - s = list of integers + Return: + - ret = list of two bytes, LSByte first per pair + """ + ret = [] + for i in s: + ret.extend([i%256, (i/256)%256]) + return ret + + +def i2bbbb(s): + """ Convert list of integers into list of byte-byte-byte-bytes + Input: + - s = list of integers + Return: + - ret = list of four bytes, LSByte first per four + """ + ret = [] + for i in s: + ret.extend([i%256, (i/256)%256, (i/(256*256))%256, (i/(256*256*256))%256]) + return ret + + +def calculate_next_sequence_value(in_word, seq='PRSG', width=12): + """ Calculate next sequence value for PRSG or COUNTER + + Input: + - in_word = seed + - seq = PRSG : use PRSG sequence as in RCU (width=12) + others : use COUNTER sequence + Return: + - out_word = next sequence value after in_word + """ + if seq=='PRSG': + # Polynome + w = 2**width-1 + taps = [0, 3, 5, 11] + + # Feedback shift register + p = 0 + for t in taps: + b = 2**t + b = 1 * (not (not (in_word & b))) + p = p ^ b + out_word = ((in_word << 1) & w) + 1 * (not p) + else: + w = 2**width - 1 + out_word = (in_word + 1) & w + return out_word + + +def reorder(data, index): + """Reorder the data list according to the indices in the index list + + Input: + - data = Input data list + - index = List with reorder indices + Return: + Reordered data list + """ + nof = len(data) + redata = nof * [0] + for i in range(nof): + redata[index[i]] = data[i] + return redata + + +def write_mem(tc, msg, pid, regid, data, blpId=['blp0'], rspId=['rsp0'], width=2, offset=0, bc=1): + """Write data to memory register + + Input: + - tc = Testcase + - msg = MepMessage + - pid = Process ID string + - regid = Register ID string + - data = List of words to write + - blpId = List of ['blp#'] + - rspId = List of ['rsp#'] + - width = Nof bytes per data word + - offset = Offset in nof bytes + - bc = When !=0 use MEP broadcast + Return: void + """ + msg.packAddr(blpId, pid, regid) + msg.packPayload(data,width) + nof = width * len(data) # nof octets + for ri in rspId: + i = 0 + n = c_eth_block + while i < nof: + if nof - i < n: + n = nof - i + hexData = msg.getPayload(i, n) + if bc == 0: + # Individual accesses to BLPs on an RSP board + for bi in blpId: + msg.packAddr([bi], pid, regid) + rspctl(tc, '--writeblock=%s,%s,%d,%s' % (ri[3:], msg.hexAddr, offset+i, hexData)) + else: + # Make use of MEP broadcast to BLPs on an RSP board + rspctl(tc, '--writeblock=%s,%s,%d,%s' % (ri[3:], msg.hexAddr, offset+i, hexData)) + i = i + n + + +def read_mem(tc, msg, pid, regid, nof, blpId=['blp0'], rspId=['rsp0'], sign='+', width=2, offset=0): + """Read data from memory register + + Input: + - tc = Testcase + - msg = MepMessage + - pid = Process ID string + - regid = Register ID string + - nof = Nof bytes to read from the memory + - blpId = List of one ['blp#'] + - rspId = List of one ['rsp#'] + - width = Nof bytes per data word + - sign = 'h' for hex string, '+' for unsigned word list, '-' for signed word list + - offset = Offset in nof bytes + Return: + - list of read words + """ + msg.packAddr(blpId, pid, regid) + msg.clearPayload() + i = 0 + n = c_eth_block + while i < nof: + if nof - i < n: + n = nof - i + msg.extractPayload(rspctl(tc, '--readblock=%s,%s,%d,%d' % (rspId[0][3:], msg.hexAddr, offset+i, n)), True) + i = i + n + if sign == 'h': + return None # use access via msg.hexPayload + else: + return msg.unpackPayload(width, sign) + + +def write_cr_syncoff(tc, msg, blpId=['blp0'], rspId=['rsp0']): + """CR disable external sync + + Input: + - tc = Testcase + - msg = MepMessage + - blpId = List of 'rsp, blp#' + - rspId = List of 'rsp#' + Return: void + """ + for ri in rspId: + msg.packAddr(blpId, 'cr', 'syncoff') + msg.packPayload([1],1) + rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload)) + + +def write_cr_syncon(tc, msg, blpId=['blp0'], rspId=['rsp0']): + """CR enable external sync + + Input: + - tc = Testcase + - msg = MepMessage + - blpId = List of 'rsp, blp#' + - rspId = List of 'rsp#' + Return: void + """ + for ri in rspId: + msg.packAddr(blpId, 'cr', 'syncoff') + msg.packPayload([0],1) + rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload)) + + +def write_cr_sync_delay(tc, msg, syncdelay=0, syncedge=0, blpId=['blp0'], rspId=['rsp0']): + """CR write external sync input delay + + Input: + - tc = Testcase + - msg = MepMessage + - syncdelay = 0 is reset input delay to hardware default, > 0 increment input delay one time + - syncedge = 0 is capture ext_sync on rising edge, != 0 is on falling edge + - blpId = List of 'rsp, blp#' + - rspId = List of 'rsp#' + Return: void + """ + bit0 = syncdelay > 0 + bit1 = syncedge > 0 + syncdata = (bit1 << 1) + bit0 + for ri in rspId: + msg.packAddr(blpId, 'cr', 'syncdelay') + msg.packPayload([syncdata],1) + rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload)) + + +def read_cr_sync_delay(tc, msg, blpId=['blp0'], rspId=['rsp0'], applev=21): + """CR read sync delay bit + + Input: + - tc = Testcase + - msg = MepMessage + - blpId = List of one 'rsp, blp#' + - rspId = List of one 'rsp#' + - applev = Append logging level + Return: + - syncdata = External sync data + . bit 0 : '0' is default input delay, '1' is incremented delay + . bit 1 : '0' capture external sync on rising edge, '1' on falling edge + + tc appendlog messages are reported. + """ + syncdata = -1 + msg.packAddr(blpId, 'cr', 'syncdelay') + readData = rspctl(tc, '--readblock=%s,%s,0,1' % (rspId[0][3:], msg.hexAddr)) + msg.extractPayload(readData) + syncdata = msg.unpackPayload(1, '+') + syncdata = syncdata[0] + bit0 = syncdata & 1 + bit1 = (syncdata & 2) >> 1 + if bit0==0 and bit1==0: + tc.appendLog(applev, '>>> RSP-%s, BLP-%-8s, read CR sync: default input delay, default capture on rising edge' % (rspId, blpId)) + elif bit0==0 and bit1!=0: + tc.appendLog(applev, '>>> RSP-%s, BLP-%-8s, read CR sync: default input delay, capture on falling edge' % (rspId, blpId)) + elif bit0!=0 and bit1==0: + tc.appendLog(applev, '>>> RSP-%s, BLP-%-8s, read CR sync: incremented input delay, default capture on rising edge' % (rspId, blpId)) + else: + tc.appendLog(applev, '>>> RSP-%s, BLP-%-8s, read CR sync: incremented input delay, capture on falling edge' % (rspId, blpId)) + return syncdata + + +def write_diag_bypass(tc, msg, bypass, blpId=['blp0'], rspId=['rsp0'], applev=21): + """Write DIAG bypass register + + Input: + - tc = Testcase + - msg = MepMessage + - bypass = Bypass enable word + - blpId = List of ['blp#'] + - rspId = List of ['rsp#'] + - applev = Append logging level + Return: void + """ + tc.appendLog(applev, '>>> RSP-%s, BLP-%s, write DIAG bypass:' % (rspId, blpId)) + tc.appendLog(applev, ' bit(0) : Bypass DC = %d' % ((bypass & 1 ) > 0)) + tc.appendLog(applev, ' bit(1) : Bypass PFS = %d' % ((bypass & (1<<1)) > 0)) + tc.appendLog(applev, ' bit(2) : Bypass PFT = %d' % ((bypass & (1<<2)) > 0)) + tc.appendLog(applev, ' bit(3) : Bypass BF = %d' % ((bypass & (1<<3)) > 0)) + tc.appendLog(applev, ' bit(4) : SI enable X = %d' % ((bypass & (1<<4)) > 0)) + tc.appendLog(applev, ' bit(5) : SI enable Y = %d' % ((bypass & (1<<5)) > 0)) + tc.appendLog(applev, ' bit(6) : DIAG result buffer use sync = %d' % ((bypass & (1<<6)) > 0)) + tc.appendLog(applev, ' bit(7) : DIAG result buffer use resync = %d' % ((bypass & (1<<7)) > 0)) + tc.appendLog(applev, ' bit(8) : PFT switching disable = %d' % ((bypass & (1<<8)) > 0)) + + for ri in rspId: + msg.packAddr(blpId, 'diag', 'bypass') + msg.packPayload([bypass],2) + rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload)) + + +def read_diag_bypass(tc, msg, blpId=['blp0'], rspId=['rsp0'], applev=21): + """Read DIAG bypass register + + Input: + - tc = Testcase + - msg = MepMessage + - blpId = List of one 'blp#' + - rspId = List of one 'rsp#' + - applev = Append logging level + Return: + - bypass = Bypass bits + """ + msg.packAddr(blpId, 'diag', 'bypass') + readData = rspctl(tc, '--readblock=%s,%s,0,2' % (rspId[0][3:], msg.hexAddr)) + msg.extractPayload(readData) + bypass = msg.unpackPayload(2, '+') + bypass = bypass[0] + + tc.appendLog(applev, '>>> RSP-%s, BLP-%s, read DIAG bypass:' % (rspId, blpId)) + tc.appendLog(applev, ' bit(0) : Bypass DC = %d' % ((bypass & 1 ) > 0)) + tc.appendLog(applev, ' bit(1) : Bypass PFS = %d' % ((bypass & (1<<1)) > 0)) + tc.appendLog(applev, ' bit(2) : Bypass PFT = %d' % ((bypass & (1<<2)) > 0)) + tc.appendLog(applev, ' bit(3) : Bypass BF = %d' % ((bypass & (1<<3)) > 0)) + tc.appendLog(applev, ' bit(4) : SI enable X = %d' % ((bypass & (1<<4)) > 0)) + tc.appendLog(applev, ' bit(5) : SI enable Y = %d' % ((bypass & (1<<5)) > 0)) + tc.appendLog(applev, ' bit(6) : DIAG result buffer use sync = %d' % ((bypass & (1<<6)) > 0)) + tc.appendLog(applev, ' bit(7) : DIAG result buffer use resync = %d' % ((bypass & (1<<7)) > 0)) + tc.appendLog(applev, ' bit(8) : PFT switching disable = %d' % ((bypass & (1<<8)) > 0)) + return bypass + + +def write_diag_selftest(tc, msg, selftest, blpId=['rsp'], rspId=['rsp0'], applev=21): + """Write DIAG selftest register + + Input: + - tc = Testcase + - msg = MepMessage + - selftest = Selftest list: [interface, mode, duration, line] + - blpId = List of ['rsp', 'blp#'] + - rspId = List of ['rsp#'] + - applev = Append logging level + Return: void + """ + tc.appendLog(applev, '>>> RSP-%s write DIAG selftest:' % rspId) + tc.appendLog(applev, ' interface = %d' % selftest[0]) + tc.appendLog(applev, ' mode = %d' % selftest[1]) + tc.appendLog(applev, ' duration = %d' % selftest[2]) + tc.appendLog(applev, ' line = %d' % selftest[3]) + + for ri in rspId: + msg.packAddr(blpId, 'diag', 'selftest') + msg.packPayload(selftest,1) + rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload)) + + +def read_diag_result_buffer(tc, msg, nof, width, blpId=['blp0'], rspId=['rsp0']): + """Read DIAG result buffer + + Input: + - tc = Testcase + - msg = MepMessage + - nof = Nof words to read from the result buffer + - width = Word width of the result buffer samples, 1, 2, or 4 + - blpId = List of one 'blp#' + - rspId = List of one 'rsp#' + Return: + - Read result buffer words + """ + return read_mem(tc, msg, 'diag', 'result', width*nof, blpId, rspId, '-', width) + + +def write_rsu_altsync(tc, msg, rspId=['rsp0']): + """RSU apply altsync + + Input: + - tc = Testcase + - msg = MepMessage + - rspId = List of 'rsp#' + Return: void + """ + for ri in rspId: + msg.packAddr(['rsp'], 'rsu', 'sysctrl') + msg.packPayload([1],1) + rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload)) + + +def write_rd_smbh_protocol_list(tc, msg, smbh, protocol_list, polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0']): + """Write and readback protocol list to SMBus handler in RSP. The list will take effect at next sync. + + Input: + - tc = Testcase + - msg = MepMessage + - smbh = SMBus handler: 'tdsh' or 'rcuh' + - protocol_list = Protocol list + - polId = Polarization ID: x, y or 'x y' for RCUH, ignored for TDSH + - blpId = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH + - rspId = RSP ID: 'rsp#' + Report: + tc.appendlog messages are reported. + tc.setResult is set + Return: void + """ + # - Write the protocol list to the SMBH + smbus.write_protocol_list(tc, msg, smbh, protocol_list, polId, blpId, rspId) + + # - Read back the protocol list to verify that this is possible + for ri in rspId: + if smbh == 'tdsh': + rb_protocol_list = smbus.readback_protocol_list(tc, msg, smbh, len(protocol_list), None, None, [ri]) + if protocol_list == rb_protocol_list: + tc.appendLog(21, '>>> RSP-%s, TDSH : The protocol list READBACK went OK' % ri) + else: + tc.appendLog(11, '>>> RSP-%s, TDSH : The protocol list READBACK went wrong:' % ri) + tc.appendLog(11, 'Expected protocol list: %s' % protocol_list) + tc.appendLog(11, 'Readback protocol list: %s' % rb_protocol_list) + tc.setResult('FAILED') + elif smbh == 'rcuh': + for bi in blpId: + for pi in polId: + rb_protocol_list = smbus.readback_protocol_list(tc, msg, smbh, len(protocol_list), pi, [bi], [ri]) + if protocol_list == rb_protocol_list: + tc.appendLog(21, '>>> RSP-%s, BLP-%s, RCUH-%s: The protocol list READBACK went OK' % (ri, bi, pi)) + else: + tc.appendLog(11, '>>> RSP-%s, BLP-%s, RCUH-%s: The protocol list READBACK went wrong:' % (ri, bi, pi)) + tc.appendLog(11, 'Expected protocol list: %s' % protocol_list) + tc.appendLog(11, 'Readback protocol list: %s' % rb_protocol_list) + tc.setResult('FAILED') + + +def overwrite_rd_smbh_protocol_results(tc, msg, smbh, polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0']): + """Overwrite and read protocol result of SMBus handler in RSP. + + Input: + - tc = Testcase + - msg = MepMessage + - smbh = SMBus handler: 'tdsh' or 'rcuh' + - polId = Polarization ID: x, y or 'x y' for RCUH, ignored for TDSH + - blpId = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH + - rspId = RSP ID: 'rsp#' + Report: + tc appendlog messages are reported. + tc setResult is set + Return: void + """ + if smbh == 'rcuh': + nof_result_bytes = 2**c_rcuh_result_adr_w + if smbh == 'tdsh': + nof_result_bytes = 2**c_tdsh_result_adr_w + + # - Overwrite first entries of protocol result register to be sure that the results will be fresh + wr_result = [] + for i in range(nof_result_bytes): + wr_result.append(17) # Just some number not equal to 0, 1, 255 and < 256 + + # - Overwrite + smbus.overwrite_results(tc, msg, smbh, wr_result, polId, blpId, rspId) + + # - Readback to verify overwrite + for ri in rspId: + if smbh == 'tdsh': + rd_result = smbus.read_results(tc, msg, smbh, nof_result_bytes, None, None, [ri]) + if wr_result == rd_result: + tc.appendLog(21, '>>> RSP-%s, TDSH : The protocol results OVERWRITE and read went OK' % ri) + else: + tc.appendLog(11, '>>> RSP-%s, TDSH : The protocol results OVERWRITE and read went wrong:' % ri) + tc.appendLog(11, 'Expected protocol result: %s' % wr_result) + tc.appendLog(11, 'Readback protocol result: %s' % rd_result) + tc.setResult('FAILED') + elif smbh == 'rcuh': + for bi in blpId: + for pi in polId: + rd_result = smbus.read_results(tc, msg, smbh, nof_result_bytes, pi, [bi], [ri]) + if wr_result == rd_result: + tc.appendLog(21, '>>> RSP-%s, BLP-%s, RCUH-%s: The protocol results OVERWRITE and read went OK' % (ri, bi, pi)) + else: + tc.appendLog(11, '>>> RSP-%s, BLP-%s, RCUH-%s: The protocol results OVERWRITE and read went wrong:' % (ri, bi, pi)) + tc.appendLog(11, 'Expected protocol result: %s' % wr_result) + tc.appendLog(11, 'Readback protocol result: %s' % rd_result) + tc.setResult('FAILED') + + +def overwrite_rsr(tc, msg, procid='all', value=255, rspId=['rsp0']): + """Overwrite the selected process fields of the RSP status register + + Input: + - tc = Testcase + - msg = MepMessage + - procid = Process ID : 'rsp', 'eth', 'mep', 'diag', 'bs', 'rcuh', 'rsu', 'ado', 'rad' or 'all' + - value = Byte value to use for overwrite + - rspId = List of 'rsp#' + Return: void + """ + if procid == 'rsp' : offset = c_ei_status_rsp_offset; size = c_ei_status_rsp_size + elif procid == 'eth' : offset = c_ei_status_eth_offset; size = c_ei_status_eth_size + elif procid == 'mep' : offset = c_ei_status_mep_offset; size = c_ei_status_mep_size + elif procid == 'diag': offset = c_ei_status_diag_offset; size = c_ei_status_diag_size + elif procid == 'bs' : offset = c_ei_status_bs_offset; size = c_nof_blp *c_ei_status_bs_size + elif procid == 'rcuh': offset = c_ei_status_rcuh_offset; size = c_nof_blp *c_ei_status_rcuh_size + elif procid == 'rsu' : offset = c_ei_status_rsu_offset; size = c_ei_status_rsu_size + elif procid == 'ado' : offset = c_ei_status_ado_offset; size = c_nof_blp *c_ei_status_ado_size + elif procid == 'rad' : offset = c_ei_status_rad_offset; size = c_rad_nof_rx *c_ei_status_rad_size + else: offset = c_ei_status_rsr_offset; size = c_ei_status_rsr_size + + status = [] + for i in range(size): + status.append(value) + + for ri in rspId: + write_mem(tc, msg, 'rsr', 'status', status, ['rsp'], [ri], 1, offset) + + +def read_rsr(tc, msg, procid='all', rspId=['rsp0'], applev=21): + """Read the selected process fields from the RSP status register + + Input: + - tc = Testcase + - msg = MepMessage + - procid = Process ID : 'rsp', 'eth', 'mep', 'diag', 'bs', 'rcuh', 'rsu', 'ado', 'rad' or 'all' + - rspId = List of 'rsp#' + - applev = Append log level + Return: + - ret = List of read process status fields, list structure: [[first RSP], ..., [last RSP]], + where the data structure per RSP depends on the procid. + - retb = Boolean telling wither the status is OK or ERROR + """ + ret_rsp = [] # Declare return result + + # Read all RSR fields + for ri in rspId: + ret = [] + retb = [] + + read_mem(tc, msg, 'rsr', 'status', c_ei_status_rsr_size, ['rsp'], [ri], 'h', 1, c_ei_status_rsr_offset) + + msg.setOffset(c_ei_status_rsr_offset) + # RSP status + rsp_volt_1v2 = msg.readUnsigned(1) + rsp_volt_2v5 = msg.readUnsigned(1) + rsp_volt_3v3 = msg.readUnsigned(1) + rsp_pcb_temp = msg.readSigned(1) + rsp_bp_temp = msg.readSigned(1) + rsp_ap0_temp = msg.readSigned(1) + rsp_ap1_temp = msg.readSigned(1) + rsp_ap2_temp = msg.readSigned(1) + rsp_ap3_temp = msg.readSigned(1) + rsp_clk = msg.readUnsigned(1) + rsp_rsvd = msg.readUnsigned(2) + # ETH status + eth_nof_frames = msg.readUnsigned(4) + eth_nof_errors = msg.readUnsigned(4) + eth_last_error = msg.readUnsigned(1) + eth_rsvd = msg.readUnsigned(3) + # MEP status + mep_seq_nr = msg.readUnsigned(2) + mep_prev_error = msg.readUnsigned(1) + mep_rsvd = msg.readUnsigned(1) + # DIAG status + diag_interface = msg.readUnsigned(1) + diag_mode = msg.readUnsigned(1) + diag_ri_errors = {} + diag_ri_errors['rsp'] = msg.readUnsigned(2) + diag_rcux_errors = msg.readUnsigned(2) + diag_rcuy_errors = msg.readUnsigned(2) + diag_eth_errors = {} + diag_eth_errors['LCU'] = msg.readUnsigned(2) + diag_eth_errors['CEP'] = msg.readUnsigned(2) + diag_serdes_errors = msg.readUnsigned(2) + diag_ri_errors['0'] = msg.readUnsigned(2) + diag_ri_errors['1'] = msg.readUnsigned(2) + diag_ri_errors['2'] = msg.readUnsigned(2) + diag_ri_errors['3'] = msg.readUnsigned(2) + diag_rsvd = msg.readUnsigned(2) + # BS status + bs_ext_cnt = {} + bs_sync_cnt = {} + bs_sample_cnt = {} + bs_slice_cnt = {} + for bi in range(c_nof_blp): + bs_ext_cnt[bi] = msg.readUnsigned(4) + bs_sync_cnt[bi] = msg.readUnsigned(4) + bs_sample_cnt[bi] = msg.readUnsigned(4) + bs_slice_cnt[bi] = msg.readUnsigned(4) + # RCU status + rcu_status = {} + rcu_nof_ovr_x = {} + rcu_nof_ovr_y = {} + for bi in range(c_nof_blp): + rcu_status[bi] = msg.readUnsigned(4) + rcu_nof_ovr_x[bi] = msg.readUnsigned(4) + rcu_nof_ovr_y[bi] = msg.readUnsigned(4) + # RSU status + rsu_cp_status = msg.readUnsigned(4) + # ADO status + ado_x = {} + ado_y = {} + for bi in range(c_nof_blp): + ado_x[bi] = msg.readSigned(4) + ado_y[bi] = msg.readSigned(4) + # RAD BP status + rad_ri = msg.readUnsigned(4) + rad_lane = {} + for la in range(c_nof_lanes): + rad_lane[la,'crosslets'] = msg.readUnsigned(4) + rad_lane[la,'beamlets'] = msg.readUnsigned(4) + + # Report RSR fields indicated by procid + tc.appendLog(applev, '') + tc.appendLog(applev, '>>> RSR read outs for RSP-%s.' % ri) + tc.appendLog(applev, '') + + if procid == 'rsp' or procid == 'all': + tc.appendLog(applev, 'RSP board status:') + tc.appendLog(applev, '') + tc.appendLog(applev, ' supply 1.2V = %6.3f V (= %3d * %5.3f)' % (rsp_volt_1v2 * c_sens2v5, rsp_volt_1v2, c_sens2v5)) + tc.appendLog(applev, ' supply 2.5V = %6.3f V (= %3d * %5.3f)' % (rsp_volt_2v5 * c_sens3v3, rsp_volt_2v5, c_sens3v3)) + tc.appendLog(applev, ' supply 3.3V = %6.3f V (= %3d * %5.3f)' % (rsp_volt_3v3 * c_sens5v, rsp_volt_3v3, c_sens5v)) + tc.appendLog(applev, '') + tc.appendLog(applev, ' temp PCB = %4d degrees C' % rsp_pcb_temp) + tc.appendLog(applev, '') + tc.appendLog(applev, ' temp BP = %4d degrees C' % rsp_bp_temp) + tc.appendLog(applev, ' temp AP0 = %4d degrees C' % rsp_ap0_temp) + tc.appendLog(applev, ' temp AP1 = %4d degrees C' % rsp_ap1_temp) + tc.appendLog(applev, ' temp AP2 = %4d degrees C' % rsp_ap2_temp) + tc.appendLog(applev, ' temp AP3 = %4d degrees C' % rsp_ap3_temp) + tc.appendLog(applev, '') + tc.appendLog(applev, ' clk rate = %4d MHz' % rsp_clk) + tc.appendLog(applev, '') + ret.append([rsp_volt_1v2, rsp_volt_2v5, rsp_volt_3v3, rsp_pcb_temp, rsp_bp_temp, rsp_ap0_temp, rsp_ap1_temp, rsp_ap2_temp, rsp_ap3_temp, rsp_clk]) + + if procid == 'eth' or procid == 'all': + tc.appendLog(applev, 'Ethernet status:') + tc.appendLog(applev, '') + tc.appendLog(applev, ' Number of frames = %d' % eth_nof_frames) + tc.appendLog(applev, ' Number of errors = %d' % eth_nof_errors) + if eth_last_error == c_ei_eth_err_noerr : tc.appendLog(applev, ' Last error = OK') + elif eth_last_error == c_ei_eth_err_preamblevalue : tc.appendLog(applev, ' Last error = Preamble value error') + elif eth_last_error == c_ei_eth_err_framedelimiter : tc.appendLog(applev, ' Last error = Frame delimiter error') + elif eth_last_error == c_ei_eth_err_preamblelength : tc.appendLog(applev, ' Last error = Preamble length error') + elif eth_last_error == c_ei_eth_err_headerlength : tc.appendLog(applev, ' Last error = Frame header lenght error') + elif eth_last_error == c_ei_eth_err_crc : tc.appendLog(applev, ' Last error = CRC error') + elif eth_last_error == c_ei_eth_err_oddnibblelength: tc.appendLog(applev, ' Last error = Odd nof nibbles error') + elif eth_last_error == c_ei_eth_err_framelength : tc.appendLog(applev, ' Last error = Frame size error') + else: tc.appendLog(applev, ' Last error = Illegal error code: %d' % eth_last_error) + tc.appendLog(applev, '') + ret.append([eth_nof_frames, eth_nof_errors, eth_last_error]) + if procid == 'mep' or procid == 'all': + tc.appendLog(applev, 'MEP status:') + tc.appendLog(applev, '') + tc.appendLog(applev, ' Sequence number = %d' % mep_seq_nr) + if mep_prev_error == c_ei_mep_err_noerr : tc.appendLog(applev, ' Error status previous msg = OK') + elif mep_prev_error == c_ei_mep_err_type : tc.appendLog(applev, ' Error status previous msg = Unknown message type') + elif mep_prev_error == c_ei_mep_err_addr_blp: tc.appendLog(applev, ' Error status previous msg = Illegal BLP address') + elif mep_prev_error == c_ei_mep_err_pid : tc.appendLog(applev, ' Error status previous msg = Invalid PID') + elif mep_prev_error == c_ei_mep_err_regid : tc.appendLog(applev, ' Error status previous msg = Register does not exist') + elif mep_prev_error == c_ei_mep_err_offset : tc.appendLog(applev, ' Error status previous msg = Offset too large') + elif mep_prev_error == c_ei_mep_err_size : tc.appendLog(applev, ' Error status previous msg = Message too large') + elif mep_prev_error == c_ei_mep_err_ringcrc : tc.appendLog(applev, ' Error status previous msg = Ring CRC error') + elif mep_prev_error == c_ei_mep_err_timeout : tc.appendLog(applev, ' Error status previous msg = Timeout') + else: tc.appendLog(applev, ' Error status previous msg = Illegal error code: %d' % mep_prev_error) + tc.appendLog(applev, '') + ret.append([mep_seq_nr, mep_prev_error]) + if procid == 'diag' or procid == 'all': + tc.appendLog(applev, 'DIAG status:') + tc.appendLog(applev, '') + tc.appendLog(applev, ' Interface = %d' % diag_interface) + tc.appendLog(applev, ' Mode = %d' % diag_mode) + # - BP RI + if diag_ri_errors['rsp'] == c_diag_res_ok: + tc.appendLog(applev, ' Test result RI-BP = OK') + elif diag_ri_errors['rsp'] == c_diag_res_none: + tc.appendLog(applev, ' Test result RI-BP = Nothing happened') + elif diag_ri_errors['rsp'] == c_diag_res_sync_timeout: + tc.appendLog(applev, ' Test result RI-BP = Sync timeout') + elif diag_ri_errors['rsp'] == c_diag_res_data_timeout: + tc.appendLog(applev, ' Test result RI-BP = Data timeout') + elif diag_ri_errors['rsp'] == c_diag_res_word_err: + tc.appendLog(applev, ' Test result RI-BP = Data errors occured') + else: + tc.appendLog(applev, ' Test result RI-BP = Unknown status %d' % diag_ri_errors['rsp']) + tc.appendLog(applev, ' Test result RCU-X = %d' % diag_rcux_errors) + tc.appendLog(applev, ' Test result RCU-Y = %d' % diag_rcuy_errors) + # - ETH + eth_interfaces = ['LCU', 'CEP'] + for ei in eth_interfaces: + if diag_eth_errors[ei] == c_diag_res_ok: + tc.appendLog(applev, ' Test result %s = OK' % ei) + elif diag_eth_errors[ei] == c_diag_res_none: + tc.appendLog(applev, ' Test result %s = Nothing happened' % ei) + elif diag_eth_errors[ei] == c_diag_res_data_timeout: + tc.appendLog(applev, ' Test result %s = Data timeout (= frame lost)' % ei) + elif diag_eth_errors[ei] == c_diag_res_word_err: + tc.appendLog(applev, ' Test result %s = Word errors occured' % ei) + else: + tc.appendLog(applev, ' Test result %s = Unknown status %d' % (ei, diag_eth_errors[ei])) + # - SERDES lanes + lane_mask = 2**c_nof_lanes-1 + lane_ref = 2**c_nof_lanes + for i in range(c_nof_lanes): + lane_errors = (diag_serdes_errors >> (i*c_nof_lanes)) & lane_mask + if lane_errors == c_diag_res_ok: + tc.appendLog(applev, ' Test result SERDES lane %d = OK' % i) + elif lane_errors == c_diag_res_none: + tc.appendLog(applev, ' Test result SERDES lane %d = nothing happened' % i) + elif lane_errors == c_diag_res_sync_timeout: + tc.appendLog(applev, ' Test result SERDES lane %d = sync timeout' % i) + elif lane_errors == c_diag_res_data_timeout: + tc.appendLog(applev, ' Test result SERDES lane %d = data timeout' % i) + elif lane_errors == c_diag_res_word_err: + tc.appendLog(applev, ' Test result SERDES lane %d = word errors occured' % i) + elif lane_errors == c_diag_res_illegal: + tc.appendLog(applev, ' Test result SERDES lane %d = illegal status %d' % (i, lane_errors)) + else: + tc.appendLog(applev, ' Test result SERDES lane %d = unknown status %d' % (i, lane_errors)) + # - APs RI + for ai in ['0','1','2','3']: + if diag_ri_errors[ai] == c_diag_res_ok: + tc.appendLog(applev, ' Test result RI-AP%s = OK' % ai) + elif diag_ri_errors[ai] == c_diag_res_none: + tc.appendLog(applev, ' Test result RI-AP%s = Nothing happened.' % ai) + elif diag_ri_errors[ai] == c_diag_res_sync_timeout: + tc.appendLog(applev, ' Test result RI-AP%s = Sync timeout.' % ai) + elif diag_ri_errors[ai] == c_diag_res_data_timeout: + tc.appendLog(applev, ' Test result RI-AP%s = Data timeout.' % ai) + elif diag_ri_errors[ai] == c_diag_res_word_err: + tc.appendLog(applev, ' Test result RI-AP%s = Data errors occured.' % ai) + else: + tc.appendLog(applev, ' Test result RI-AP%s = Unknown status %d.' % (ai, diag_ri_errors[ai])) + tc.appendLog(applev, '') + ret.append([diag_interface, diag_mode, diag_ri_errors['rsp'], diag_rcux_errors, diag_rcuy_errors, diag_eth_errors['LCU'], diag_eth_errors['CEP'], diag_serdes_errors, diag_ri_errors['0'], diag_ri_errors['1'], diag_ri_errors['2'], diag_ri_errors['3']]) + if procid == 'bs' or procid == 'all': + tc.appendLog(applev, 'BS status:') + tc.appendLog(applev, '') + for bi in range(c_nof_blp): + st = 'BLP-%s: ' % bi + st += 'Ext_cnt = %u, ' % bs_ext_cnt[bi] + st += 'Sync_cnt = %u, ' % bs_sync_cnt[bi] + st += 'Sample_cnt = %u, ' % bs_sample_cnt[bi] + st += 'Slice_cnt = %u.' % bs_slice_cnt[bi] + tc.appendLog(applev, ' %s' % st) + ret.append([bs_ext_cnt[bi], bs_sync_cnt[bi], bs_sample_cnt[bi], bs_slice_cnt[bi]]) + tc.appendLog(applev, '') + if procid == 'rcuh' or procid == 'all': + tc.appendLog(applev, 'RCU status:') + tc.appendLog(applev, '') + for bi in range(c_nof_blp): + st = 'BLP-%s: ' % bi + st += 'status = %u, ' % rcu_status[bi] + st += 'nof_ovr_x = %u, ' % rcu_nof_ovr_x[bi] + st += 'nof_ovr_y = %u.' % rcu_nof_ovr_y[bi] + tc.appendLog(applev, ' %s' % st) + ret.append([rcu_status[bi], rcu_nof_ovr_x[bi], rcu_nof_ovr_y[bi]]) + tc.appendLog(applev, '') + if procid == 'rsu' or procid == 'all': + tc.appendLog(applev, 'RSU status:') + tc.appendLog(applev, '') + tc.appendLog(applev, ' CP status = %d' % rsu_cp_status) + tc.appendLog(applev, '') + if ((rsu_cp_status >> c_cp_statusRdy) & 0x1) == 1: + tc.appendLog(applev, ' [%d] statusRdy = 1 : CP is done' % c_cp_statusRdy) + else: + tc.appendLog(applev, ' [%d] statusRdy = 0 : CP is in some intermediate state' % c_cp_statusRdy) + if ((rsu_cp_status >> c_cp_statusFpgaType) & 0x1) == c_cp_bp: + tc.appendLog(applev, ' [%d] statusFpgaType = %d : Image was loaded via JTAG' % (c_cp_statusFpgaType, c_cp_bp)) + else: + tc.appendLog(applev, ' [%d] statusFpgaType = %d : Image was loaded from flash' % (c_cp_statusFpgaType, 1 * (not c_cp_bp))) + if ((rsu_cp_status >> c_cp_statusImageType) & 0x1) == 0: + tc.appendLog(applev, ' [%d] statusImageType = 0 : Factory image is running' % c_cp_statusImageType) + else: + tc.appendLog(applev, ' [%d] statusImageType = 1 : User image is running' % c_cp_statusImageType) + if ((rsu_cp_status >> c_cp_statusTrigLo) & c_cp_trig_mask) == c_cp_trig_ButtonRst: + tc.appendLog(applev, ' [%d:%d] statusTrig = %d : Reconfiguration due to button reset' % (c_cp_statusTrigHi, c_cp_statusTrigLo, c_cp_trig_ButtonRst)) + elif ((rsu_cp_status >> c_cp_statusTrigLo) & c_cp_trig_mask) == c_cp_trig_TempRst: + tc.appendLog(applev, ' [%d:%d] statusTrig = %d : Reconfiguration due to over temperature' % (c_cp_statusTrigHi, c_cp_statusTrigLo, c_cp_trig_TempRst)) + elif ((rsu_cp_status >> c_cp_statusTrigLo) & c_cp_trig_mask) == c_cp_trig_UserRst: + tc.appendLog(applev, ' [%d:%d] statusTrig = %d : Reconfiguration due to user reset' % (c_cp_statusTrigHi, c_cp_statusTrigLo, c_cp_trig_UserRst)) + elif ((rsu_cp_status >> c_cp_statusTrigLo) & c_cp_trig_mask) == c_cp_trig_WdRst: + tc.appendLog(applev, ' [%d:%d] statusTrig = %d : Reconfiguration due to watchdog reset' % (c_cp_statusTrigHi, c_cp_statusTrigLo, c_cp_trig_WdRst)) + else: + tc.appendLog(applev, ' [%d:%d] statusTrig = %d : Unknown reconfiguration trigger' % (c_cp_statusTrigHi, c_cp_statusTrigLo, (rsu_cp_status >> c_cp_statusTrigLo) & c_cp_trig_mask)) + cp_version = (((rsu_cp_status >> c_cp_statusVersion1) & 0x1) << 1) + ((rsu_cp_status >> c_cp_statusVersion0) & 0x1) + tc.appendLog(applev, ' [%d,%d] statusVersion = %d : CP version number' % (c_cp_statusVersion1, c_cp_statusVersion0, cp_version)) + tc.appendLog(applev, '') + ret.append([rsu_cp_status]) + elif procid == 'ado' or procid == 'all': + tc.appendLog(applev, 'ADC offset:') + tc.appendLog(applev, '') + for bi in range(c_nof_blp): + nof_samples_psync = bs_slice_cnt[bi] * c_slice_size + st = 'BLP-%s, RCU-X ADC offset = ' % bi + if nof_samples_psync != 0: + st += '%11.7f lsb ' % (1.0 * ado_x[bi] * c_ado_scale / nof_samples_psync) + else: + st += '-----------' + st += '(%10d * %u / %11.0f)' % (ado_x[bi], c_ado_scale, nof_samples_psync) + tc.appendLog(applev, ' %s' % st) + + st = 'BLP-%s, RCU-Y ADC offset = ' % bi + if nof_samples_psync != 0: + st += '%11.7f lsb ' % (1.0 * ado_y[bi] * c_ado_scale / nof_samples_psync) + else: + st += '-----------' + st += '(%10d * %u / %11.0f)' % (ado_y[bi], c_ado_scale, nof_samples_psync) + tc.appendLog(applev, ' %s' % st) + + ret.append([ado_x[bi], ado_y[bi]]) + tc.appendLog(applev, '') + if procid == 'rad' or procid == 'all': + tc.appendLog(applev, 'RAD BP frame rx status:') + tc.appendLog(applev, '') + tc.appendLog(applev, ' Align Sync CRC Frame cnt') + retb = c_rsr_undefined # default undefined + st = 'RI : ' + cnt = rad_ri & ((1<<18)-1) + if cnt==0: + st += '- - - ' + else: + # when rad is busy there is always input from RI, from lane only in case of multiple RSP + retb = c_rsr_ok + st += '- ' # not applicable for RI + if (rad_ri & (1<<19))!=0: st += 'OK ' + else: st += 'Error '; retb = c_rsr_error # sync error(s) + if (rad_ri & (1<<18))==0: st += 'OK ' + else: st += 'Error '; retb = c_rsr_error # CRC error(s) + st += '%u' % cnt + tc.appendLog(applev, ' %s' % st) + ret.append(rad_ri) + for la in range(c_nof_lanes): + for let in ['crosslets', 'beamlets']: + st = 'Lane-%d, %-9s: ' % (la, let) + cnt = rad_lane[la, let] & ((1<<18)-1) + if cnt==0: + st += '- - - ' + else: + # input from lane can keep retb as set by input from RI, or cause retb to indicate error + if (rad_lane[la, let] & (1<<20))==0: st += 'OK ' + else: st += 'Error '; retb = c_rsr_error # frame(s) discarded + if (rad_lane[la, let] & (1<<19))!=0: st += 'OK ' + else: st += 'Error '; retb = c_rsr_error # sync error(s) + if (rad_lane[la, let] & (1<<18))==0: st += 'OK ' + else: st += 'Error '; retb = c_rsr_error # CRC error(s) + st += '%u' % cnt + tc.appendLog(applev, ' %s' % st) + ret.append(rad_lane[la, let]) + tc.appendLog(applev, '') + ret = [retb, ret] + ret_rsp.append(ret) + return ret_rsp + + +def write_rad_settings(tc, msg, settings, rspId=['rsp0'], applev=21): + """RAD_BP write settings + + Input: + - tc = Testcase + - msg = MepMessage + - settings = Lane settings for beamlets and crosslets + - rspId = List of 'rsp#' + - applev = Append log level + Report: + tc appendlog messages are reported (see read_rad_settings for lane mode definition). + Return: void + """ + tc.appendLog(applev, '>>> RSP-%s write RAD settings (= 0x%X):' % (rspId, settings)) + # beamlet lane modes + for i in range(c_nof_lanes): + lane_mode = (settings >> (8*i)) & 0x3 + if lane_mode==0: tc.appendLog(applev, ' lane(%d): beamlet mode local' % i) + elif lane_mode==1: tc.appendLog(applev, ' lane(%d): beamlet mode disable' % i) + elif lane_mode==2: tc.appendLog(applev, ' lane(%d): beamlet mode combine' % i) + else: tc.appendLog(applev, ' lane(%d): beamlet mode remote' % i) + # crosslet lane modes + for i in range(c_nof_lanes): + lane_mode = (settings >> (8*i + 2)) & 0x3 + if lane_mode==0: tc.appendLog(applev, ' lane(%d): crosslet mode local' % i) + elif lane_mode==1: tc.appendLog(applev, ' lane(%d): crosslet mode disable' % i) + elif lane_mode==2: tc.appendLog(applev, ' lane(%d): crosslet mode combine' % i) + else: tc.appendLog(applev, ' lane(%d): crosslet mode remote' % i) + for ri in rspId: + msg.packAddr(['rsp'], 'rad', 'settings') + msg.packPayload([settings],4) + rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload)) + + +def read_rad_settings(tc, msg, rspId=['rsp0'], applev=21): + """RAD_BP read settings + Input: + - tc = Testcase + - msg = MepMessage + - rspId = List of one 'rsp#' + - applev = Append log level + Report: + tc appendlog messages are reported. + Return: + - settings = Lane settings for beamlets and crosslets + lane mode: one byte for each lane + format: XXXXAABB + where XX = don't care + AA = xlet mode + BB = blet mode + mode 00 = ignore remote data (only local) DEFAULT + mode 01 = disable + mode 10 = combine local and remote data + mode 11 = ignore local data (only remote) + """ + msg.packAddr(['rsp'], 'rad', 'settings') + readData = rspctl(tc, '--readblock=%s,%s,0,4' % (rspId[0][3:], msg.hexAddr)) + msg.extractPayload(readData) + settings = msg.unpackPayload(4, '+') + settings = settings[0] + tc.appendLog(applev, '>>> RSP-%s read RAD settings (= 0x%X):' % (rspId, settings)) + # beamlet lane modes + for i in range(c_nof_lanes): + lane_mode = (settings >> (8*i)) & 0x3 + if lane_mode==0: tc.appendLog(applev, ' lane(%d): beamlet mode local' % i) + elif lane_mode==1: tc.appendLog(applev, ' lane(%d): beamlet mode disable' % i) + elif lane_mode==2: tc.appendLog(applev, ' lane(%d): beamlet mode combine' % i) + else: tc.appendLog(applev, ' lane(%d): beamlet mode remote' % i) + # crosslet lane modes + for i in range(c_nof_lanes): + lane_mode = (settings >> (8*i + 2)) & 0x3 + if lane_mode==0: tc.appendLog(applev, ' lane(%d): crosslet mode local' % i) + elif lane_mode==1: tc.appendLog(applev, ' lane(%d): crosslet mode disable' % i) + elif lane_mode==2: tc.appendLog(applev, ' lane(%d): crosslet mode combine' % i) + else: tc.appendLog(applev, ' lane(%d): crosslet mode remote' % i) + return settings + + +def read_rad_latency(tc, msg, rspId=['rsp0'], applev=21): + """RAD_BP read latency + + Input: + - tc = Testcase + - msg = MepMessage + - rspId = List of 'rsp#' + - applev = Append log level + Report: + tc appendlog messages are reported. + Return: + - latency = RI and lane latencies crosslets and beamlets + """ + latency = [] + nof_rd = 2*c_rad_nof_rx + + title_str = '>>> ' + title_str += 'Ri' + for i in range(c_nof_lanes-1,-1,-1): + title_str += ' X%d' % i + for i in range(c_nof_lanes-1,-1,-1): + title_str += ' B%d' % i + tc.appendLog(applev, title_str) + + for ri in rspId: + lat = [] + read_mem(tc, msg, 'rad', 'latency', nof_rd, ['rsp'], [ri], 'h', 1, 0) + + msg.setOffset(0) + lane = {} + for i in range(c_nof_lanes): + lane[i,'b'] = msg.readUnsigned(2) + lane[i,'x'] = msg.readUnsigned(2) + ring = msg.readUnsigned(2) + + lat_str = 'RSP-%s' % ri + lat_str += '%6d' % ring + lat.append(ring) + for i in range(c_nof_lanes-1,-1,-1): + lat_str += '%6d' % lane[i,'x'] + lat.append(lane[i,'x']) + for i in range(c_nof_lanes-1,-1,-1): + lat_str += '%6d' % lane[i,'b'] + lat.append(lane[i,'b']) + tc.appendLog(applev, lat_str) + latency.append(lat) + return latency + + +def write_ss(tc, msg, ss_map, blpId=['blp0'], rspId=['rsp0']): + """Write subband to beamlet mapping to SS register + + Input: + - tc = Testcase + - msg = MepMessage + - ss_map = List of words for subband to beamlet mapping + - blpId = List of 'blp#' + - rspId = List of 'rsp#' + Return: void + """ + write_mem(tc, msg, 'ss', 'settings', ss_map, blpId, rspId, 2) + + +def read_ss(tc, msg, nof, blpId=['blp0'], rspId=['rsp0']): + """Read subband to beamlet mapping from SS register + + Input: + - tc = Testcase + - msg = MepMessage + - nof = Nof words to read from the SS register + - blpId = List of one 'blp#' + - rspId = List of one 'rsp#' + Return: + - Read SS register words + """ + width = 2 + return read_mem(tc, msg, 'ss', 'settings', width*nof, blpId, rspId, '+', width) + + +################################################################################ +# Try some functions on the python command line +if __name__ == "__main__": + import sys + sys.argv[1:] # list of input arguments diff --git a/StationTest/modules/smbus.py b/StationTest/modules/smbus.py new file mode 100644 index 0000000000000000000000000000000000000000..d73e8825f3fd1679290b1257651c545e44cdb6d7 --- /dev/null +++ b/StationTest/modules/smbus.py @@ -0,0 +1,281 @@ +"""SMBus (I2C) access constants and functions (translated from RSP smbus.tcl) + + Constants for I2C peripherals + + - c_max6652 voltage temperature sensor + - c_pca9555 I/O expander + + Procedures for accessing the SMBus (I2C) interface + + - set_protocol + - write_protocol_list + - readback_protocol_list + - read_results + - overwrite_results +""" + +################################################################################ +# System imports + +# User imports +import rsp + +############################################################################### +# - MAX6652 voltage temperature sensor constants + +c_max6652_addr_gnd = 0x14 # I2C slave address +c_max6652_addr_vcc = 0x15 +c_max6652_addr_sda = 0x16 +c_max6652_addr_scl = 0x17 + +c_max6652_cmd_read_2v5 = 0x20 # Commands +c_max6652_cmd_read_12v = 0x21 +c_max6652_cmd_read_3v3 = 0x22 +c_max6652_cmd_read_vcc = 0x23 +c_max6652_cmd_read_temp = 0x27 +c_max6652_cmd_config = 0x40 + +c_max6652_config_start = 0x01 # Configuration bits +c_max6652_config_int_en = 0x02 +c_max6652_config_int_clr = 0x08 +c_max6652_config_line_freq_sel = 0x10 +c_max6652_config_short_cycle = 0x20 +c_max6652_config_reset = 0x80 + +c_max6652_unit_12v = 12.0/192 # Unit in V +c_max6652_unit_vcc = 5.0/192 +c_max6652_unit_3v3 = 3.3/192 +c_max6652_unit_2v5 = 2.5/192 +c_max6652_unit_temp = 1.0 # Unit in degree C + + +############################################################################### +# - PCA9555 I/O expander constants + +c_pca9555_base_addr = 0x20 +c_pca9555_addr_000 = c_pca9555_base_addr + 0 # A2 A1 A0 +c_pca9555_addr_001 = c_pca9555_base_addr + 1 +c_pca9555_addr_010 = c_pca9555_base_addr + 2 +c_pca9555_addr_011 = c_pca9555_base_addr + 3 +c_pca9555_addr_100 = c_pca9555_base_addr + 4 +c_pca9555_addr_101 = c_pca9555_base_addr + 5 +c_pca9555_addr_110 = c_pca9555_base_addr + 6 +c_pca9555_addr_111 = c_pca9555_base_addr + 7 + +c_pca9555_cmd_input_0 = 0 +c_pca9555_cmd_input_1 = 1 +c_pca9555_cmd_output_0 = 2 +c_pca9555_cmd_output_1 = 3 +c_pca9555_cmd_invert_0 = 4 +c_pca9555_cmd_invert_1 = 5 +c_pca9555_cmd_config_0 = 6 +c_pca9555_cmd_config_1 = 7 + + +############################################################################### +# - SMBus functions + +def set_protocol(tc, protocol_id, cnt=1, addr=1, data='', cmd='', cmd2='', appLev=1): + """Returns filled in protocol message + + See i2c_smbus(pkg).vhd for more detailed comments on the SMBus protocol definitions. + + Input: + - tc = Testcase + - protocol_id = Protocol ID: STRING + - cnt = Number of data bytes, or timeout value: INTEGER + - addr = I2C slave address: BYTE + - data = I2C write data: list of BYTE + - cmd = I2C slave command (register) + - cmd2 = I2C slave command (register) 2 + + Return: + - msg = Protocol request message + """ + + def error_len(data, le): + ret = 0 + if len(data)!=le: + print 'Wrong SMBus protocol data length, must be %d bytes.' % le + ret = 1 + return ret + + # SMBUS protocol identifiers conform i2c_smbus(pkg).vhd + PROTOCOL_ARRAY = {'PROTOCOL_WRITE_QUICK' :2, + 'PROTOCOL_READ_QUICK' :3, + 'PROTOCOL_SEND_BYTE' :4, + 'PROTOCOL_RECEIVE_BYTE' :5, + 'PROTOCOL_WRITE_BYTE' :6, + 'PROTOCOL_READ_BYTE' :7, + 'PROTOCOL_WRITE_WORD' :8, + 'PROTOCOL_READ_WORD' :9, + 'PROTOCOL_WRITE_BLOCK' :10, + 'PROTOCOL_READ_BLOCK' :11, + 'PROTOCOL_PROCESS_CALL' :12, + 'PROTOCOL_C_WRITE_BLOCK_NO_CNT' :13, + 'PROTOCOL_C_READ_BLOCK_NO_CNT' :14, + 'PROTOCOL_C_SEND_BLOCK' :15, + 'PROTOCOL_C_RECEIVE_BLOCK' :16, + 'PROTOCOL_C_NOP' :17, + 'PROTOCOL_C_WAIT' :18, + 'PROTOCOL_C_END' :19, + 'PROTOCOL_C_UNKNOWN' :20} # To test unknown protocol + + # First message field + msg = [] + msg.append(PROTOCOL_ARRAY[protocol_id]) + + # Additional message fields: + if protocol_id == 'PROTOCOL_WRITE_QUICK': msg.append(addr) + elif protocol_id == 'PROTOCOL_READ_QUICK': msg.append(addr) + elif protocol_id == 'PROTOCOL_SEND_BYTE': + msg.append(addr) + msg.extend(data) + if error_len(data,1)!=0: msg = -1 + elif protocol_id == 'PROTOCOL_RECEIVE_BYTE': msg.append(addr) + elif protocol_id == 'PROTOCOL_WRITE_BYTE': + msg.append(addr) + msg.append(cmd) + msg.extend(data) + if error_len(data,1)!=0: msg = -1 + elif protocol_id == 'PROTOCOL_READ_BYTE': msg.append(addr); msg.append(cmd) + elif protocol_id == 'PROTOCOL_WRITE_WORD': + msg.append(addr) + msg.append(cmd) + msg.extend(data) + if error_len(data,2)!=0: msg = -1 + elif protocol_id == 'PROTOCOL_READ_WORD': msg.append(addr); msg.append(cmd) + elif protocol_id == 'PROTOCOL_WRITE_BLOCK': msg.append(addr); msg.append(cmd); msg.append(cnt); msg.extend(data) + elif protocol_id == 'PROTOCOL_READ_BLOCK': msg.append(addr); msg.append(cmd); msg.append(cnt) + elif protocol_id == 'PROTOCOL_PROCESS_CALL': + msg.append(addr) + msg.append(cmd) + msg.extend(data) + if error_len(data,2)!=0: msg = -1 + msg.append(addr); msg.append(cmd2) + elif protocol_id == 'PROTOCOL_C_WRITE_BLOCK_NO_CNT': msg.append(addr); msg.append(cmd); msg.append(cnt); msg.extend(data) + elif protocol_id == 'PROTOCOL_C_READ_BLOCK_NO_CNT': msg.append(addr); msg.append(cmd); msg.append(cnt) + elif protocol_id == 'PROTOCOL_C_SEND_BLOCK': msg.append(addr); msg.append(cnt); msg.extend(data) + elif protocol_id == 'PROTOCOL_C_RECEIVE_BLOCK': msg.append(addr); msg.append(cnt) + elif protocol_id == 'PROTOCOL_C_NOP': None + elif protocol_id == 'PROTOCOL_C_WAIT': msg.extend(rsp.i2bbbb([cnt])) + elif protocol_id == 'PROTOCOL_C_END': None + else: tc.appendLog(appLev, 'Unknown SMBus protocol.') + + return msg + + +def test_protocols(tc): + """Procedure used to verify set_protocol in a Python shell + """ + print set_protocol(tc, 'PROTOCOL_WRITE_QUICK', None, 1, None, None, None) + print set_protocol(tc, 'PROTOCOL_READ_QUICK', None, 1, None, None, None) + print set_protocol(tc, 'PROTOCOL_SEND_BYTE', None, 1, [5], None, None) + print set_protocol(tc, 'PROTOCOL_RECEIVE_BYTE', None, 1, None, None, None) + print set_protocol(tc, 'PROTOCOL_WRITE_BYTE', None, 1, [5], 17, None) + print set_protocol(tc, 'PROTOCOL_READ_BYTE', None, 1, None, 17, None) + print set_protocol(tc, 'PROTOCOL_WRITE_WORD', None, 1, [5, 6], 17, None) + print set_protocol(tc, 'PROTOCOL_READ_WORD', None, 1, None, 17, None) + print set_protocol(tc, 'PROTOCOL_WRITE_BLOCK', 3, 1, [9, 9, 9], 17, None) + print set_protocol(tc, 'PROTOCOL_READ_BLOCK', 3, 1, None, 17, None) + print set_protocol(tc, 'PROTOCOL_PROCESS_CALL', None, 1, [5, 6], 17, 18) + print set_protocol(tc, 'PROTOCOL_C_WRITE_BLOCK_NO_CNT', 3, 1, [9, 9, 9], 17, None) + print set_protocol(tc, 'PROTOCOL_C_READ_BLOCK_NO_CNT', 3, 1, None, 17, None) + print set_protocol(tc, 'PROTOCOL_C_SEND_BLOCK', 3, 1, [9, 9, 9], None, None) + print set_protocol(tc, 'PROTOCOL_C_RECEIVE_BLOCK', 3, 1, None, None, None) + print set_protocol(tc, 'PROTOCOL_C_NOP', None, 1, None, None, None) + print set_protocol(tc, 'PROTOCOL_C_WAIT', 1333, 1, None, None, None) + print set_protocol(tc, 'PROTOCOL_C_END', None, 1, None, None, None) + set_protocol( tc, 'PROTOCOL_C_UNKNOWN', None, 1, None, None, None) + + +def write_protocol_list(tc, msg, smbh, protocol_list, polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0']): + """Write SMBus protocol list to SMBus handler + + Input: + - tc = Testcase + - msg = MepMessage + - smbh = I2C device handler: 'rcuh' or 'tdsh' + - protocol_list = Protocol list: bytes + - polId = Polarization: 'x' or 'y' for RCUH, ignored for TDSH + - blpId = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH + - rspId = RSP ID: 'rsp#' + + Return: void + """ + width = 1 # protocol_list is in bytes + offset = 0 # access from address 0 + bc = 1 # allow BLP broadcast + if smbh == 'tdsh': + rsp.write_mem(tc, msg, smbh, 'protocol', protocol_list, ['rsp'], rspId, width, offset, bc) + if smbh == 'rcuh': + for pi in polId: + rsp.write_mem(tc, msg, smbh, 'protocol'+pi, protocol_list, blpId, rspId, width, offset, bc) + + +def readback_protocol_list(tc, msg, smbh, le, polId='x', blpId=['blp0'], rspId=['rsp0']): + """Read back SMBus protocol list from SMBus handler + + Input: + - tc = Testcase + - msg = MepMessage + - smbh = I2C device handler: 'rcuh' or 'tdsh' + - le = Number of bytes to read from the protocol list buffer, INTEGER + - polId = Polarization ID: 'x' or 'y' for RCUH, ignored for TDSH - only one + - blpId = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH - only one + - rspId = RSP ID: 'rsp#' - only one + + Return: Read protocol list bytes + """ + width = 1 # protocol_list is in bytes + offset = 0 # access from address 0 + if smbh == 'tdsh': + return rsp.read_mem(tc, msg, smbh, 'protocol', width * le, ['rsp'], rspId, '+', width, offset) + if smbh == 'rcuh': + return rsp.read_mem(tc, msg, smbh, 'protocol'+polId, width * le, blpId, rspId, '+', width, offset) + + +def read_results (tc, msg, smbh, le, polId='x', blpId=['blp0'], rspId=['rsp0']): + """Read the results of the SMBus protocol list from the SMBus handler + + Input: + - tc = Testcase + - msg = MepMessage + - smbh = I2C device handler: 'rcuh' or 'tdsh' + - le = Number of bytes to read from the protocol result buffer, INTEGER + - polId = Polarization ID: 'x' or 'y' for RCUH, ignored for TDSH - only one + - blpId = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH - only one + - rspId = RSP ID: 'rsp#' - only one + + Return: = Read result data + """ + width = 1 # protocol_list is in bytes + offset = 0 # access from address 0 + if smbh == 'tdsh': + return rsp.read_mem(tc, msg, smbh, 'result', width * le, ['rsp'], rspId, '+', width, offset) + if smbh == 'rcuh': + return rsp.read_mem(tc, msg, smbh, 'result'+polId, width * le, blpId, rspId, '+', width, offset) + + +def overwrite_results (tc, msg, smbh, wr_result, polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0']): + """Write SMBus results to SMBus handler + + Input: + - tc = Testcase + - msg = MepMessage + - smbh = I2C device handler: 'rcuh' or 'tdsh' + - wr_result = Overwrite results: bytes + - polId = Polarization: 'x' or 'y' for RCUH, ignored for TDSH + - blpId = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH + - rspId = RSP ID: 'rsp#' + + Return: void + """ + width = 1 # result is in bytes + offset = 0 # access from address 0 + bc = 1 # allow BLP broadcast + if smbh == 'tdsh': + rsp.write_mem(tc, msg, smbh, 'result', wr_result, ['rsp'], rspId, width, offset, bc) + if smbh == 'rcuh': + for pi in polId: + rsp.write_mem(tc, msg, smbh, 'result'+pi, wr_result, blpId, rspId, width, offset, bc) diff --git a/StationTest/modules/testcase.py b/StationTest/modules/testcase.py new file mode 100644 index 0000000000000000000000000000000000000000..1463e2311627323696f203ef0cd2d2a11a82826a --- /dev/null +++ b/StationTest/modules/testcase.py @@ -0,0 +1,72 @@ +"""Testcase utilities +""" + +################################################################################ +# System imports +import time + +################################################################################ +# Functions + +class Testcase: + + def __init__(self, verbosity=11, testName='empty.py', repeat=1, + rspId=['rsp0'], bpId='rsp', blpId='blp0', + tbbId=None, tpId=None, mpId=None, + polId=['x','y']): + self.startTime = time.time() + self.verbosity = verbosity + self.testName = testName + self.repeat = repeat + self.rspId = rspId + self.bpId = bpId + self.blpId = blpId + self.tbbId = tbbId + self.tpId = tpId + self.mpId = mpId + self.polId = polId + if testName != None: + self.logName = testName[0:-3] + '.log' + self.logFile = open(self.logName,'w') + self.result = 'RUNONLY' + + def setResult(self, res): # Use this method rather than direct access to result + if res in ['RUNONLY', 'PASSED', 'FAILED']: # Ignore illegal res + if self.result != 'FAILED': # Once FAILED the result can not be changed + self.result=res + + def getResult(self): # Method alterative to than direct access to result + return self.result + + def appendLog(self, level, string, nolevel=0, notime=0): + txt = 'Tc %s - ' % self.testName[0:-3] + if notime == 0: + t = time.localtime() + txt = txt + '[%d:%02d:%02d %02d:%02d:%02d]' % (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec) + if nolevel == 0: + txt = txt + ' - (%02d) ' % level + txt = txt + string + + if level <= self.verbosity: + print txt + self.logFile.write(txt + '\n') + + def appendFile(self, level, fileName): + try: + appFile = open(fileName,'r') + self.appendLog(level,appFile.read(),1,1,1) + appFile.close() + except IOError: + self.appendLog(level,'ERROR : Can not open file %s' % fileName) + + def sleep(self, ms): + time.sleep(ms/1000.0) + + def setStartTime(self): + self.startTime = time.time() + + def getRunTime(self): + return int(time.time() - self.startTime) + + def closeLog(self): + self.logFile.close() diff --git a/StationTest/modules/testlog.py b/StationTest/modules/testlog.py new file mode 100644 index 0000000000000000000000000000000000000000..d31e7b62940b28312a4f5885a0dffa21a35711f2 --- /dev/null +++ b/StationTest/modules/testlog.py @@ -0,0 +1,69 @@ +"""Test logging utilities +""" + +################################################################################ +# System imports +import time + +################################################################################ +# Functions + +class Testlog: + + def __init__(self, verbosity=11, testId=None, logName='empty.dat'): + self.startTime = time.time() + self.verbosity = verbosity + self.testId = testId + self.logName = logName + if logName != None: + try: + self.logFile = open(self.logName,'w') + except IOError: + print 'ERROR : Can not open log file %s' % logName + self.result = 'RUNONLY' + + def setId(self, txt): # Use this method rather than direct access to testId + self.testId=txt + + def setResult(self, res): # Use this method rather than direct access to result + if res in ['RUNONLY', 'PASSED', 'FAILED']: # Ignore illegal res + if self.result != 'FAILED': # Once FAILED the result can not be changed + self.result=res + + def getResult(self): # Method alternative for direct access to result + return self.result + + def appendLog(self, level, string, notime=0, nolevel=0, noId=0): + txt = '' + if notime == 0: + t = time.localtime() + txt = txt + '[%d:%02d:%02d %02d:%02d:%02d]' % (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec) + if nolevel == 0: + txt = txt + ' - (%02d) ' % level + if noId == 0: + txt = txt + self.testId + txt = txt + string + + if level <= self.verbosity: + print txt + self.logFile.write(txt + '\n') + + def appendFile(self, level, fileName): + try: + appFile = open(fileName,'r') + self.appendLog(level,appFile.read(),1,1,1) + appFile.close() + except IOError: + self.appendLog(level,'ERROR : Can not open file %s' % fileName) + + def sleep(self, ms): + time.sleep(ms/1000.0) + + def setStartTime(self): + self.startTime = time.time() + + def getRunTime(self): + return int(time.time() - self.startTime) + + def closeLog(self): + self.logFile.close() diff --git a/StationTest/prbs_dir_test.py b/StationTest/prbs_dir_test.py new file mode 100644 index 0000000000000000000000000000000000000000..83709022e5305cb535c1705ade217e77ef51e644 --- /dev/null +++ b/StationTest/prbs_dir_test.py @@ -0,0 +1,114 @@ + +""" script for testing PRBS data in dir. +Gijs, 16 dec 07 +""" +# INIT + +import array +import operator +import os +import time +import commands + +# Open file for processing +def open_dir() : + files = os.listdir('./prbs/.') + files.sort() +# print files + return files + +def open_file(files, file_nr) : + file_name = './prbs/' + files[file_nr][:] + if files[file_nr][-3:] == 'dat': + fileinfo = os.stat(file_name) + size = int(fileinfo.st_size) + f=open(file_name,'rb') + max_frames = size/(88 + 1024*2 + 4) + frames_to_proces=max_frames + else : + frames_to_proces=0 + f=open(file_name,'rb') + return f, frames_to_proces + + +# Read single frame from file +def read_frame(f, info_plot, frame_nr,f_log): + station_info = array.array('B') + station_info.fromfile(f,4) # Bytes 0..3 + time_info = array.array('L') + time_info.fromfile(f,3) # Bytes 4..15 + if (info_plot) : + time_string = time.ctime(time_info[1]) +# string_info = 'Frame nr %(FR)d Station %(ST)d RSP %(RSP)d RCU %(RCU)d Sample rate %(S)d MHz time of data %(ti_D)s and %(SN)00.6f seconds'%\ +# {"FR": frame_nr, "ST": station_info[0] ,"RSP": station_info[1], "RCU": station_info[2], "S": station_info[3], "ti_D": time_string,"SN": float(time_info[2])/float(200000000)} + string_info = 'Frame nr %(FR)d Station %(ST)d RSP %(RSP)d RCU %(RCU)d Sample rate %(S)d MHz'%\ + {"FR": frame_nr, "ST": station_info[0] ,"RSP": station_info[1], "RCU": station_info[2], "S": station_info[3]} +# print string_info + f_log.write(string_info + '\n') + div_info = array.array('H') + div_info.fromfile(f,36) # Bytes 16..87 + + # READ DATA SAMPLES + data_in = array.array('H') + samples = int(div_info[0]) + data_in.fromfile(f,samples) + data_list = data_in.tolist() + + data_crc = array.array('l') + data_crc.fromfile(f,1) + return data_list, time_info[1], time_info[2] + + +# Function for testing PRBS data +def PRBS_CHECK(data_list, prev): + samples_chk=0 + prbs_err=0 + for i in range(0,len(data_list)) : + if prev == 0x0FFF : + prev = data_list[i] & 0x07FF + elif data_list[i] == 0xFFFF : + prbs_err = prbs_err + 1 + else : + cur = data_list[i] & 0x0FFE + samples_chk = samples_chk + 1 + if cur != 2*prev : + prbs_err = prbs_err + 1 +# print(str(i) + ' ' + hex(2*prev) + ' ' + hex(cur)) + prev = data_list[i] & 0x07FF + return samples_chk, prbs_err, prev + + +# Main loop +def main() : + files = open_dir() + f_log = file('prbs_dir_test.log', 'w') + f_log.write('\n \n PRSB test \n \n') + for file_cnt in range(len(files)) : + prev = 0x0FFF; + samples_chk=0 + prbs_err=0 + o_ta=0 + o_tb=0 + (f, frames_to_proces) = open_file(files, file_cnt) + if frames_to_proces >0 : + for frame_cnt in range(frames_to_proces): + data_list, ta, tb = read_frame(f, (frame_cnt==0), frame_cnt, f_log) + if (((ta==o_ta) and tb==(o_tb+1024)) or (ta == (o_ta+1))) : +# if (tb==(o_tb+1)) : + prev = prev + else: + prev=0x0FFF + r_samples_chk, r_prbs_err, prev = PRBS_CHECK(data_list, prev) + samples_chk = samples_chk + r_samples_chk + prbs_err = prbs_err + r_prbs_err + o_ta = ta + o_tb = tb + # plot results +# print 'Samples checked : ' + str(samples_chk) + ' PRBS errors: ' + str(prbs_err) + f_log.write('Samples checked : ' + str(samples_chk) + ' PRBS errors: ' + str(prbs_err) + '\n') + + f.close + f_log.close + +if __name__ == "__main__": + main() diff --git a/StationTest/prbs_test.py b/StationTest/prbs_test.py new file mode 100644 index 0000000000000000000000000000000000000000..5dea30abe241b8d9be5461025090a60ad43df857 --- /dev/null +++ b/StationTest/prbs_test.py @@ -0,0 +1,103 @@ + +""" script for testing PRBS data in dir. +Gijs, 16 dec 07 +""" +# INIT + +import array +import operator +import os +import time + +# Open file for processing +def open_dir() : +# os.chdir('c:/test') + files = os.listdir('.') + return files + +def open_file(files, file_nr) : + if files[file_nr][-3:] == 'dat': + fileinfo = os.stat(files[file_nr]) + size = int(fileinfo.st_size) + f=open(files[file_nr],'rb') + max_frames = size/(88 + 1024*2 + 4) + frames_to_proces=max_frames + else : + frames_to_proces=0 + f=open(files[file_nr],'rb') + return f, frames_to_proces + + + + +# Read single frame from file +def read_frame(f, info_plot, frame_nr,f_log): + station_info = array.array('B') + station_info.fromfile(f,4) # Bytes 0..3 + time_info = array.array('L') + time_info.fromfile(f,3) # Bytes 4..15 + if (info_plot) : + time_string = time.ctime(time_info[1]) + string_info = 'Frame nr %(FR)d Station %(ST)d RSP %(RSP)d RCU %(RCU)d Sample rate %(S)d MHz time of data %(ti_D)s and %(SN)00.6f seconds'%\ + {"FR": frame_nr, "ST": station_info[0] ,"RSP": station_info[1], "RCU": station_info[2], "S": station_info[3], "ti_D": time_string,"SN": float(time_info[2])/float(200000000)} + print string_info + f_log.write(string_info + '\n') + div_info = array.array('H') + div_info.fromfile(f,36) # Bytes 16..87 + + # READ DATA SAMPLES + data_in = array.array('H') + samples = int(div_info[0]) + data_in.fromfile(f,samples) + data_list = data_in.tolist() + + data_crc = array.array('l') + data_crc.fromfile(f,1) + return data_list + + +# Function for testing PRBS data +def PRBS_CHECK(data_list, prev): + samples_chk=0 + prbs_err=0 + for i in range(0,len(data_list)) : + if prev == 0x0FFF : + prev = data_list[i] & 0x07FF + elif data_list[i] == 0xFFFF : + prbs_err = prbs_err + 1 + else : + cur = data_list[i] & 0x0FFE + samples_chk = samples_chk + 1 + if cur != 2*prev : + prbs_err = prbs_err + 1 +# print(str(i) + ' ' + hex(2*prev) + ' ' + hex(cur)) + prev = data_list[i] & 0x07FF + return samples_chk, prbs_err, prev + + +# Main loop +def main() : + files = open_dir() + f_log = file('prbs_test.log', 'a') + f_log.write('\n \n PRSB test \n \n') + for file_cnt in range(len(files)) : + prev = 0x0FFF; + samples_chk=0 + prbs_err=0 + f, frames_to_proces = open_file(files, file_cnt) + if frames_to_proces >1 : + for frame_cnt in range(frames_to_proces): + data_list = read_frame(f, (frame_cnt==0), frame_cnt, f_log) + # Test data + r_samples_chk, r_prbs_err, prev = PRBS_CHECK(data_list, prev) + samples_chk = samples_chk + r_samples_chk + prbs_err = prbs_err + r_prbs_err + + # plot results + print 'Samples checked : ' + str(samples_chk) + ' PRBS errors: ' + str(prbs_err) + f_log.write('Samples checked : ' + str(samples_chk) + ' PRBS errors: ' + str(prbs_err) + '\n') + + f.close + f_log.close + +main() diff --git a/StationTest/rmfiles.sh b/StationTest/rmfiles.sh new file mode 100644 index 0000000000000000000000000000000000000000..c80deb914e2bab4c837b2f55744aa181ed9895fb --- /dev/null +++ b/StationTest/rmfiles.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +rm -f tc/*.log +rm -f *.log +rm -f *.diff +rm -f *.nfo +rm -f *.dat diff --git a/StationTest/rsp_version.sh b/StationTest/rsp_version.sh new file mode 100644 index 0000000000000000000000000000000000000000..64d46a8b4cf6c212fca347551155992fb231b59f --- /dev/null +++ b/StationTest/rsp_version.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# +# Get version info from the RSP boards and compare this with the expected golden result. +# + +rm -f *.log +rm -f *.diff +rspctl --version > rsp_version.log +diff rsp_version.log gold/rsp_version.gold > rsp_version.diff +if [ -e rsp_version.log ] && [ -e gold/rsp_version.gold ] && [ -e rsp_version.diff ] && ! [ -s rsp_version.diff ]; then + # The files exists AND the diff has size 0 + echo "RSP version test went OK" +else + echo "RSP version test went wrong" +fi diff --git a/StationTest/rsp_xc_160.sh b/StationTest/rsp_xc_160.sh new file mode 100644 index 0000000000000000000000000000000000000000..b6c6af8e664ae76301886a3073afae05889743a3 --- /dev/null +++ b/StationTest/rsp_xc_160.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# +# Test the SERDES ring between the RSP by verifing the crosslet statistics. +# + +./xc_160_setup.sh + +sleep 2 + +./xc_160_verify.sh diff --git a/StationTest/rsp_xc_200.sh b/StationTest/rsp_xc_200.sh new file mode 100644 index 0000000000000000000000000000000000000000..b5afc5a52a6bbabcbb57e14f35e605723cb1b52e --- /dev/null +++ b/StationTest/rsp_xc_200.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# +# Test the SERDES ring between the RSP by verifing the crosslet statistics. +# + +./xc_200_setup.sh + +sleep 2 + +./xc_200_verify.sh diff --git a/StationTest/station_production.py b/StationTest/station_production.py new file mode 100644 index 0000000000000000000000000000000000000000..69507897f3b97909906da3fc3c12cb11a9f94671 --- /dev/null +++ b/StationTest/station_production.py @@ -0,0 +1,191 @@ +# +# Run the production tests for a LOFAR station +# + +import sys +from optparse import OptionParser + +import cli +import testlog + +################################################################################ +# Parse command line for subrack ID +# +# -v 0 : only PASSED or FAILED +# -v 1 : overall title +# -v 11 : result per test +# -v 21 : title per test + +op = OptionParser(usage='usage: python %prog [options]', version='%prog 0.1') + +op.add_option('-v', type='int', dest='verbosity', + help='Verbosity level',default=11) +op.add_option('-r', type='int', dest='rsp_nr', + help='Provide number of rsp boards that will be used in this test',default=None) +op.add_option('-t', type='int', dest='tbb_nr', + help='Provide number of tbb boards that will be used in this test',default=None) + +opts, args = op.parse_args() + +# - Option checks and/or reformatting +if opts.rsp_nr==None: + op.error('Option -r must specify the number of rsp boards') +if opts.tbb_nr==None: + op.error('Option -t must specify the number of tbb boards') + + +################################################################################ +# Define subrack testlog class for pass/fail and logging +vlev = opts.verbosity +testId = '' +appLev = False +logName = '/home/lofartest/subracktest/data/SUBR-%05d-%05d.dat' % (opts.rsp_nr, opts.tbb_nr) +cli.command('rm -f /home/lofartest/subracktest/data/SUBR-%05d-%05d.dat', appLev) +sr = testlog.Testlog(vlev, testId, logName) + +sr.setResult('PASSED') + +sr.setId('Station - ') +sr.appendLog(11,'') +sr.appendLog(1,'Station production test %s' % logName) +sr.appendLog(11,'') + + +################################################################################ +sr.setId('RSP version - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify LCU - RSP ethernet link by getting the RSP version info') +sr.appendLog(21,'') +res = cli.command('./rsp_version.sh') +if res.find('wrong')==-1: + sr.appendLog(11,'>>> RSP version test went OK') +else: + sr.appendLog(11,'>>> RSP version test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendLog(11,'Result:') + sr.appendFile(11,'rsp_version.log') + sr.appendLog(11,'Expected:') + sr.appendFile(11,'gold/rsp_version.gold') + sr.setResult('FAILED') + + +################################################################################ +sr.setId('TBB version - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify LCU - TBB ethernet link by getting the TBB version info') +sr.appendLog(21,'') +res = cli.command('./tbb_version.sh') +if res.find('wrong')==-1: + sr.appendLog(11,'>>> TBB version test went OK') +else: + sr.appendLog(11,'>>> TBB version test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendLog(11,'Result:') + sr.appendFile(11,'tbb_version.log') + sr.appendLog(11,'Expected:') + sr.appendFile(11,'gold/tbb_version.gold') + sr.setResult('FAILED') + + +################################################################################ +sr.setId('SPU status - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify the RSP - SPU I2C interface by reading the SPU sensor data') +sr.appendLog(21,'') + +res = cli.command('python i2c_spu.py') +res = cli.command('python i2c_spu.py') +if res.find('wrong')==-1: + sr.appendLog(11,'>>> RSP - SPU I2c interface test went OK') +else: + sr.appendLog(11,'>>> RSP - SPU I2c interface test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendLog(11,'Result:') + sr.appendFile(11,'spustat.log') + sr.setResult('FAILED') + + +################################################################################ +sr.setId('TD status - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify the RSP - TD I2C interface by reading the TD sensor data') +sr.appendLog(21,'') + +res = cli.command('python i2c_td.py') +if res.find('wrong')==-1: + sr.appendLog(11,'>>> RSP - TD I2c interface test went OK') +else: + sr.appendLog(11,'>>> RSP - TD I2c interface test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendLog(11,'Result:') + sr.appendFile(11,'tdstat.log') + sr.setResult('FAILED') + + +################################################################################ +sr.setId('RCU-RSP - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify the RCU -> RSP LVDS interfaces by capturing pseudo random data on RSP') +sr.appendLog(21,'') + + +res = cli.command('python verify.py --brd rsp0,rsp1,rsp2,rsp3 --fpga blp0,blp1,blp2,blp3 --pol x,y --rep 1 -v 11 --te tc/prsg.py') + +if res.find('FAILED')==-1: + sr.appendLog(11,'>>> RCU-RSP interface test went OK') + sr.appendFile(21,'tc/prsg.log') +else: + sr.appendLog(11,'>>> RCU-RSP interface test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendFile(11,'tc/prsg.log') + sr.setResult('FAILED') + +################################################################################ +sr.setId('Serdes ring -') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify the Serdes ring connection between the RSP boards') +sr.appendLog(21,'') + +res = cli.command('python verify.py --brd rsp0,rsp1,rsp2,rsp3,rsp4,rsp5,rsp6,rsp7,rsp8,rsp9,rsp10,rsp11 --rep 1 -v 21 --te tc/serdes.py') + +if res.find('FAILED')==-1: + sr.appendLog(11,'>>> Serdes ring test went OK') + sr.appendLog(21,'tc/serdes.log') +else: + sr.appendLog(11,'>>> Serdes ring test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendLog(11,'tc/serdes.log') + sr.appendLog('FAILED') + + + +################################################################################ +sr.setId('RCU-RSP-TBB - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify the RCU - RSP - TBB LVDS interfaces by capturing pseudo random data on TBB') +sr.appendLog(21,'') + +res = cli.command('./tbb_prbs_tester.sh') +if res.find('wrong')==-1: + sr.appendLog(11,'>>> RCU - RSP - TBB LVDS interfaces test went OK') +else: + sr.appendLog(11,'>>> RCU - RSP - TBB LVDS interfaces went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.setResult('FAILED') + + +################################################################################ +# End of the subrack test + +sr.setId('Subrack - ') +dt = sr.getRunTime() +sr.appendLog(2,'Duration: %02dm:%02ds' % (dt/60 % 60, dt % 60)) +sr.appendLog(0,sr.getResult()) +sr.closeLog() diff --git a/StationTest/subrack_production.py b/StationTest/subrack_production.py new file mode 100644 index 0000000000000000000000000000000000000000..a70b196447cfe64a9549a386f44ba3b44a348df6 --- /dev/null +++ b/StationTest/subrack_production.py @@ -0,0 +1,170 @@ +# +# Run the production tests for a LOFAR station subrack +# + +import sys +from optparse import OptionParser + +import cli +import testlog + +################################################################################ +# Parse command line for subrack ID +# +# -v 0 : only PASSED or FAILED +# -v 1 : overall title +# -v 11 : result per test +# -v 21 : title per test + +op = OptionParser(usage='usage: python %prog [options]', version='%prog 0.1') + +op.add_option('-v', type='int', dest='verbosity', + help='Verbosity level',default=11) +op.add_option('-b', type='int', dest='batch_nr', + help='Provide subrack batch number that will be used for the log file name',default=None) +op.add_option('-s', type='int', dest='serial_nr', + help='Provide subrack serial number that will be used for the log file name',default=None) + +opts, args = op.parse_args() + +# - Option checks and/or reformatting +if opts.batch_nr==None: + op.error('Option -b must specify a subrack batch number') +if opts.serial_nr==None: + op.error('Option -s must specify a subrack serial number') + + +################################################################################ +# Define subrack testlog class for pass/fail and logging +vlev = opts.verbosity +testId = '' +appLev = False +logName = '/home/lofartest/subracktest/data/SUBR-%05d-%05d.dat' % (opts.batch_nr, opts.serial_nr) +cli.command('rm -f /home/lofartest/subracktest/data/SUBR-%05d-%05d.dat', appLev) +sr = testlog.Testlog(vlev, testId, logName) + +sr.setResult('PASSED') + +sr.setId('Subrack - ') +sr.appendLog(11,'') +sr.appendLog(1,'Subrack production test %s' % logName) +sr.appendLog(11,'') + + +################################################################################ +sr.setId('RSP version - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify LCU - RSP ethernet link by getting the RSP version info') +sr.appendLog(21,'') +res = cli.command('./rsp_version.sh') +if res.find('wrong')==-1: + sr.appendLog(11,'>>> RSP version test went OK') +else: + sr.appendLog(11,'>>> RSP version test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendLog(11,'Result:') + sr.appendFile(11,'rsp_version.log') + sr.appendLog(11,'Expected:') + sr.appendFile(11,'gold/rsp_version.gold') + sr.setResult('FAILED') + + +################################################################################ +sr.setId('TBB version - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify LCU - TBB ethernet link by getting the TBB version info') +sr.appendLog(21,'') +res = cli.command('./tbb_version.sh') +if res.find('wrong')==-1: + sr.appendLog(11,'>>> TBB version test went OK') +else: + sr.appendLog(11,'>>> TBB version test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendLog(11,'Result:') + sr.appendFile(11,'tbb_version.log') + sr.appendLog(11,'Expected:') + sr.appendFile(11,'gold/tbb_version.gold') + sr.setResult('FAILED') + + +################################################################################ +sr.setId('SPU status - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify the RSP - SPU I2C interface by reading the SPU sensor data') +sr.appendLog(21,'') + +res = cli.command('python i2c_spu.py') +res = cli.command('python i2c_spu.py') +if res.find('wrong')==-1: + sr.appendLog(11,'>>> RSP - SPU I2c interface test went OK') +else: + sr.appendLog(11,'>>> RSP - SPU I2c interface test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendLog(11,'Result:') + sr.appendFile(11,'spustat.log') + sr.setResult('FAILED') + + +################################################################################ +sr.setId('TD status - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify the RSP - TD I2C interface by reading the TD sensor data') +sr.appendLog(21,'') + +res = cli.command('python i2c_td.py') +if res.find('wrong')==-1: + sr.appendLog(11,'>>> RSP - TD I2c interface test went OK') +else: + sr.appendLog(11,'>>> RSP - TD I2c interface test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendLog(11,'Result:') + sr.appendFile(11,'tdstat.log') + sr.setResult('FAILED') + + +################################################################################ +sr.setId('RCU-RSP - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify the RCU -> RSP LVDS interfaces by capturing pseudo random data on RSP') +sr.appendLog(21,'') + +res = cli.command('python verify.py --brd rsp0,rsp1,rsp2,rsp3 --fpga blp0,blp1,blp2,blp3 --pol x,y --rep 1 -v 11 --te tc/prsg.py') +if res.find('FAILED')==-1: + sr.appendLog(11,'>>> RCU-RSP interface test went OK') + sr.appendFile(21,'tc/prsg.log') +else: + sr.appendLog(11,'>>> RCU-RSP interface test went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.appendFile(11,'tc/prsg.log') + sr.setResult('FAILED') + + +################################################################################ +sr.setId('RCU-RSP-TBB - ') +sr.appendLog(21,'') +sr.appendLog(21,'### Verify the RCU - RSP - TBB LVDS interfaces by capturing pseudo random data on TBB') +sr.appendLog(21,'') + +res = cli.command('./tbb_prbs_tester.sh') +if res.find('wrong')==-1: + sr.appendLog(11,'>>> RCU - RSP - TBB LVDS interfaces test went OK') +else: + sr.appendLog(11,'>>> RCU - RSP - TBB LVDS interfaces went wrong') + sr.appendLog(11,'CLI:') + sr.appendLog(11,res,1,1,1) + sr.setResult('FAILED') + + +################################################################################ +# End of the subrack test + +sr.setId('Subrack - ') +dt = sr.getRunTime() +sr.appendLog(2,'Duration: %02dm:%02ds' % (dt/60 % 60, dt % 60)) +sr.appendLog(0,sr.getResult()) +sr.closeLog() diff --git a/StationTest/subracktest.sh b/StationTest/subracktest.sh new file mode 100644 index 0000000000000000000000000000000000000000..4ac35bcf8ffdead3e779f256a1954d1af0c03d1e --- /dev/null +++ b/StationTest/subracktest.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# +# Run the tests for a LOFAR station subrack +# + +# Verify LCU - RSP, LCU - TBB ethernet links by getting the version info +./rsp_version.sh +./tbb_version.sh + +# Verify the RSP internal interfaces (Ethernet LCU, Ethernet CEP, 10 Gb Serdes, LVDS ring) by running the BIST +python verify.py --brd rsp0,rsp1,rsp2,rsp3 --rep 1 -v 11 --te tc/bist.py + +# Verify the RSP - SPU, TD I2C interface by reading the sensor data +python i2c_spu.py +python i2c_td.py + +# Verify the RSP - RSP SERDES links using pseudo random data +python verify.py --brd rsp0,rsp1,rsp2,rsp3 --rep 1 -v 11 --te tc/serdes.py --mode tx_rx + +# Verify the RSP - RSP SERDES links by capturing cross correlation statistics +./rsp_xc_200.sh + +# Verify the RCU -> RSP LVDS interfaces by capturing pseudo random data on RSP +python verify.py --brd rsp0,rsp1,rsp2,rsp3 --fpga blp0,blp1,blp2,blp3 --pol x,y --rep 1 -v 11 --te tc/prsg.py + +# Verify the RCU -> RSP -> TBB LVDS interfaces by capturing pseudo random data on TBB +./tbb_prbs_tester.sh + diff --git a/StationTest/tbb_prbs_tester.sh b/StationTest/tbb_prbs_tester.sh new file mode 100644 index 0000000000000000000000000000000000000000..4390bb7c21e0bd961d73b5a1796b8339272c0a31 --- /dev/null +++ b/StationTest/tbb_prbs_tester.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# +# Test the LVDS interfaces between RCU -> RSP -> TBB using the Pseudo Random generator in the RCUs. +# + +nof_rcu=32 + +rm -f *.log +rm -f *.diff +rm -f ./prbs/*.* +rm -f ./prbs/.* + + +# Set up RCU and RSP, make sure waveform generator is off +rspctl --rcuprsg=1 +sleep 1 +rspctl --tbbmode=transient + +sleep 5 +# set up TBB +nof_slices=10 # one slice contains 1024 transient (raw data) samples + +tbbctl --free +tbbctl --alloc +tbbctl --rec + +sleep 0.1 + +# Freeze and get the captured data from TBB +cd ./prbs +tbbctl --stop +for ((i = 0; i < $nof_rcu; i++)) do + tbbctl --readpage=$i,0,$nof_slices +done +cd .. +# Verify the PRBS +python prbs_dir_test.py + + +echo "" +diff prbs_dir_test.log ./gold/prbs_dir_test.gold > prbs_dir_test.diff +if [ -e prbs_dir_test.log ] && [ -e ./gold/prbs_dir_test.gold ] && [ -e prbs_dir_test.diff ] && ! [ -s prbs_dir_test.diff ]; then + # The files exists AND has the diff size 0 + echo "RCU -> RSP -> TBB interfaces test went OK" +else + echo "RCU -> RSP -> TBB interfaces test went wrong" +fi diff --git a/StationTest/tbb_version.sh b/StationTest/tbb_version.sh new file mode 100644 index 0000000000000000000000000000000000000000..c9b8155367c13f54f2d3f3671fa4c554a0d04019 --- /dev/null +++ b/StationTest/tbb_version.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# +# Get version info from the TBB boards and compare this with the expected golden result. +# + +rm -f *.log +rm -f *.diff +tbbctl --version --select=0,1 > tbb_version.log +diff tbb_version.log gold/tbb_version.gold > tbb_version.diff +if [ -e tbb_version.log ] && [ -e gold/tbb_version.gold ] && [ -e tbb_version.diff ] && ! [ -s tbb_version.diff ]; then + # The files exists AND has the diff size 0 + echo "TBB version test went OK" +else + echo "TBB version test went wrong" +fi diff --git a/StationTest/tc/Makefile.am b/StationTest/tc/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..8bee11394e1dd9254b3d0236bd68d3ac3d8c5e29 --- /dev/null +++ b/StationTest/tc/Makefile.am @@ -0,0 +1,15 @@ +testdir = $(prefix)/stationtest/tc +test_SCRIPTS = bist.py \ + empty.py \ + hba_client.py \ + hba_server.py \ + prsg.py \ + rad_lanemode.py \ + rad_latency.py \ + serdes.py \ + spustat.py \ + status.py \ + sync_delay.py \ + tdstat.py + +include $(top_srcdir)/Makefile.common diff --git a/StationTest/tc/bist.py b/StationTest/tc/bist.py new file mode 100644 index 0000000000000000000000000000000000000000..4f44e401d83fca3d5edf5a496fb6a312b371351b --- /dev/null +++ b/StationTest/tc/bist.py @@ -0,0 +1,146 @@ +"""Run the BIST messages manually, based on TCL testcase 11.5. +""" + +# See bist/src/data/bist_msgrom.txt + +################################################################################ +# - Verify options +rspId = tc.rspId +bpId = ['rsp'] +fpgaId = ['rsp', 'blp0', 'blp1', 'blp2', 'blp3'] + +tc.appendLog(11, '') +tc.appendLog(11, '>>> Run the BIST messages manually on RSP-%s' % rspId) +tc.appendLog(11, '') + +################################################################################ +# - Test selections +tst_duration = rsp.c_diag_duration_quick # 1 = quick +tst_duration = rsp.c_diag_duration_normal # 2 = normal +tst_lane = 0 + +# Ensure CR ext sync is enabled +#rsp.write_cr_syncon(tc, msg, fpgaId, rspId) + +# - Overwrite 20 (= 0x10+0x04) RSR selftest result fields with FE starting at offset 30 (= 0x1E). +# +# ty st frlen blp rsp pi rg offset payld seqnr rsvd Data ... +# 02 00 20 00 00 01 01 00 1E 00 10 00 01 00 00 00 FE FE FE FE FE FE FE FE FE FE FE FE FE FE FE FE +# 02 00 14 00 00 01 01 00 2E 00 04 00 02 00 00 00 FE FE FE FE 00 00 00 00 00 00 00 00 00 00 00 00 +# +value = 0xFE +rsp.overwrite_rsr(tc, msg, 'mep', value, rspId) +rsp.overwrite_rsr(tc, msg, 'diag', value, rspId) + +# Check overwriten RSR DIAG +for ri in rspId: + rsp.read_rsr(tc, msg, 'diag', [ri], 31) + +# - Write DIAG selftest for LCU +# +# ty st frlen blp rsp pi rg offset payld seqnr rsvd Data ... +# 02 00 14 00 00 01 03 06 00 00 04 00 03 00 00 00 03 01 02 00 00 00 00 00 00 00 00 00 00 00 00 00 +# +tst_interface = rsp.c_diag_dev_lcu # 3 = LCU +tst_mode = rsp.c_diag_mode_loop_local # 1 = loop local +selftest = [tst_interface, tst_mode, tst_duration, tst_lane] +for ri in rspId: + rsp.write_diag_selftest(tc, msg, selftest, bpId, [ri], 99) +tc.sleep(7000) + +# - Write DIAG selftest for CEP +# +# ty st frlen blp rsp pi rg offset payld seqnr rsvd Data ... +# 02 00 14 00 00 01 03 06 00 00 04 00 04 00 00 00 04 01 02 00 00 00 00 00 00 00 00 00 00 00 00 00 +# +tst_interface = rsp.c_diag_dev_cep # 4 = CEP +tst_mode = rsp.c_diag_mode_loop_local # 1 = loop local +selftest = [tst_interface, tst_mode, tst_duration, tst_lane] +for ri in rspId: + rsp.write_diag_selftest(tc, msg, selftest, bpId, [ri], 99) +tc.sleep(5000) + +# - Write DIAG selftest for SERDES +# +# ty st frlen blp rsp pi rg offset payld seqnr rsvd Data ... +# 02 00 14 00 00 01 03 06 00 00 04 00 05 00 00 00 05 01 02 00 00 00 00 00 00 00 00 00 00 00 00 00 +# +tst_interface = rsp.c_diag_dev_serdes # 5 = SERDES +tst_mode = rsp.c_diag_mode_loop_local # 1 = loop local +selftest = [tst_interface, tst_mode, tst_duration, tst_lane] +for ri in rspId: + rsp.write_diag_selftest(tc, msg, selftest, bpId, [ri], 99) +tc.sleep(1000) + +# - Write DIAG selftest for RI +# +# ty st frlen blp rsp pi rg offset payld seqnr rsvd Data ... +# 02 00 14 00 0F 01 03 06 00 00 04 00 06 00 00 00 00 06 02 00 00 00 00 00 00 00 00 00 00 00 00 00 +# +tst_interface = rsp.c_diag_dev_ri # 0 = RI +tst_mode = rsp.c_diag_mode_bus # 6 = mode bus is mode tx,rx +selftest = [tst_interface, tst_mode, tst_duration, tst_lane] +for ri in rspId: + rsp.write_diag_selftest(tc, msg, selftest, fpgaId, [ri], 99) +tc.sleep(1000) + +# - Read RSR to get BIST result, starting with MEP status error field (offset 0x1A) and length 0x18 bytes +# +# ty st frlen blp rsp pi rg offset payld seqnr rsvd Data ... +# 01 00 10 00 00 01 01 00 1A 00 18 00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# +for ri in rspId: + rsp.read_mem(tc, msg, 'rsr', 'status', rsp.c_ei_status_rsr_size, bpId, [ri], 'h', 1, rsp.c_ei_status_rsr_offset) + + msg.setOffset(rsp.c_ei_status_mep_offset) + dummy = msg.readUnsigned(2) + mep_prev_msg = msg.readUnsigned(1) + dummy = msg.readUnsigned(1) + + msg.setOffset(rsp.c_ei_status_diag_offset) + # DIAG status + diag_interface = msg.readUnsigned(1) + diag_mode = msg.readUnsigned(1) + diag_ri_bp = msg.readUnsigned(2) + diag_rcux = msg.readUnsigned(2) + diag_rcuy = msg.readUnsigned(2) + diag_eth_LCU = msg.readUnsigned(2) + diag_eth_CEP = msg.readUnsigned(2) + diag_serdes = msg.readUnsigned(2) + diag_ri_ap0 = msg.readUnsigned(2) + diag_ri_ap1 = msg.readUnsigned(2) + diag_ri_ap2 = msg.readUnsigned(2) + diag_ri_ap3 = msg.readUnsigned(2) + + # Verify + if mep_prev_msg == 0 and \ + diag_ri_bp == rsp.c_diag_res_ok and \ + diag_rcux != rsp.c_diag_res_ok and \ + diag_rcuy != rsp.c_diag_res_ok and \ + diag_eth_LCU == rsp.c_diag_res_ok and \ + diag_eth_CEP == rsp.c_diag_res_ok and \ + diag_serdes == rsp.c_diag_res_ok and \ + diag_ri_ap0 == rsp.c_diag_res_ok and \ + diag_ri_ap1 == rsp.c_diag_res_ok and \ + diag_ri_ap2 == rsp.c_diag_res_ok and \ + diag_ri_ap3 == rsp.c_diag_res_ok: + tc.appendLog(11, 'RSP-%s : BIST sequence went OK' % ri) + tc.setResult('PASSED') + else: + tc.appendLog(11, 'RSP-%s : BIST sequence went wrong:' % ri) + tc.appendLog(11, ' mep msg = %d' % mep_prev_msg) + tc.appendLog(11, ' ri-bp = %d' % diag_ri_bp) + tc.appendLog(11, ' rcux = %d' % diag_rcux) + tc.appendLog(11, ' rcuy = %d' % diag_rcuy) + tc.appendLog(11, ' eth-LCU = %d' % diag_eth_LCU) + tc.appendLog(11, ' eth-CEP = %d' % diag_eth_CEP) + tc.appendLog(11, ' serdes = %d' % diag_serdes) + tc.appendLog(11, ' ri-ap0 = %d' % diag_ri_ap0) + tc.appendLog(11, ' ri-ap1 = %d' % diag_ri_ap1) + tc.appendLog(11, ' ri-ap2 = %d' % diag_ri_ap2) + tc.appendLog(11, ' ri-ap3 = %d' % diag_ri_ap3) + tc.setResult('FAILED') + +# Read RSR DIAG again to also display result in text instead of numbers +for ri in rspId: + rsp.read_rsr(tc, msg, 'diag', [ri], 21) diff --git a/StationTest/tc/empty.py b/StationTest/tc/empty.py new file mode 100644 index 0000000000000000000000000000000000000000..0f6116eefa8e11048bd70e1560e6ee42e911047b --- /dev/null +++ b/StationTest/tc/empty.py @@ -0,0 +1,2 @@ +"""Empty testcase""" + diff --git a/StationTest/tc/hba_client.py b/StationTest/tc/hba_client.py new file mode 100644 index 0000000000000000000000000000000000000000..6d74e533d8ff35184bdc11ab429dc3bd0fd2d2ad --- /dev/null +++ b/StationTest/tc/hba_client.py @@ -0,0 +1,167 @@ +"""Write and readback HBA client registers, based on TCL testcase 5.42 + + - Specific arguments + . client_rcu : RCU to use for the HBA client I2C access, x or y + . client_access : r = read only, w = write only, wr = first write then readback + . client_reg : client register to access: request, response, led, vref, version, speed + . data : data byte(s) to write or verify read +""" + +################################################################################ +# - Verify options +rspId = tc.rspId +blpId = tc.blpId +repeat = tc.repeat # When > 1 then the register access will be repeated + +# - Rename testcase specific options +arg_rcu = arg_hba_client_rcu +arg_access = arg_hba_client_access +arg_reg = arg_hba_client_reg + +# Get rcuId +rcuId = [arg_rcu] + +# Adapt access format +if arg_access == 'w': + str_access = 'Write' +elif arg_access == 'r': + str_access = 'Read' +else: + str_access = 'Write and read' + arg_access = 'wr' + +tc.setResult('PASSED') + +tc.appendLog(11, '') +tc.appendLog(11, '>>> %s access of RSP-%s, BLP-%s, HBA client register %s via I2C access of RCU-%s' % (str_access, rspId, blpId, arg_reg, arg_rcu)) +tc.appendLog(11, '') + +################################################################################ +# - Testcase initializations + +# - Disable external sync +rsp.write_cr_syncoff(tc, msg, blpId, rspId) + +# - Prepare the protocol list for RCU control register +addr = rsp.c_rcuh_i2c_addr_hba # HBA client I2C address (7 bit) + +cmd_request = rsp.c_hba_cmd_request +cmd_response = rsp.c_hba_cmd_response +cmd_led = rsp.c_hba_cmd_led +cmd_vref = rsp.c_hba_cmd_vref +cmd_speed = rsp.c_hba_cmd_speed +cmd_version = rsp.c_hba_cmd_version + +f_set_byte = rsp.c_hba_f_set_byte +f_get_byte = rsp.c_hba_f_get_byte +f_set_word = rsp.c_hba_f_set_word +f_get_word = rsp.c_hba_f_get_word + +bc_server = rsp.c_hba_bc_server +first_server = 1 +last_server = 16 + +reg_xdelay = rsp.c_hba_sreg_xdelay + +# Select register +if arg_reg == 'request': + cmd = cmd_request + data_len = 2*(last_server - first_server + 1) + data = [] # primary data values + data.append(bc_server) + data.append(5 + data_len) + data.append(f_set_word) + data.append(reg_xdelay) + data.append(first_server) + data.append(last_server) + data2 = data # alternate data values + for i in range(data_len): + data.append(i) # count up data + data2.append(data_len - i) # count down data +elif arg_reg == 'response': + cmd = cmd_response + data = [17, 37, 59, 214] + data2 = [97, 231, 1, 14] +elif arg_reg == 'led': + cmd = cmd_led + data = arg_data # HBA client LED on > 0 + data2 = 0 # HBA client LED off = 0 +elif arg_reg == 'vref': + cmd = cmd_vref + data = arg_data # HBA client VREF setting, see pic16f87 manual + data2 = 236 # HBA client default VREF "11101100", [5]=1 for 24 steps, [3:0]=12 for mid level +elif arg_reg == 'speed': + cmd = cmd_speed + data = arg_data # HBA modem default speed setting is 40 + data2 = 41 +elif arg_reg == 'version': + cmd = cmd_version + data = arg_data # HBA client version write access should be ignored + data2 = 29 +else: + tc.appendLog(11, 'Register -%s- is unknown or not supported!' % arg_reg) + sys.exit() + +# - HBA modem timing +msec = rsp.c_msec +bc_wait = rsp.hba_bc_wait +gap_wait = rsp.hba_gap_wait +bc_i2c = rsp.hba_bc_i2c +reg_i2c = rsp.hba_reg_i2c + +for rep in range(1,1+repeat): + reg_dat = data + if repeat > 1: + tc.appendLog(11, '>>> %s' % rep) + if (rep % 2)==0 and arg_access != 'r': + reg_dat = data2 # alternate between write data and write data2 + + protocol_list = [] + exp_result = [] + if arg_access == 'wr' or arg_access == 'w': + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WRITE_BLOCK_NO_CNT', len(reg_dat), addr, reg_dat, cmd)) + exp_result.append(0) + if arg_access == 'wr' and arg_reg == 'request': + # Broadcast request takes modem time, 38 msec seems minimum for broadcast 16 servers and modem speed = 40, + # other I2C only register accesses do not need wait. + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WAIT', bc_wait * msec)) + exp_result.append(0) + else: + # Default I2C client register access wait time + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WAIT', gap_wait * msec)) + exp_result.append(0) + if arg_access == 'wr' or arg_access == 'r': + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_READ_BLOCK_NO_CNT', len(reg_dat), addr, None, cmd)) + exp_result.extend(reg_dat) + exp_result.append(0) + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_END')) + exp_result.append(0) + + # - Overwrite and read the protocol results from the RCUH + rsp.overwrite_rd_smbh_protocol_results(tc, msg, 'rcuh', rcuId, blpId, rspId) + + # - Write (and readback) the protocol list to the RCUH + rsp.write_rd_smbh_protocol_list(tc, msg, 'rcuh', protocol_list, rcuId, blpId, rspId) + + # - Apply altsync to start the RCUH SMBus protocols + rsp.write_rsu_altsync(tc, msg, rspId) + tc.sleep(bc_i2c + bc_wait + reg_i2c) + + # Read the protocol results from the RCUH + for ri in rspId: + for bi in blpId: + for pi in rcuId: + rd_result = smbus.read_results(tc, msg, 'rcuh', len(exp_result), pi, [bi], [ri]) + # Equal? + if rd_result == exp_result: + tc.appendLog(21, '>>> RSP-%s, BLP-%s, RCU-%s, HBA client I2C access result buffer contents is OK' % (ri, bi, pi)) + else: + tc.appendLog(11, '>>> RSP-%s, BLP-%s, RCU-%s, HBA client I2C access result buffer contents is wrong:' % (ri, bi, pi)) + tc.appendLog(11, 'Expected protocol result: %s' % exp_result) + tc.appendLog(11, 'Read protocol result: %s' % rd_result) + tc.setResult('FAILED') + + #tc.sleep(1000) + +# - Enable external sync +rsp.write_cr_syncon(tc, msg, blpId, rspId) diff --git a/StationTest/tc/hba_server.py b/StationTest/tc/hba_server.py new file mode 100644 index 0000000000000000000000000000000000000000..7aa8be90387546446a21eac1ad9d898885ae8e1c --- /dev/null +++ b/StationTest/tc/hba_server.py @@ -0,0 +1,337 @@ +"""HBA server access via modem, based on TCL testcase 5.43 + + - Specific arguments: + . client_rcu : RCU to use for the HBA client I2C access, x or y + . server : first server number and last server number: first,last + . server_access : bc = broadcast to all servers, uc = unicast to first server + . server_func : server function: gb, gw, sb, sw + . server_reg : server register: delay_x, delay_y, version, address + . data : data byte(s) to write or verify for each server + . count : use counter data for each write request (instead of data) + . rand : use random data for each write request (instead of data) +""" + +################################################################################ +# - Verify options +rspId = tc.rspId +blpId = tc.blpId +repeat = tc.repeat # When > 1 then the register access will be repeated + +# - Rename testcase specific options +arg_rcu = arg_hba_client_rcu +arg_server = arg_hba_server +arg_access = arg_hba_server_access +arg_func = arg_hba_server_function +arg_reg = arg_hba_server_reg + +# Get rcuId +rcuId = [arg_rcu] + +# Adapt access format +if arg_access == 'bc': + str_access = 'broadcast' +else: + str_access = 'unicast' + arg_access = 'uc' + +# Get server addresses +bc_server = rsp.c_hba_bc_server +if arg_access == 'bc': + first_server = arg_server[0] + last_server = arg_server[1] +else: + first_server = arg_server[0] + last_server = first_server +if first_server > last_server: + tc.appendLog(11, 'First server %d must be <= last server %d!' % (first_server, last_server)) + sys.exit() +elif last_server - first_server + 1 > 16: + tc.appendLog(11, 'Maximum first server %d to %d range is 16!' % (first_server, last_server)) + sys.exit() +elif first_server < 1 or first_server > 127: + tc.appendLog(11, 'First server %d must be in range 1 to 127!' % first_server) + sys.exit() +elif last_server < 1 or last_server > 127: + tc.appendLog(11, 'Last server %d must be in range 1 to 127!' % last_server) + sys.exit() + +# Get function +f_set_byte = rsp.c_hba_f_set_byte +f_get_byte = rsp.c_hba_f_get_byte +f_set_word = rsp.c_hba_f_set_word +f_get_word = rsp.c_hba_f_get_word +if arg_func == 'sb': + funcId = f_set_byte + funcSet = 1 + funcWidth = 1 +elif arg_func == 'gb': + funcId = f_get_byte + funcSet = 0 + funcWidth = 1 +elif arg_func == 'sw': + funcId = f_set_word + funcSet = 1 + funcWidth = 2 +elif arg_func == 'gw': + funcId = f_get_word + funcSet = 0 + funcWidth = 2 +else: + tc.appendLog(11, 'Function -%s- is unknown or not supported!' % arg_func) + sys.exit() + +# Get server register +if arg_reg == 'delay_x': + sreg = rsp.c_hba_sreg_xdelay # HBA server frontend X delay register +elif arg_reg == 'delay_y': + sreg = rsp.c_hba_sreg_ydelay # HBA server frontend Y delay register + if funcWidth != 1 and funcSet == 1: + tc.appendLog(11, 'Combination -%s- and -%s- is not supported!' % (arg_func, arg_reg)) + sys.exit() +elif arg_reg == 'version': + sreg = rsp.c_hba_sreg_version # HBA server version register + if funcWidth != 1 and funcSet == 1: + tc.appendLog(11, 'Combination -%s- and -%s- is not supported!' % (arg_func, arg_reg)) + sys.exit() +elif arg_reg == 'address': + sreg = rsp.c_hba_sreg_address # HBA server address register + if funcWidth != 1 and funcSet == 1: + tc.appendLog(11, 'Combination -%s- and -%s- is not supported!' % (arg_func, arg_reg)) + sys.exit() +else: + tc.appendLog(11, 'Server register -%s- is unknown or not supported!' % arg_reg) + sys.exit() + +# Define the server data: count values for bc and arg_data for uc +data = range(2) +data[0] = arg_data[0] +data[1] = 0 +if len(arg_data) == 2: + data[1] = arg_data[1] + +server_data = range(256) +for i in range(256): + server_data[i] = range(2) + server_data[i][0] = 0 + server_data[i][1] = 0 + +if arg_access == 'bc': + for si in range(first_server, last_server+1): + offset = 1 + for di in range(funcWidth): + server_data[si][di] = funcWidth*(si-first_server)+offset + offset += 1 +else: + for di in range(funcWidth): + server_data[first_server][di] = data[di] + +# Init random seed to allow reproduceble results for arg_rand +random.seed(0) + +tc.setResult('PASSED') + +tc.appendLog(11, '') +tc.appendLog(11, '>>> HBA server access of RSP-%s, BLP-%s via I2C access and control modem of RCU-%s' % (rspId, blpId, rcuId)) +tc.appendLog(11, ' Server access : str_access') +if arg_access == 'bc': + tc.appendLog(11, ' First server : %d' % first_server) + tc.appendLog(11, ' Last server : %d' % last_server) +else: + tc.appendLog(11, ' Server address : %d' % first_server) +tc.appendLog(11, ' Function : %s' % arg_func) +tc.appendLog(11, ' Register : %s' % arg_reg) +if funcSet == 1: + if arg_count==1: + tc.appendLog(11, ' Server data : Counter') + elif arg_rand==1: + tc.appendLog(11, ' Server data : Random') + else: + tc.appendLog(11, ' Server data :') + for si in range(first_server, last_server+1): + if funcWidth == 1: + tc.appendLog(11, ' %-3d: d(0) = %3d' % (si, server_data[si][0])) + else: + tc.appendLog(11, ' %-3d: d(0) = %3d, d(1) = %3d' % (si, server_data[si][0], server_data[si][1])) +tc.appendLog(11, '') + + +################################################################################ +# - Determine data request message + +reg_response_size = rsp.c_hba_reg_response_sz # HBA client RESPONSE register size in bytes + +data_request_hdr = [] +if arg_access == 'bc': + # Broadcast request + data_request_hdr.append(bc_server) + if funcSet == 1: + # Set byte or word + data_request_hdr.append(5 + funcWidth*(last_server - first_server + 1)) + data_request_hdr.append(funcId) + data_request_hdr.append(sreg) + data_request_hdr.append(first_server) + data_request_hdr.append(last_server) + else: + # Get byte or word + tc.appendLog(11, '') + tc.appendLog(11, '>>> Broadcast get function is allowed but void, because the HBA servers will not respond!') + tc.appendLog(11, '') + data_request_hdr.append(5) + data_request_hdr.append(funcId) + data_request_hdr.append(sreg) + data_request_hdr.append(first_server) + data_request_hdr.append(last_server) +else: + # Unicast request + data_request_hdr.append(first_server) + if funcSet == 1: + # Set byte or word + data_request_hdr.append(3 + funcWidth) + data_request_hdr.append(funcId) + data_request_hdr.append(sreg) + else: + # Get byte or word + data_request_hdr.append(3) + data_request_hdr.append(funcId) + data_request_hdr.append(sreg) + +################################################################################ +# - Testcase initializations + +# - Disable external sync +rsp.write_cr_syncoff(tc, msg, blpId, rspId) + +# - HBA modem timing +msec = rsp.c_msec +bc_wait = rsp.hba_bc_wait +uc_wait = rsp.hba_uc_wait +gap_wait = rsp.hba_gap_wait +bc_i2c = rsp.hba_bc_i2c +uc_i2c = rsp.hba_uc_i2c +reg_i2c = rsp.hba_reg_i2c + + +############################################################################### +# - HBA client I2C access + +i2c_addr = rsp.c_rcuh_i2c_addr_hba # HBA client I2C address (7 bit) + +cmd_request = rsp.c_hba_cmd_request # HBA client REQUEST register +cmd_response = rsp.c_hba_cmd_response # HBA client RESPONSE register + +for rep in range(1,1+repeat): + + if arg_count==1: + # - Use counter write data for each new data request + count = rep-1 + for si in range(first_server, last_server+1): + server_data[si][0] = (count >> 8) & 0xFF # byte data repeats after 2^8 count + if funcWidth==2: + server_data[si][1] = count & 0xFF # word data repeats after 2^16 count + # use same count for all servers + elif arg_rand==1: + # - Use random write data for each new data request + for si in range(first_server, last_server+1): + for di in range(funcWidth): + server_data[si][di] = int(256*random.random()) + # else: use default data + + # - Append the write data to the fixed data request header + data_request = data_request_hdr + if arg_access == 'bc': + # Broadcast request + if funcSet == 1: + # Set byte or word + for si in range(first_server, last_server+1): + for di in range(funcWidth): + data_request.append(server_data[si][di]) + # else: Get byte or word + else: + # Unicast request + if funcSet == 1: + # Set byte or word + for di in range(funcWidth): + data_request.append(server_data[first_server][di]) + # else: Get byte or word + + # - Define random data for response overwrite + repsonse_overwrite = [] + for i in range(reg_response_size): + repsonse_overwrite.append(int(256*random.random())) + + if arg_access == 'bc': + # Broadcast request + # Define arbitrary response register data that will written first and should not be affected by the broadcast request + data_response = repsonse_overwrite + else: + # Unicast request + # Determine expected response register data + data_response = [first_server + 128] + if funcSet == 1: + data_response.append(1) + else: + data_response.append(funcWidth + 1) + for di in range(funcWidth): + data_response.append(server_data[first_server][di]) + + # Log for debugging + #tc.appendLog(11, 'Expected REQUEST register: %s' % data_request) + #tc.appendLog(11, 'Expected RESPONSE register: %s' % data_response) + + if repeat > 1: + tc.appendLog(11, '>>> rep') + + protocol_list = [] + exp_result = [] + tc.appendLog(21, 'Overwrite RESPONSE register: %s' % repsonse_overwrite) + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WRITE_BLOCK_NO_CNT', len(repsonse_overwrite), i2c_addr, repsonse_overwrite, cmd_response)) + exp_result.append(0) + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WAIT', gap_wait * msec)) + exp_result.append(0) + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WRITE_BLOCK_NO_CNT', len(data_request), i2c_addr, data_request, cmd_request)) + exp_result.append(0) + if arg_access == 'bc': + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WAIT', bc_wait * msec)) + else: + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WAIT', uc_wait * msec)) + exp_result.append(0) + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_READ_BLOCK_NO_CNT', len(data_response), i2c_addr, None, cmd_response)) + exp_result.extend(data_response) + exp_result.append(0) + protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_END')) + exp_result.append(0) + + # - Overwrite and read the protocol results from the RCUH + rsp.overwrite_rd_smbh_protocol_results(tc, msg, 'rcuh', rcuId, blpId, rspId) + + # - Write (and readback) the protocol list to the RCUH + rsp.write_rd_smbh_protocol_list(tc, msg, 'rcuh', protocol_list, rcuId, blpId, rspId) + + # - Apply altsync to start the RCUH SMBus protocols + rsp.write_rsu_altsync(tc, msg, rspId) + if arg_access == 'bc': + tc.sleep(reg_i2c + gap_wait + bc_i2c + bc_wait) + else: + tc.sleep(reg_i2c + gap_wait + uc_i2c + uc_wait) + + # Read the protocol results from the RCUH + for ri in rspId: + for bi in blpId: + for pi in rcuId: + rd_result = smbus.read_results(tc, msg, 'rcuh', len(exp_result), pi, [bi], [ri]) + # Equal? + if rd_result == exp_result: + tc.appendLog(21, '>>> RSP-%s, BLP-%s, RCU-%s, HBA client I2C access result buffer contents is OK' % (ri, bi, pi)) + #tc.appendLog(11, 'Expected protocol result: %s' % exp_result) # useful for debugging + else: + tc.appendLog(11, '>>> RSP-%s, BLP-%s, RCU-%s, HBA client I2C access result buffer contents is wrong:' % (ri, bi, pi)) + tc.appendLog(11, 'Expected protocol result: %s' % exp_result) + tc.appendLog(11, 'Read protocol result: %s' % rd_result) + tc.setResult('FAILED') + + if tc.getResult()=='FAILED': + None + #break + +# - Enable external sync +rsp.write_cr_syncon(tc, msg, blpId, rspId) diff --git a/StationTest/tc/prsg.py b/StationTest/tc/prsg.py new file mode 100644 index 0000000000000000000000000000000000000000..73188b0e01ff30d9e6d914e7a32569d1db1dd9c1 --- /dev/null +++ b/StationTest/tc/prsg.py @@ -0,0 +1,150 @@ +"""Testcase for RCU - RSP data interface using PRSG, based on TCL testcase 5.10 + + Note: No specific arguments +""" + +################################################################################ +# Constants + +nof_reflets_ap = rsp.c_nof_reflets_ap +nof_beamlets = rsp.c_nof_beamlets_ap # maximum capable by RSP gateware +nof_beamlets = 216 # sufficient nof beamlets for 32 MHz BW +nof_beamlets_ap = rsp.c_nof_beamlets_ap # including reflets +nof_beamlets_ap = nof_reflets_ap + nof_beamlets # including reflets + +# - SS output size +c_ss_reflets_size = rsp.c_pol * nof_reflets_ap +c_ss_size = rsp.c_pol * nof_beamlets_ap + +c_ss_gap = rsp.c_slice_size - rsp.c_cpx * rsp.c_pol * nof_beamlets_ap + +# - Datapath result buffer +c_res_word_width = 4 +c_res_nof_words = rsp.c_cpx * rsp.c_pol * nof_beamlets_ap # include read reflets +c_res_nof_words_per_pol = rsp.c_cpx * nof_beamlets # skipped reflets + +################################################################################ +# - Verify options +rspId = tc.rspId +blpId = tc.blpId +polId = tc.polId +repeat = tc.repeat +tc.setResult('PASSED') # self checking test, so start assuming it will run PASSED + +tc.appendLog(11,'') +tc.appendLog(11,'>>> Capture PRSG data for RSP-%s, BLP-%s, RCU-%s' % (rspId, blpId, polId)) +tc.appendLog(11,'') + +################################################################################ +# - Testcase initializations +bypass = 0x8F # Bypass data path to have direct access to RCU data via SS, use resync + # version of pps to preserve X and Y order in captured data + +# - Write incrementing SS mapping, repeat (r > 1) write to 'ensure' both pages are written +#ss_map = [] +#for i in range(0, rsp.c_pol * nof_beamlets_ap): +# ss_map.append(i) +#r = 1 +#for i in range(0,r): +# rsp.write_ss(tc, msg, ss_map, blpId, rspId) +# tc.sleep(1000) +# rsp.write_ss(tc, msg, ss_map, blpId, rspId) +# tc.sleep(1000) + +# Apparently rspctl updates the SS every pps, so overwriting it does not work. +# Disabling SS update in RSPDriver.conf may be an option. However instead adapt +# this test case to the actual SS by reordering the captured data accordingly. +# Therefore read the actual SS into ss_map. + +# - Read actual SS mapping, to use it to reorder the read DIAG result +# . assume all BLP use same mapping +# . strip the reflets +# . assume that the beamlets mapping uses all subbands +bi = [blpId[0]] +ri = [rspId[0]] +ss_map = rsp.read_ss(tc, msg, c_ss_size, bi, ri) +ss_map = ss_map[c_ss_reflets_size:] + +rsp.write_cr_syncoff(tc, msg, blpId, rspId) +rsp.write_diag_bypass(tc, msg, bypass, blpId, rspId) + +################################################################################ +# Set RCU in PRSG mode +rsp.rspctl(tc, '--rcuprsg') + +################################################################################ +# Run the test +for k in range(0, repeat): + rsp.write_rsu_altsync(tc, msg, rspId) # Apply altsync to capture a new result buffer + tc.sleep(100) + + for ri in rspId: + for bi in blpId: + res_buffer = rsp.read_diag_result_buffer(tc, msg, c_res_nof_words, c_res_word_width, [bi], [ri]) + + res ={'x':[], 'y':[]} + for x in range(0, len(res_buffer), 2): + res['x'].append(res_buffer[x] & rsp.c_rcu_dat_mask) + for y in range(1, len(res_buffer), 2): + res['y'].append(res_buffer[y] & rsp.c_rcu_dat_mask) + res['x'] = res['x'][c_ss_reflets_size:] # strip the reflets + res['y'] = res['y'][c_ss_reflets_size:] + res['x'] = rsp.reorder(res['x'], ss_map) # reorder according to SS map + res['y'] = rsp.reorder(res['y'], ss_map) + + for pi in polId: + first = 1 # First result sample is used as starting seed for the expected samples + ok = 0 # 0 = OK + if len(res[pi]) == c_res_nof_words_per_pol: + for rs in res[pi]: + if first == 0: + if ok == 0: + if rs != rsp.calculate_next_sequence_value(rs_prev): + # Mismatch, so bridge the potential SS gap in the sample stream to verify whether this is the cause + rs_gap = rs_prev + for i in range(0, c_ss_gap): + rs_gap = rsp.calculate_next_sequence_value(rs_gap) + if rs != rsp.calculate_next_sequence_value(rs_prev): + # Mismatch again, so assume the potential SS gap was not the cause of the initial mismatch + nxt_rs_prev = rsp.calculate_next_sequence_value(rs_prev) + exp.append(nxt_rs_prev) + ok = 1 # 1 = sample mismatch + else: + # OK, so bridge the SS gap in the expected results + nxt_rs_prev = rsp.calculate_next_sequence_value(rs_gap) + exp.append(nxt_rs_prev) + else: + # OK, no SS gap to bridge + nxt_rs_prev = rsp.calculate_next_sequence_value(rs_prev) + exp.append(nxt_rs_prev) + else: + # A mismatch has aleready occured, no need to check for more mismatches + nxt_rs_prev = rsp.calculate_next_sequence_value(rs_prev) + exp.append(nxt_rs_prev) + else: + first = 0 + nxt_rs_prev = res[pi][0] + exp = [nxt_rs_prev] + rs_prev = nxt_rs_prev + else: + ok = 2 # 2 = length error + + # Report results + if ok == 0: + tc.appendLog(11,'>>> %d : RSP-%s, BLP-%s, RCU-%s PRSG data is OK.' % (k, ri, bi, pi)) + elif ok == 1: + tc.appendLog(11,'>>> %d : RSP-%s, BLP-%s, RCU-%s PRSG data mismatch.' % (k, ri, bi, pi)) + tc.appendLog(11,'- Expected data:') + tc.appendLog(11,'%s' % exp) + tc.appendLog(11,'- Captured data:') + tc.appendLog(11,'%s' % res[pi]) + tc.setResult('FAILED') + else: + tc.appendLog(11,'>>> %d : RSP-%s, BLP-%s, RCU-%s PRSG data length mismatch.' % (k, ri, bi, pi)) + tc.appendLog(11,'Captured length %d != expected length %d' % (len(res[pi]), c_res_nof_words_per_pol)) + tc.setResult('FAILED') + +# Restore defaults +bypass = 1 +rsp.write_diag_bypass(tc, msg, bypass, blpId, rspId, 99) +rsp.write_cr_syncon(tc, msg, blpId, rspId) diff --git a/StationTest/tc/rad_lanemode.py b/StationTest/tc/rad_lanemode.py new file mode 100644 index 0000000000000000000000000000000000000000..102806726d7d8bc078778e1e55e0c888ccc70820 --- /dev/null +++ b/StationTest/tc/rad_lanemode.py @@ -0,0 +1,35 @@ +"""Write or read the RAD lane mode, based on TCL testcase 5.24""" + +################################################################################ +# - Verify options +rspId = tc.rspId +repeat = tc.repeat + +# - Construct settings word from arg_rad_lane_mode +# +# settings: one byte for each lane, byte [3:0] for lane [3:0] +# format: XXXXAABB +# where XX = don't care +# AA = xlet mode +# BB = blet mode +# +# mode 00 = ignore remote data (only local) DEFAULT +# mode 01 = disable +# mode 10 = combine local and remote data +# mode 11 = ignore local data (only remote) +# +# arg_rad_lane_mode = [X3,X2,X1,X0,B3,B2,B1,B0] + +settings = 0 +for i in range(rsp.c_nof_lanes): + settings += ((arg_rad_lane_mode[i] << 2) + arg_rad_lane_mode[i+rsp.c_nof_lanes]) << (8*i) # X,B[3:0] + + +############################################################################# +# Read RAD latency for each RSP board + +if arg_read: + for ri in rspId: + rsp.read_rad_settings(tc, msg, [ri], 11) +else: + rsp.write_rad_settings(tc, msg, settings, rspId, 11) diff --git a/StationTest/tc/rad_latency.py b/StationTest/tc/rad_latency.py new file mode 100644 index 0000000000000000000000000000000000000000..b4bf54d46cf5351d293fafd84fa48883b7c2f258 --- /dev/null +++ b/StationTest/tc/rad_latency.py @@ -0,0 +1,21 @@ +"""Read the RAD latency, based on TCL testcase 5.49""" + +################################################################################ +# - Verify options +rspId = tc.rspId +repeat = tc.repeat + +tc.appendLog(11, '') +tc.appendLog(11, '>>> Read RAD_BP latency for RSP-%s.' % rspId) +tc.appendLog(11, '') + + +############################################################################# +# Read RAD latency for each RSP board + +if repeat==1: + latency = rsp.read_rad_latency(tc, msg, rspId, 11) +else: + for rep in range(1,1+repeat): + tc.appendLog(11, '>>> Rep %d' % rep) + latency = rsp.read_rad_latency(tc, msg, rspId, 11) diff --git a/StationTest/tc/serdes.py b/StationTest/tc/serdes.py new file mode 100644 index 0000000000000000000000000000000000000000..06f92b21fd068603de40c8da651219c326c32cb0 --- /dev/null +++ b/StationTest/tc/serdes.py @@ -0,0 +1,187 @@ +"""Test the SERDES ring between RSP boards, based on TCL testcase 3.8 + + - Specific arguments: + . diag_mode: + off = rsp.c_diag_mode_no_tst --> enable sync to stop continuous tx test + tx = rsp.c_diag_mode_loop_tx --> keep ext sync disabled to continue tx + rx = rsp.c_diag_mode_loop_rx + tx_rx = rsp.c_diag_mode_loop_tx_rx + local = rsp.c_diag_mode_loop_local --> use local loopback (idem as testcase 3.6) + . diag_sync: When 0 use external sync, else use altsync with sync interval time + given by 'sync' sec. + . diag_data: + cntr = use incremental data + lfsr = use LFSR data + + - Note: + . All four lanes are verified in parallel +""" +################################################################################ + +# NOTE: +# When using arg_sync = 0 to select the external sync the --brd order of RSP +# boards should match the fysical SERDES tx order. Due to the slow script +# (few MEP messages/sec) the test migth otherwise fail when too many boards +# are in the test. + +################################################################################ +# - Verify options +rspId = tc.rspId +repeat = tc.repeat + +# - Rename testcase specific options +arg_mode = arg_diag_mode +arg_sync = arg_diag_sync +arg_data = arg_diag_data + +################################################################################ +# - Test selections +tst_interface = rsp.c_diag_dev_serdes +tst_lane = 0xFF # not used + +if arg_mode == 'off': tst_mode = rsp.c_diag_mode_no_tst +elif arg_mode == 'tx': tst_mode = rsp.c_diag_mode_tx +elif arg_mode == 'rx': tst_mode = rsp.c_diag_mode_rx +elif arg_mode == 'tx_rx': tst_mode = rsp.c_diag_mode_tx_rx +elif arg_mode == 'local': tst_mode = rsp.c_diag_mode_loop_local +else: + tst_mode = rsp.c_diag_mode_loop_local + arg_mode = 'local' + tc.appendLog(11, 'ILLEGAL test mode, default to test mode %s.' % arg_mode) + +if arg_mode == 'tx': + # Use mode 'tx' as continuous tx, so no repeat necessary. Mode 'off' will stop the tx. + repeat = 1 + +# Incremental data is generated for test duration debug, else LFSR data +if arg_data == 'cntr': tst_duration = rsp.c_diag_duration_debug +elif arg_data == 'lfsr': tst_duration = rsp.c_diag_duration_quick +else: + tst_duration = rsp.c_diag_duration_quick + arg_data = 'lfsr' + +selftest = [tst_interface, tst_mode, tst_duration, tst_lane] + +############################################################################# +# Constants + +if arg_mode == 'off': + tc.appendLog(11, '') + tc.appendLog(11, '>>> RSP-%s, stop any previous SERDES tx selftest using mode %s.' % (rspId, arg_mode)) + tc.appendLog(11, '') + # - Stop any previous tx selftest + rsp.write_rsu_altsync(tc, msg, rspId) # start of tst sync interval + rsp.write_rsu_altsync(tc, msg, rspId) # end of tst sync interval + rsp.write_rsu_altsync(tc, msg, rspId) # end tx + rsp.write_cr_syncon(tc, msg, ['rsp'], rspId) # restore CR ext sync enabled default +else: + # - Run selftest + + tc.appendLog(11, '') + if arg_sync == 0: + tc.appendLog(11, '>>> RSP-%s, run SERDES test: mode %s, data %s, using external sync from TD clock board.' % (rspId, arg_mode, arg_data)) + else: + tc.appendLog(11, '>>> RSP-%s, run SERDES test: mode %s, data %s, using RSP on board alternative sync.' % (rspId, arg_mode, arg_data)) + tc.appendLog(11, '') + + for rep in range(1,1+repeat): + # Temporarily disable external sync + rsp.write_cr_syncoff(tc, msg, ['rsp'], rspId) + + value = 0xAB + tc.appendLog(31, '') + tc.appendLog(31, '>>> Overwrite RSR diag bytes with %#x to ensure fresh status.' % value) + tc.appendLog(31, '') + rsp.overwrite_rsr(tc, msg, 'diag', value, rspId) + for ri in rspId: + rsp.read_rsr(tc, msg, 'diag', [ri], 31) + + # Configure DIAG tst + for ri in rspId: + rsp.write_diag_selftest(tc, msg, selftest, ['rsp'], [ri], 99) + + tc.sleep(100) # wait DIAG ack_period_done + + # Sync control + if arg_mode != 'tx': + if arg_sync == 0: + # Enable external sync, first ext sync will start test, next ext sync will end test + rsp.write_cr_syncon(tc, msg, ['rsp'], rspId) + + # Wait for serdes_diag_lane tx, rx test to finish (1 until start sync, 1 measurement sync interval, 1 sync interval + # for tx to finish, so worst case 3 sec) + tc.sleep(3000) + else: + # Run serdes_diag_lane tx, rx test for 1 sync interval (arbitrary long, typically 1 sec) + rsp.write_rsu_altsync(tc, msg, rspId) # start of sync interval + tc.sleep(arg_sync*1000) + rsp.write_rsu_altsync(tc, msg, rspId) # end of sync interval + rsp.write_rsu_altsync(tc, msg, rspId) # end tx + tc.sleep(1000) # allow time for DIAG tst result event to reach RSR + rsp.write_cr_syncon(tc, msg, ['rsp'], rspId) # restore CR ext sync enabled default + # else: For mode 'tx' keep ext sync off to run tx forever, i.e. until tc is rerun with mode 'off'. + + for ri in rspId: + tc.appendLog(31, '') + tc.appendLog(31, '>>> %d: RSP-%s, read RSR diag status:' % (rep, ri)) + tc.appendLog(31, '') + + status = rsp.read_rsr(tc, msg, 'diag', [ri], 31) + status = status[0][0][:] + diag_interface = status[0] + diag_mode = status[1] + diag_ri_errors = status[2] + diag_rcux_errors = status[3] + diag_rcuy_errors = status[4] + diag_lcu_errors = status[5] + diag_cep_errors = status[6] + diag_serdes_errors = status[7] + diag_ap0_ri_errors = status[8] + diag_ap1_ri_errors = status[9] + diag_ap2_ri_errors = status[10] + diag_ap3_ri_errors = status[11] + + if arg_mode == 'tx': + if diag_interface == value: + tc.appendLog(11, '>>> RSP-%s, SERDES tx only is active, use mode off to stop it.' % ri) + tc.appendLog(11, '') + else: + tc.appendLog(11, '>>> RSP-%s, SERDES tx only went wrong.' % ri) + tc.appendLog(11, ' Unexpected test interface %d.' % diag_interface) + tc.setResult('FAILED') + elif diag_interface == tst_interface and \ + diag_mode == tst_mode and \ + diag_serdes_errors == 0: + tc.appendLog(11, '>>> %d: RSP-%s, SERDES test went OK.' % (rep, ri)) + tc.setResult('PASSED') + else: + tc.appendLog(11, '>>> %d: RSP-%s, SERDES test went wrong.' % (rep, ri)) + if diag_interface != tst_interface: + tc.appendLog(11, ' Unexpected test interface %d.' % diag_interface) + elif diag_mode != tst_mode: + tc.appendLog(11, ' Unexpected test mode %d.' % diag_mode) + else: + lane_mask = 2**rsp.c_nof_lanes - 1 + lane_ref = 2**rsp.c_nof_lanes + for i in range(rsp.c_nof_lanes): + lane_errors = (diag_serdes_errors >> (i*rsp.c_nof_lanes)) & lane_mask + if lane_errors == rsp.c_diag_res_ok: + tc.appendLog(11, ' Lane %d went OK.' % i) + elif lane_errors == rsp.c_diag_res_none: + tc.appendLog(11, ' Lane %d went wrong, nothing happened.' % i) + elif lane_errors == rsp.c_diag_res_sync_timeout: + tc.appendLog(11, ' Lane %d went wrong, sync timeout.' % i) + elif lane_errors == rsp.c_diag_res_data_timeout: + tc.appendLog(11, ' Lane %d went wrong, data timeout.' % i) + elif lane_errors == rsp.c_diag_res_word_err: + tc.appendLog(11, ' Lane %d went wrong, word errors occured.' % i) + elif lane_errors == rsp.c_diag_res_illegal: + tc.appendLog(11, ' Lane %d illegal status %d.' % (i, lane_errors)) + else: + tc.appendLog(11, ' Lane %d unknown status %d.' % (i, lane_errors)) + tc.setResult('FAILED') + # Break repeat loop in case test FAILED + if tc.getResult() == 'FAILED': + break + # Restore external sync enabled + rsp.write_cr_syncon(tc, msg, ['rsp'], rspId) diff --git a/StationTest/tc/spustat.py b/StationTest/tc/spustat.py new file mode 100644 index 0000000000000000000000000000000000000000..3c571e43513f06966591649654356b96087cb9da --- /dev/null +++ b/StationTest/tc/spustat.py @@ -0,0 +1,102 @@ +"""SPU monitor voltages and temperature via I2C, based on TCL testcase 9.6""" + +################################################################################ +# - Verify options +rspId = tc.rspId # allow multiple rsp, e.g. rsp0,rsp4 to access SPU in two subracks +repeat = tc.repeat # use >1 for continuous T,V monitoring or I2C stress test + +tc.setResult('PASSED') + + +tc.appendLog(11,'') +tc.appendLog(11,'>>> Monitor T and V of the SPU board using an I2C access via RSP-%s.' % rspId) +tc.appendLog(11,'') + +# Handle older versions of the SPU (Subrack Power Unit). +spu_version = 2 +#spu_version = 3 +if spu_version == 2: + v48 = 8 +if spu_version == 3: + v48 = 48 + +################################################################################ +# - Testcase initializations + +# - Disable external sync to avoid asynchronous trigger of TDSH protocol list +rsp.write_cr_syncoff(tc, msg, ['rsp'], rspId) + + +################################################################################ +# Read SPU sensor status via I2C + +addr = smbus.c_max6652_addr_vcc +config = smbus.c_max6652_config_start + smbus.c_max6652_config_line_freq_sel +protocol_list = [] +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_WRITE_BYTE', None, addr, [config], smbus.c_max6652_cmd_config)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE', None, addr, None, smbus.c_max6652_cmd_read_2v5)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE', None, addr, None, smbus.c_max6652_cmd_read_3v3)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE', None, addr, None, smbus.c_max6652_cmd_read_12v)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE', None, addr, None, smbus.c_max6652_cmd_read_vcc)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE', None, addr, None, smbus.c_max6652_cmd_read_temp)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_END')) +exp_result = '0 ? 0 ? 0 ? 0 ? 0 ? 0 0' +len_result = len(exp_result.split()) + + +for rep in range(1,1+repeat): + for ri in rspId: + # - Overwrite and read the protocol results from the TDSH + rsp.overwrite_rd_smbh_protocol_results(tc, msg, 'tdsh', None, None, [ri]) + + # - Write (and readback) the protocol list to the TDSH + rsp.write_rd_smbh_protocol_list(tc, msg, 'tdsh', protocol_list, None, None, [ri]) + + # Apply altsync to start the TDSH SMBus protocols + rsp.write_rsu_altsync(tc, msg, [ri]) + tc.sleep(100) + + # Read the protocol results from the TDSH + rd_result = smbus.read_results(tc, msg, 'tdsh', len_result, None, None, [ri]) + + # Sensor values + spu_volt_2v5 = rd_result[1] + spu_volt_3v3 = rd_result[3] + spu_volt_12v = rd_result[5] + spu_volt_vcc = rd_result[7] + spu_temp = rd_result[9] + + # SPU voltages + v_rcu = spu_volt_2v5 * smbus.c_max6652_unit_2v5 * (10+10)/10 + v_lba_rcu = spu_volt_3v3 * smbus.c_max6652_unit_3v3 * (10+20)/10 + v_hba = spu_volt_12v * smbus.c_max6652_unit_12v * (10+30.1)/10 + v_monitor = spu_volt_vcc * smbus.c_max6652_unit_vcc + + tc.appendLog(11, '') + tc.appendLog(11, 'SPU voltage and temperature measurements:') + tc.appendLog(11, '') + tc.appendLog(11, ' V_RCU = %6.3f V (= %4d * %7.1f mV)' % (v_rcu, spu_volt_2v5, 1000 * smbus.c_max6652_unit_2v5 * (10+10)/10)) + tc.appendLog(11, ' V_LBA_RCU = %6.3f V (= %4d * %7.1f mV)' % (v_lba_rcu, spu_volt_3v3, 1000 * smbus.c_max6652_unit_3v3 * (10+20)/10)) + tc.appendLog(11, ' V_HBA = %6.3f V (= %4d * %7.1f mV)' % (v_hba, spu_volt_12v, 1000 * smbus.c_max6652_unit_12v * (10+30.1)/10)) + tc.appendLog(11, '') + tc.appendLog(11, ' V_monitor = %6.3f V (= %4d * %7.1f mV) (This is the supply voltage of the sensor itself)' \ + % (v_monitor, spu_volt_vcc, 1000 * smbus.c_max6652_unit_vcc)) + tc.appendLog(11, '') + tc.appendLog(11, ' Temp = %4d degrees C' % spu_temp) + tc.appendLog(11, '') + + if rd_result[ 0] == 0 and v_rcu > 4.0 and v_rcu < 5.5 and \ + rd_result[ 2] == 0 and v_lba_rcu > 7 and v_lba_rcu < 9 and \ + rd_result[ 4] == 0 and v_hba > v48-5 and v_hba < v48+5 and \ + rd_result[ 6] == 0 and v_monitor > 3 and v_monitor < 4 and \ + rd_result[ 8] == 0 and spu_temp > 0 and spu_temp < 70 and \ + rd_result[10] == 0: + tc.appendLog(11, '>>> Rep-%d, RSP-%s, I2C access to the MAX6652 T,V sensor on the SPU board went OK' % (rep, ri)) + else: + tc.appendLog(11, '>>> Rep-%d, RSP-%s, I2C access to the MAX6652 T,V sensor on the SPU board went wrong:' % (rep, ri)) + tc.appendLog(11, 'Expected protocol result: %s' % exp_result) + tc.appendLog(11, 'Read protocol result: %s (slave address 0x%x)' % (rd_result, addr)) + tc.setResult('FAILED') + +# - Enable external sync +rsp.write_cr_syncon(tc, msg, ['rsp'], rspId) diff --git a/StationTest/tc/status.py b/StationTest/tc/status.py new file mode 100644 index 0000000000000000000000000000000000000000..c0dae7045eaef06138422d833d04095b24d6f5e6 --- /dev/null +++ b/StationTest/tc/status.py @@ -0,0 +1,57 @@ +""" Read the RSP status for one or all pid, based on TCL testcase 11.1""" + +################################################################################ +# - Verify options +rspId = tc.rspId +repeat = tc.repeat + +# Testcase specific options + +if not (arg_procid in ['rsp', + 'eth', + 'mep', + 'diag', + 'bs', + 'rcuh', + 'rsu', + 'ado', + 'rad', + 'all']): + arg_procid = 'all' + tc.appendLog(11, 'Forced unknown procid to \'all\'.') + +tc.appendLog(11, '') +tc.appendLog(11, '>>> Selected RSR read %s for RSP-%s.' % (arg_procid, rspId)) +tc.appendLog(11, '') + + +############################################################################# +# Read RSR for each RSP board + +if repeat==1: + status = rsp.read_rsr(tc, msg, arg_procid, rspId, 11) +else: + for rep in range(1,1+repeat): + tc.appendLog(11, '>>> %d' % rep) + if arg_procid == 'rad': + for ri in rspId: + status = rsp.read_rsr(tc, msg, arg_procid, [ri], 99) + rad_status = status[0][0] # based on bit 20 (= align, 0 is ok), + # bit 19 (= sync, 1 is ok), + # bit 18 (= brc, 0 is ok) + rad_raw = status[0][1] # rad_status info with count (bits 17:0) + rad_cnt = status[0][1][0] & 0x3FFFF # use RI count bits 17:0 + + rsr_str = '%d' % rad_status + for rd in rad_raw: + rsr_str += '%8d' % rd + if rad_status == rsp.c_rsr_undefined: + tc.appendLog(11, '%s, %d: RAD status is OFF (%s)' % (ri, rep, rsr_str)) + elif rad_status == rsp.c_rsr_ok: + tc.appendLog(21, '%s, %d: RAD status is OK (%s), RI count = %d' % (ri, rep, rsr_str, rad_cnt)) + else: + tc.appendLog(11, '%s, %d: RAD status is wrong : %s' % (ri, rep, rsr_str)) + else: + for ri in rspId: + status = rsp.read_rsr(tc, msg, arg_procid, [ri], 11) + tc.sleep(100) # less than 1 sec so we do not miss an interval status diff --git a/StationTest/tc/sync_delay.py b/StationTest/tc/sync_delay.py new file mode 100644 index 0000000000000000000000000000000000000000..378e45e658cfcf434394849897b1a9ba18856ef8 --- /dev/null +++ b/StationTest/tc/sync_delay.py @@ -0,0 +1,37 @@ +""" Read the RSP status for one or all pid, based on TCL testcase 11.1""" + +################################################################################ +# - Verify options +rspId = tc.rspId +blpId = tc.bpId +blpId.extend(tc.blpId) + +# Testcase specific options +arg_edge = arg_pps_edge +arg_delay = arg_pps_delay + +tc.appendLog(11, '') +if arg_read: + tc.appendLog(11, '>>> Read PPS input delay status for RSP-%s, BLP-%s.' % (rspId, blpId)) + tc.appendLog(11, '') + for ri in rspId: + for bi in blpId: + rsp.read_cr_sync_delay(tc, msg, [bi], [ri]) +else: + if arg_delay==0: + if arg_edge=='r': + tc.appendLog(11, '>>> RSP-%s, BLP-%s: Reset PPS input delay to default and capture on rising edge.' % (rspId, blpId)) + rsp.write_cr_sync_delay(tc, msg, 0, 0, blpId, rspId) + else: + tc.appendLog(11, '>>> RSP-%s, BLP-%s: Reset PPS input delay to default and capture on falling edge.' % (rspId, blpId)) + rsp.write_cr_sync_delay(tc, msg, 0, 1, blpId, rspId) + else: + if arg_edge=='r': + tc.appendLog(11, '>>> RSP-%s, BLP-%s: Increment PPS input delay %d times and capture on rising edge.' % (rspId, blpId, arg_delay)) + for ri in range(arg_delay): + rsp.write_cr_sync_delay(tc, msg, 1, 0, blpId, rspId) + else: + tc.appendLog(11, '>>> RSP-%s, BLP-%s: Increment PPS input delay %d times and capture on falling edge.' % (rspId, blpId, arg_delay)) + for ri in range(arg_delay): + rsp.write_cr_sync_delay(tc, msg, 1, 1, blpId, rspId) +tc.appendLog(11, '') diff --git a/StationTest/tc/tdstat.py b/StationTest/tc/tdstat.py new file mode 100644 index 0000000000000000000000000000000000000000..338394890733783481a695fe83201c7aa5ff6c74 --- /dev/null +++ b/StationTest/tc/tdstat.py @@ -0,0 +1,95 @@ +"""TDS monitor voltages and temperature via I2C, based on TCL testcase 9.1""" + +################################################################################ +# - Verify options +rspId = tc.rspId # allow multiple rsp, e.g. rsp0,rsp4 to access TDS in two subracks +repeat = tc.repeat # use >1 for continuous T,V monitoring or I2C stress test + +tc.setResult('PASSED') + +tc.appendLog(11,'') +tc.appendLog(11,'>>> Monitor T and V of the TDS board using an I2C access via RSP-%s.' % rspId) +tc.appendLog(11,'') + +# Handle older versions of the TDS (Timing Distribution Subrack) clock board. +td_version = 2 +#td_version = 3 +if td_version == 2: + v5 = 0 +if td_version == 3: + v5 = 5 + +################################################################################ +# - Testcase initializations + +# - Disable external sync to avoid asynchronous trigger of TDSH protocol list +rsp.write_cr_syncoff(tc, msg, ['rsp'], rspId) + + +################################################################################ +# Read TD sensor status via I2C + +addr = smbus.c_max6652_addr_gnd +config = smbus.c_max6652_config_start + smbus.c_max6652_config_line_freq_sel +protocol_list = [] +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_WRITE_BYTE', None, addr, [config], smbus.c_max6652_cmd_config)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE', None, addr, None, smbus.c_max6652_cmd_config)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE', None, addr, None, smbus.c_max6652_cmd_read_2v5)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE', None, addr, None, smbus.c_max6652_cmd_read_vcc)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE', None, addr, None, smbus.c_max6652_cmd_read_temp)) +protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_END')) +exp_result = '0 %d 0 ? 0 ? 0 ? 0 0' % config +len_result = len(exp_result.split()) + + +for rep in range(1,1+repeat): + for ri in rspId: + # - Overwrite and read the protocol results from the TDSH + rsp.overwrite_rd_smbh_protocol_results(tc, msg, 'tdsh', None, None, [ri]) + + # - Write (and readback) the protocol list to the TDSH + rsp.write_rd_smbh_protocol_list(tc, msg, 'tdsh', protocol_list, None, None, [ri]) + + # Apply altsync to start the TDSH SMBus protocols + rsp.write_rsu_altsync(tc, msg, [ri]) + tc.sleep(100) + + # Read the protocol results from the TDSH + rd_result = smbus.read_results(tc, msg, 'tdsh', len_result, None, None, [ri]) + + # Sensor values + volt_2v5 = rd_result[3] + volt_vcc = rd_result[5] + temp = rd_result[7] + + # TDS voltages + tds_5v = volt_2v5 * smbus.c_max6652_unit_2v5 * (10+10)/10 + tds_3v3 = volt_vcc * smbus.c_max6652_unit_vcc # note vcc unit is based on 5v, independent of true VCC + + tc.appendLog(11, '') + tc.appendLog(11, '>>> TDS voltage and temperature measurements:') + tc.appendLog(11, '') + tc.appendLog(11, ' 5V via 2v5 input = %6.3f V (= %4d * %7.4f mV)' % (tds_5v, volt_2v5, 1000*smbus.c_max6652_unit_2v5 * (10+10)/10)) + tc.appendLog(11, ' 3.3V via vcc input = %6.3f V (= %4d * %7.4f mV)' % (tds_3v3, volt_vcc, 1000*smbus.c_max6652_unit_vcc)) + tc.appendLog(11, ' Temp = %4d degrees C' % temp) + tc.appendLog(11, '') + + if rd_result[0] == 0 and \ + rd_result[1] == config and \ + rd_result[2] == 0 and \ + tds_5v > v5-1.0 and tds_5v < v5+0.5 and \ + rd_result[4] == 0 and \ + tds_3v3 > 3.0 and tds_3v3 < 4.0 and \ + rd_result[6] == 0 and \ + temp > 0 and temp < 70 and \ + rd_result[8] == 0 and \ + rd_result[9] == 0: + tc.appendLog(11, '>>> Rep-%d, RSP-%s, I2C access to the MAX6652 T,V sensor on the TDS board went OK' % (rep, ri)) + else: + tc.appendLog(11, '>>> Rep-%d, RSP-%s, I2C access to the MAX6652 T,V sensor on the TDS board went wrong:' % (rep, ri)) + tc.appendLog(11, 'Expected protocol result: %s' % exp_result) + tc.appendLog(11, 'Read protocol result: %s (slave address 0x%x)' % (rd_result, addr)) + tc.setResult('FAILED') + +# - Enable external sync +rsp.write_cr_syncon(tc, msg, ['rsp'], rspId) diff --git a/StationTest/verify.py b/StationTest/verify.py new file mode 100644 index 0000000000000000000000000000000000000000..b61f451fc71fe0de3c7ec6c881629841d71b507c --- /dev/null +++ b/StationTest/verify.py @@ -0,0 +1,188 @@ +"""Master script to execute a LOFAR station testcase script + + Features: + - Imports several modules + - Provides argument parsing using optparse + - Instantiates a Testcase class for logging + - Instantiates a MepMessage class for using rspctl --writeblock, --readblock + - Executes one or more testcase scripts (all use the same arguments) + + Notes: + - The structure resembles the TCL/C testcase suite used for the station + gateware (VHDL) development. + - Most TCL testcase will work directly if they are translated to Python. The + python scripts ougth to use high level rspctl commands wherever possible. + - The TCL suite only works under Windows, because it uses WinPCap for ethernet + access. This Python suite only works under Linux, because it uses rspctl. +""" + +################################################################################ +# Parse command line for testcase and options + +import sys +from optparse import OptionParser + +# Define empty class to be used as record, to keep local verify variables less +# easily known in the testcase scripts. +class v: + pass + +verify = OptionParser(usage='usage: python %prog [options]', version='%prog 0.1') + +# - Common options +verify.add_option('-v', type='int', dest='verbosity', + help='Verbosity level for the log file', default=11) +verify.add_option('--te', type='string', dest='testname', + help='File names of one or more testcases') + # Multiple testcases can be run using comma seperator, each with the same options though +verify.add_option('--rep', type='int', dest='repeat', + help='Repeat the test', default=1) +verify.add_option('--brd', type='string', dest='brdId', + help='Board id: rsp0,rsp1 for RSP 0 and 1, tbb0 for TBB 0', default='rsp0') + # Note multiple values for an option are possible by providing them with comma seperator and no spaces +verify.add_option('--fpga', type='string', dest='fpId', + help='FPGA id: rsp for BP, blp0 for AP0, tbb for TP, mp0 for MP0', default='rsp') + # On RSP and BLP is equivalent to an AP, but generaly an AP could implement multiple BLP +verify.add_option('--pol', type='string', dest='polId', + help='Polarization id: x, y or x,y', default='x,y') + +# - Testcase specific options +# Define the testcase specific options here, rather than passing an --args +# string to the testcase. The advantage is that they all show up with --help. +# The disadvantage is that for every new options also this verify.py needs to +# be updated. +verify.add_option('--pid', type='string', dest='pid', + help='Process ID: rsp, eth, mep, diag, bs, rcuh, rsu, ado, rad, all', default='all') +verify.add_option('--data', type='string', dest='data', + help='Data values(s) to write or verify read', default='40') +verify.add_option('--count', action='store_true', dest='count', + help='Use counter data values') +verify.add_option('--rand', action='store_true', dest='rand', + help='Use random data values') +verify.add_option('--read', action='store_true', dest='read', + help='Run the testcase read only') +verify.add_option('--pps_edge', type='string', dest='pps_edge', + help='Capture PPS on rising or falling clock edge: r, f', default='r') +verify.add_option('--pps_delay', type='int', dest='pps_delay', + help='Increment PPS input delay in steps of about 75 ps, use 0 for reset', default=1) +verify.add_option('--diag_mode', type='string', dest='diag_mode', + help='Diag mode: off, tx, rx, tx_rx, local', default='tx_rx') +verify.add_option('--diag_sync', type='int', dest='diag_sync', + help='Diag sync: 0 for pps, > 0 for alt sync interval in s', default=1) +verify.add_option('--diag_data', type='string', dest='diag_data', + help='Diag data: lfsr, cntr', default='lfsr') +verify.add_option('--rad_lane_mode', type='string', dest='rad_lane_mode', + help='RAD lane mode: X lane 3:0, B lane 3:0, where 0=local, 1=disable, 2=combine, 3=remote', default='0,0,0,0,0,0,0,0') +verify.add_option('--client_rcu', type='string', dest='client_rcu', + help='HBA control via this RCU, power via the other RCU: x or y', default='y') +verify.add_option('--client_access', type='string', dest='client_access', + help='HBA client access: r = read only, w = write only, wr = first write then readback', default='r') +verify.add_option('--client_reg', type='string', dest='client_reg', + help='HBA client register: request, response, led, vref, version, speed', default='led') +verify.add_option('--server', type='string', dest='server', + help='HBA server range, first server and last server', default='1,16') +verify.add_option('--server_access', type='string', dest='server_access', + help='HBA server access: bc = broadcast to all servers, uc = unicast to first server', default='uc') +verify.add_option('--server_function', type='string', dest='server_function', + help='HBA server function: gb, gw, sb, sw', default='gb') +verify.add_option('--server_reg', type='string', dest='server_reg', + help='HBA server register: delay_x, delay_y, version, address', default='delay_x') + +v.opts, v.args = verify.parse_args() + +# - Option checks and/or reformatting +if v.opts.testname==None: + verify.error('Option --te must specify a testcase file name') +else: + v.testname = v.opts.testname.split(',') + +v.strId = v.opts.brdId.split(',') +v.rspId = [] +v.tbbId = [] +for brd in v.strId: + if brd[:3] == 'rsp': + v.rspId.append(brd) + elif brd[:3] == 'tbb': + v.tbbId.append(brd) + else: + verify.error('Option --brd has invalid board id %s' % brd) + +v.strId = v.opts.fpId.split(',') +v.bpId = [] # RSP +v.blpId = [] +v.tpId = [] # TBB +v.mpId = [] +for fp in v.strId: + if fp == 'rsp': + v.bpId.append(fp) + elif fp[:3] == 'blp': + v.blpId.append(fp) + elif fp == 'tbb': + v.tpId.append(fp) + elif fp[:2] == 'mp': + v.mpId.append(fp) + else: + verify.error('Option --fp has invalid FPGA id %s' % fp) + +v.polId = v.opts.polId.split(',') + +# Pass the testcase specific options on directly, to avoid having to edit +# testcase.py for every new option. Rename with prefix arg_ so it is easier +# to search for the specific arguments, e.g. with grep or an editor. + +arg_procid = v.opts.pid +data_str = v.opts.data.split(',') +arg_data = [] +for di in data_str: + arg_data.append(int(di)) +arg_count = v.opts.count +arg_rand = v.opts.rand +arg_read = v.opts.read +arg_pps_edge = v.opts.pps_edge +arg_pps_delay = v.opts.pps_delay +arg_diag_mode = v.opts.diag_mode +arg_diag_sync = v.opts.diag_sync +arg_diag_data = v.opts.diag_data +rad_lane_mode_str = v.opts.rad_lane_mode.split(',') +arg_rad_lane_mode = [] +for lm in rad_lane_mode_str: + arg_rad_lane_mode.append(int(lm)) +arg_hba_client_rcu = v.opts.client_rcu +arg_hba_client_access = v.opts.client_access +arg_hba_client_reg = v.opts.client_reg +server_str = v.opts.server.split(',') +arg_hba_server = [] +for si in server_str: + arg_hba_server.append(int(si)) +arg_hba_server_access = v.opts.server_access +arg_hba_server_function = v.opts.server_function +arg_hba_server_reg = v.opts.server_reg + + +################################################################################ +# Run the testcase + +# Import here so no need in Testcase +import random +import mep +import testcase +import rsp +import smbus + +msg = mep.MepMessage() + +for te in v.testname: + # Pass the common options on via the testcase class instance. + tc = testcase.Testcase(v.opts.verbosity, + te, + v.opts.repeat, + v.rspId, v.bpId, v.blpId, + v.tbbId, v.tpId, v.mpId, + v.polId) + tc.appendLog(2,'--------------------------------------------------------------------------------') + tc.setResult('RUNONLY') + execfile(tc.testName) + dt = tc.getRunTime() + tc.appendLog(2,'Duration: %d %02d:%02d:%02d' % (dt/60/60/24, dt/60/60 % 24, dt/60 % 60, dt % 60)) + tc.appendLog(0,tc.getResult()) + tc.closeLog() diff --git a/StationTest/xc_160_setup.sh b/StationTest/xc_160_setup.sh new file mode 100644 index 0000000000000000000000000000000000000000..919a24161ea1a89c04775b1910ba8b97529ed813 --- /dev/null +++ b/StationTest/xc_160_setup.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# +# Setup part - Test the SERDES ring between the RSP by verifing the crosslet statistics. +# + +pi=$(echo "4*a(1)" | bc -l) + +nof_subbands=512 + +# Start waveform generators for crosscorrelation measurement + +nof_rcu=32 # nof RCU in a subrack +sample_freq=160000000 +rf_freq=40000000 +xc_subband=$(echo "$nof_subbands * $rf_freq / ($sample_freq/2)" | bc -l) + +for ((i = 0; i < $nof_rcu; i++)) do + phs=$(echo "($i * 2 * $pi) / $nof_rcu" | bc -l) + amp=$(echo "0.498 * $i / $nof_rcu" | bc -l) # use 0.498 for deterministic result, see bug 767 + rspctl --wg=$rf_freq --select=$i --ampli=$amp --phase=$phs +done + +rspctl --xcsubband=$xc_subband diff --git a/StationTest/xc_160_verify.sh b/StationTest/xc_160_verify.sh new file mode 100644 index 0000000000000000000000000000000000000000..6c3dbfa0d003c547475c7dbc72ebd15d13941970 --- /dev/null +++ b/StationTest/xc_160_verify.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# +# Verify part - Test the SERDES ring between the RSP by verifing the crosslet statistics. +# + +rm -f *.dat +rm -f *.diff + +# Capture crosscorrelation data for 1 sec + +rspctl --xcstat --duration=1 + + +# Verify the captured data + +xc_dat=$(ls *.dat) +diff $xc_dat gold/xst_160.gold > xst.diff +if [ -e $xc_dat ] && [ -e gold/xst_160.gold ] && [ -e xst.diff ] && ! [ -s xst.diff ]; then + # The files exists AND the diff has size 0 + echo "RSP serdes crosscorrelation test at 160 MHz went OK" +else + echo "RSP serdes crosscorrelation test at 160 MHz went wrong" +fi + diff --git a/StationTest/xc_200_setup.sh b/StationTest/xc_200_setup.sh new file mode 100644 index 0000000000000000000000000000000000000000..42d7b17d6f406dec3189507270ae4d158e4cad8c --- /dev/null +++ b/StationTest/xc_200_setup.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# +# Setup part - Test the SERDES ring between the RSP by verifing the crosslet statistics. +# + +pi=$(echo "4*a(1)" | bc -l) + +nof_subbands=512 + +# Start waveform generators for crosscorrelation measurement + +nof_rcu=32 # nof RCU in a subrack +sample_freq=200000000 +rf_freq=50000000 +xc_subband=$(echo "$nof_subbands * $rf_freq / ($sample_freq/2)" | bc -l) + +for ((i = 0; i < $nof_rcu; i++)) do + phs=$(echo "($i * 2 * $pi) / $nof_rcu" | bc -l) + amp=$(echo "0.498 * $i / $nof_rcu" | bc -l) # use 0.498 for deterministic result, see bug 767 + rspctl --wg=$rf_freq --select=$i --ampli=$amp --phase=$phs +done + +rspctl --xcsubband=$xc_subband diff --git a/StationTest/xc_200_verify.sh b/StationTest/xc_200_verify.sh new file mode 100644 index 0000000000000000000000000000000000000000..1fbfe22a32b537f47cfef717288d09cc47449944 --- /dev/null +++ b/StationTest/xc_200_verify.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# +# Verify part - Test the SERDES ring between the RSP by verifing the crosslet statistics. +# + +rm -f *.dat +rm -f *.diff + +# Capture crosscorrelation data for 1 sec + +rspctl --xcstat --duration=1 + + +# Verify the captured data, at 200 MHz it is necessary to distinghuis between even or odd sec + +xc_dat=$(ls *.dat) +diff $xc_dat gold/xst_200_even.gold > xst.diff +if [ -e $xc_dat ] && [ -e gold/xst_200_even.gold ] && [ -e xst.diff ] && ! [ -s xst.diff ]; then + # The files exists AND the diff has size 0 + echo "RSP serdes crosscorrelation test even second went OK" +else + diff $xc_dat gold/xst_200_odd.gold > xst.diff + if [ -e $xc_dat ] && [ -e gold/xst_200_odd.gold ] && [ -e xst.diff ] && ! [ -s xst.diff ]; then + # The files exists AND the diff has size 0 + echo "RSP serdes crosscorrelation test odd second went OK" + else + echo "RSP serdes crosscorrelation test went wrong" + fi +fi +