SKA PST RECV Architecture

Overview

The purpose of RECV is to acquire the timeseries of tied-array voltages from the Correlator Beam Former (CBF) and write them to the Shared Memory Ring Buffer (SMRB). RECV adds meta-data received from PST LMC during scan configuration to the meta-data that describe the timeseries, thereby providing a complete description of the data stream.

RECV implements the external interface between CBF and PST, further described in the Interfaces section. This interface handles the capture UDP packets transmitted by CBF, re-blocking the data payloads into larger segments and then writing these to the SMRB. These operations are governed by internal interfaces with the MGMT and SMRB.

Each PST Beam will spread the workload of RECV into a number (e.g. 4) of parallel data streams that can be split across the computational resources. The split will occur in the frequency domain, thereby creating multiple sub-bands (i.e. blocks of contiguous channels). The number of sub-bands and size of each sub-band may differ for each processing configuration.

Decomposition

RECV consists of a monitoring and control module (RECV.MGMT) which interacts with the MGMT component and controls the other sub-components of the RECV. RECV.MGMT controls instances of DataBlockManager, one for each sub-band. Each DataBlockManager, contains DataBlock instances for the Data and Weights streams. The DataBlock contains ring buffers for the Header (meta-data) and Data (time-series). Each of these ring buffers have a configurable number of elements and element size. The structure and relationship of of these classes are shown in the figure below.

../../../_images/DDD.RECV.Composition.png

Data and Control Flow

The data and control connections between these sub-components and modules are shown in the Connector and Component diagram below. The RECV component is largely a passive component as the RECV component writes to memory addresses managed by the RECV and the STAT and DSP components read from the same memory addresses.

../../../_images/DDD.RECV.DataControlFlow.png

State Model

@startuml
actor User
participant UDPReceiveDB as Recv
participant DataBlockWrite as Writer
participant ipcbuf_t as header
participant ipcio_t as data

activate Recv
User -> Recv: Call perform_configure_beam()
Recv -> Writer: Create DataBlockWrite instance
activate Writer
Writer -> header: Create ipcbuf_t instance
activate header
Writer -> data: Create ipcio_t instance
activate data

Recv -> Writer: Call connect()
Writer -> header: Call connect()
Writer -> data: Call connect()

Recv -> Writer: Call lock()
Writer -> header: Call lock_write()

User -> Recv: Call perform_configure_scan()
Recv -> Writer: Call write_config()
Writer -> header: Call get_next_write()
Writer -> header: Call mark_filled()

loop For each scan
    User -> Recv: Call perform_scan()

    Recv -> Writer: Call write_header()
    Writer -> header: Call get_next_write()
    Writer -> header: Call mark_filled()

    Recv -> Writer: Call open()
    Writer -> data: Call open('W')

    loop Until end of data
        Recv -> Writer: Call open_block()
        Writer -> data: Call open_block_write()
        Recv -> Writer: Call close_block()
        Writer -> data: Call close_block_write()
    end

    Recv -> Writer: Call close()
    Writer -> data: Call close()

    User -> Recv: Call perform_stop_scan()
end

User -> Recv: Call perform_deconfigure_scan()
Recv -> Writer: Call clear_config()

User -> Recv: Call perform_deconfigure_beam()
Recv -> Writer: Call unlock()
Writer -> header: Call unlock_write()

Recv -> Writer: Call disconnect()
Writer -> header: Call disconnect()
Writer -> data: Call disconnect()

deactivate Writer
deactivate data
deactivate header
@enduml

Sequence diagram showing interaction with the ring buffer