============================ Using Interactive station.py ============================ Once the SPS Test Suite has been installed a station can be deployed. This requires a :doc:`../station_config` corresponding to the used system. Configuration files for persistent deployments are provided in the :code:`config` directory of this project. If a new configuration file is needed, it is suggested to copy, rename and modify an existing configuration according to the used system. Configurations can also be generated from templates. These are available within the :code:`config/templates` directory and can be generated using :code:`scripts/config/python/generate_templates.py`. See the CI Pipeline :code:`.gitlab-ci.yml` for an example. Even if using an existing config file, the Tile Processing Modules being used may need to be changed. For example the RAL station config files default to only a selection of the TPMs available. There are two possible syntax for this, :code:`tiles` and :code:`subracks`. See the Station Configuration YAML page for more information. .. code-block:: # List of Subrack IPs (or names), and TPM slots which will form station subracks: subrack_1: cpu_ip: "10.192.0.24" # slots: [1, 2, 3, 4, 5, 6, 7, 8] slots: [] subrack_2: cpu_ip: "10.192.0.74" # slots: [1, 2, 3, 4, 5, 6, 7, 8] slots: [] # List of TPM IPs (or names) which will form station tiles: # Subrack 1 - "10.132.0.21" - "10.132.0.22" # - "10.132.0.23" # - "10.132.0.24" # - "10.132.0.25" # - "10.132.0.26" # - "10.132.0.27" # - "10.132.0.28" # # Subrack 2 # - "10.132.0.41" # - "10.132.0.42" # - "10.132.0.43" # - "10.132.0.44" # - "10.132.0.45" # - "10.132.0.46" # - "10.132.0.47" # - "10.132.0.48" The station can then be deployed with :code:`ipython` as below. The arguments :code:`IPB` initialise, program the FPGAs and start the beamformers. The full set of command line arguments are available below but this is the most common usage when deploying a station with :code:`ipython`. .. code-block:: pushd src/ska_low_sps_testsuite/common/ ipython -i station.py -- --config=config.yml -IPB **NOTE:** The installation creates symbolic links to many files and directories that are commonly used, including the :code:`station.py` file, the :code:`bitfiles` directory and the :code:`config` files directory. In most commands and YAML files where paths are required, it is typically easier to provide absolute paths based on the install location. For example :code:`/opt/sps/bitfiles/tpm_firmware_6_2_0.bit` for the FPGA firmware. For example on one of the machines at STFC-RAL :code:`te7dastardly`: .. code-block:: pushd src/ska_low_sps_testsuite/common/ ipython -i station.py -- --config=/opt/sps/config/ral_subrack_te7dastardly.yml -IPB A station can be deployed without an :code:`ipython` shell from any directory, so long as the virtual environment is sourced: .. code-block:: station.py --config=/opt/sps/config/.yml -IPB Below are all command line arguments supported by station.py : .. code-block:: Options: -h, --help show this help message and exit --config=CONFIG Configuration file [default: None] --port=PORT Port [default: None] --lmc_ip=LMC_IP IP [default: None] --lmc_port=LMC_PORT Port [default: None] -f BITFILE, --bitfile=BITFILE Bitfile to use (-P still required) [default: None] -t TILES, --tiles=TILES Tiles to add to station [default: None] -P, --program Program FPGAs [default: False] -I, --initialise Initialise TPM [default: False] --single_tile_mode Program all tiles as a single tile station, for testing --qsfp_detection=QSFP_DETECTION Force QSFP cable detection: auto, qsfp1, qsfp2, all, none [default: auto] --use_teng Use 10G for LMC [default: None] --chan-trunc=CHAN_TRUNC Channeliser truncation [default: None] -B, --beamf_start Start network beamformer [default: False] --channel-integration-time=CHANNEL_INTEG Integrated channel integration time [default: None] --beam-integration-time=BEAM_INTEG Integrated beam integration time [default: None] --beamformer-scaling=BEAM_SCALING Beamformer scaling [default: None] --beam-start_frequency=START_FREQUENCY_CHANNEL Beamformer scaling [default: None] --beam-bandwidth=BEAM_BANDWIDTH Beamformer scaling [default: None] --fft_sign_invert Conjugate FFT output [default: False] --log_level=LOG_LEVEL Specifies the log level [default: STEP] Tile methods ============ Once the station is initialised you will find yourself in an :code:`ipython` shell. At this stage some useful functionality is as follows: Calling station level methods like starting and stopping the beamformer: .. code-block:: In [1]: station.stop_beamformer() In [2]: station.start_beamformer() Hardware, firmware and network information such as build dates, hardware and bios revisions and IP addresses can be displayed by printing the tile object: .. code-block:: In [1]: for tile in station.tiles: print(tile) Out [1]: Tile Processing Module v2.0.1a Serial Number: 0850423050010 __________________________________________________________________________________________ | Classification | iTPM_ADU_2.0-NO-ADA Hardware Revision | v2.0.1a Serial Number | 0850423050010 BIOS Revision | v0.5.0 (CPLD_0x23092511-MCU_0xb000011a_0x20230209_0x0) Board Location | 65535:255:255 DDR Memory Capacity | 4 GB per FPGA _____________________________|____________________________________________________________ | FPGA Firmware Design | tpm_ska_low FPGA Firmware Release | 6.2.1 FPGA Firmware Build | 2007 FPGA Firmware Compile Time | 2025-02-19 19:15:13.771050 UTC FPGA Firmware Compile User | gitlab-runner (created by hajira bazaz) FPGA Firmware Compile Host | te7nelson linux-4.18.0-553.33.1.el8_10.x86_64-x86_64-with-glibc2.28 FPGA Firmware Git Branch | detached head FPGA Firmware Git Commit | db395557dcff7e5aa9d140045b4ff532dd41d86f janus-76: removed std.textio from tb_tb_example.vhd _____________________________|____________________________________________________________ | 1G (MGMT) IP Address | 10.132.0.62 1G (MGMT) MAC Address | fc:0f:e7:e6:f4:b0 1G (MGMT) Netmask | 255.255.255.0 1G (MGMT) Gateway IP | 10.132.0.254 EEP IP Address | 10.0.10.2 EEP Netmask | 255.255.255.0 EEP Gateway IP | 255.255.255.255 40G Port 1 IP Address | 10.130.0.53 40G Port 1 MAC Address | 62:00:0A:82:00:35 40G Port 1 Netmask | 255.255.255.128 40G Port 1 Gateway IP | 10.130.0.126 40G Port 2 IP Address | 0.0.0.0 40G Port 2 MAC Address | 02:00:00:00:00:00 40G Port 2 Netmask | 255.255.255.128 40G Port 2 Gateway IP | 10.130.0.126 Accessing the tiles in a station and some basic examples of reading attributes: .. code-block:: In [1]: tile = station.tiles[0] In [2]: tile.get_temperature() Out[2]: 58.8125 In [3]: tile.get_voltage(voltage_name='FPGA0_CORE') Out[3]: {'FPGA0_CORE': 0.94} Getting the health status dictionary for a tile: .. code-block:: In [4]: health_dict = tile.get_health_status() Calling plugin methods ====================== In the TPM API, plugins are used to represent hardware components of the TPM (Tile Processing Module) and the associated hierachy. During development you may want to call a plugin method directly from :code:`ipython`, for example the :code:`tpm_test_firmware` plugin. These objects represent the FPGA, each tile has two. .. code-block:: In [1]: tile = station.tiles[0] In [2]: fpga0_firmware = tile.tpm.tpm_test_firmware[0] In [3]: fpga1_firmware = tile.tpm.tpm_test_firmware[1] In [4]: fpga0_firmware.check_ddr_initialisation() Out[4]: True In [5]: fpga1_firmware.check_ddr_initialisation() Out[5]: False Or the mcu plugin. This represents the micro controller, each tile has one. .. code-block:: In [1]: tile = station.tiles[0] In [2]: tpm_monitor = tile.tpm.tpm_monitor[0] In [3]: tpm_monitor.get_version() Out[3]: **NOTE:** Only access plugin methods directly if you know what you are doing. This is only intended for development purposes, for production code plugin methods should have a corresponding method exposed at the tile level. Accessing TPM Registers directly ================================ Although methods such as the above exist to access top station and tile methods,, TPM registers can be accessed directly. To find a register using a string match i.e: .. code-block:: In [1]: tile.find_register('rst') Reading the value of a register, i.e the F2F interface reset: .. code-block:: In [1]: tile['fpga1.f2f_0.ctrl.rst'] Writing the same register, for example with the value 1, can simply be done with: .. code-block:: In [2]: tile['fpga1.f2f_0.ctrl.rst'] = 1 **NOTE:** Only access registers directly if you know what you are doing. This is only intended for development purposes, for production code registers should have a corresponding plugin methods.