The DIBAS is a multi-mode instrument. Modes are selected by programming the FPGA with new BOF files and initializing them according to the needs for that mode.
Each BOF file has its own set of registers which do not necessarily do the same things and are not named the same way accross BOF files. The Backend classes exist to abstract away the differences and provide a common interface to all the BOF files.
The Bank class uses a strategy pattern [strategy] to deal with each different BOF file. When a mode is selected an object that derives from Backend is constructed and handles all requests to the Backend functions. Each Backend class implements the Backend interface as appropriate. There are currently 8 backend classes:
- Backend: the base class
- GuppiBackend: incoherent mode pulsar backend based on GBT GUPPI instrument
- GuppiCODDBackend: Coherent de-dispersion mode pulsar backend, based on GBT GUPPI instrument.
- VegasBackend: Base class for the spectral line modes, based on GBT VEGAS spectrometer
- VegasHBWBackend: Instance class for the wide band spectral line modes (modes 1-3)
- VegasLBWBackend: Base class for the narrow band spectral line modes (modes 4-29)
- VegasL1LBWBackend: Instance class for the L1 lbw modes. These modes provide a fixed narrow-band window.
- VegasL8LBWBackend: Instance class for the L8 lbw modes. These modes provide 1 or 8 movable narrow-band windows.
The base class provides the interface and a fair amount of common functionality (gettting/setting status memory, roach registers, etc.) The individual derived backend classes provide the functionality that must be specific to each backend.
A base class which implements some of the common backend calculations (e.g switching).
Backend(theBank, theMode, theRoach, theValon, unit_test) Where:
execute_phase(self, phase)
A super simple interpreter of commands to do things to the FPGA, such as resetting the ROACH, arming it, etc. By interpreting the string list ‘phase’ the specific sequence of commands can then be stored in a configuration file instead of being hard-coded in the code.
self: This object.
phase: a sequence of string tuples, where the first element of the tuple is the command, and the second element the parameter: [(“sg_sync, “0x12”), (“wait”, “0.5”), (“arm”, “0”), (“arm”, “1”), ...]
Converts an IP string, ie ‘170.0.0.1’, and returns an integer. If ‘ip’ is already an int, returns it.
Waits for the shared memory status register ‘reg’ to read value ‘expected’. Returns True if that value appears within ‘max_delay’ (milliseconds), False if not. ‘wait’ returns the actual time waited (mS), within 100 mS.
add_switching_state(duration, blank, cal, sig):
Add a description of one switching phase (backend dependent).
If any of the named parameters is not provided, that parameter defaults to False.
Example to set up a 8 phase signal (4-phase if blanking is not considered) with blanking, cal, and sig/ref, total of 400 mS:
be = Backend(None) # no real backend needed for example
be.clear_switching_states()
be.add_switching_state(0.01, blank = True, cal = True, sig = True)
be.add_switching_state(0.09, cal = True, sig = True)
be.add_switching_state(0.01, blank = True, cal = True)
be.add_switching_state(0.09, cal = True)
be.add_switching_state(0.01, blank = True, sig = True)
be.add_switching_state(0.09, sig = True)
be.add_switching_state(0.01, blank = True)
be.add_switching_state(0.09)
arm_roach(self):
Sends a sequence of commands to arm the ROACH. This is mode dependent and mode should have been specified in advance, as the sequence of commands is obtained from the ‘MODEX’ section of the configuration file.
This explicitly cleans up any child processes. This will be called by the player before deleting the backend object.
disarm_roach(self):
Sends a sequence of commands to disarm the ROACH. This is mode dependent and mode should have been specified in advance, as the sequence of commands is obtained from the ‘MODEX’ section of the configuration file.
getI2CValue(addr, nbytes, data):
Returns the IF bits used to set the input filter.
Example:
bits = self.getI2CValue(0x38, 1)
Return the value of a parameter, if available, or None if the parameter does not exist.
Returns the specified key’s value, or the values of several keys, or the entire contents of the shared memory status buffer.
keys == None: The entire buffer is returned, as a dictionary containing the key/value pairs.
keys is a list or tuple of keys: returns a dictionary containing the requested subset of key/value pairs.
keys is a single string: a single value will be looked up and returned using ‘keys’ as the single key.
Returns the doc string of the Backend member function that is responsible for setting the value of param, or, returns a list of all params with their doc string.
Returns a string, the doc string for the specified parameter, or a dictinary of all parameters with their doc strings.
Opens the named pipe to the HPC program, sends ‘cmd’, and closes the pipe. This takes care to not block on the fifo.
monitor() requests that the DAQ program go into monitor mode. This is handy for troubleshooting issues like no data. In monitor mode the DAQ’s net thread starts receiving data but does not do anything with that data. However the thread’s status may be read in the status memory: NETSTAT will say ‘receiving’ if packets are arriving, ‘waiting’ if not.
Configures the 10Gb/s interface on the roach. This consists of sending the tap-start katcp command to initialize the FPGA’s 10Gb/s interface, and updating a couple of registers on the ROACH2 with the destination IP address and port of the HPC computer.
All the parameters to this function have ‘None’ as default values; if any is ommitted from the call the function will use the corresponding value loaded from the configuration file.
progdev(self, bof, frequency):
Programs the ROACH2 with boffile ‘bof’.
reset_roach(self):
Sends a sequence of commands to reset the ROACH. This is mode dependent and mode should have been specified in advance, as the sequence of commands is obtained from the MODE sections of the configuration file.
Round the provided time up to the nearest second.
This parameter records the cal on/off frequency used on the telescope, in Hz.
setI2CValue(addr, nbytes, data):
Sets the IF bits used to set the input filter.
Example:
self.setI2CValue(0x38, 1, 0x25)
Turns the noise source on or off
Selects the noise source or test tone for channel 1
Selects the noise source or test tone for channel 2
Sets the project id for the session. This becomes part of the directory path for the backend data in the form:
$DIBAS_DATA/<projectid>/<backend>/<data file>
This parameter sets the SRC_NAME shared memory value.
This parameter sets the source’s RA & Dec.
Source RA/Dec may be specified as a string:
set_param(source_ra_dec="J141213.23+161252.12")
or:
set_param(source_ra_dec="03:14:15.9 +26:37:10.11")
This parameter sets the TELESCOP shared memory value.
set_gbt_ss(period, ss_list):
adds a complete GBT style switching signal description.
Example:
b.set_gbt_ss(period = 0.1,
ss_list = ((0.0, SWbits.SIG, SWbits.CALON, 0.025),
(0.25, SWbits.SIG, SWbits.CALOFF, 0.025),
(0.5, SWbits.REF, SWbits.CALON, 0.025),
(0.75, SWbits.REF, SWbits.CALOFF, 0.025))
)
Programs the I2C based on bandwidth, noise source, and noise tones. Intended to be called from Backend’s ‘prepare’ function.
The DIBAS backends are directly controlled by setting registers in the FPGA, setting key/value pairs in status memory, setting the Valon and I2C controllers, etc. Low level interfaces to do all these things exist. However, there are often time and value dependencies associated between these values. set_param() provides a way to set values at a higher level of abstraction so that when the low-level values are set, the dependencies are computed and the values are set in the proper order. This is therefore a high-level method of setting instrument parameters.
Once all parameters are set a call to prepare() will cause the dependencies to be computed and the values sent to their respective destinations.
If a parameter is given that does not exist, the function will throw an exception that includes a list of the available parameters (see help_param() as well).
This function is normally called by the Bank.set_param(**kvpairs) member.
Example:
self.set_param('exposure', 0.05)
Updates the named roach registers with the values for the keys specified in the parameter list as keyword value pairs.
This is a low-level function that directly sets FPGA registers. Use set_param() where possible.
Example:
self.set_register(FFT_SHIFT=0xaaaaaaaa, N_CHAN=6)
This sets the FFT_SHIFT and N_CHAN registers.
Note: Only integer values are supported.
Modifies the local status dictionary
This is a low-level function that will set any arbitrary key to any value in status shared memory. Use set_param() where possible.
Example:
self.set_status(PROJID='JUNK', OBS_MODE='HBW')
# or, equivalent
d = {'PROJID':'JUNK', 'OBS_MODE'='HBW'}
self.set_status(**d)
–OR–
Sets up the system for a measurement and kicks it off at the appropriate time, based on ‘starttime’. If ‘starttime’ is not on a PPS boundary it is bumped up to the next PPS boundary. If ‘starttime’ is not given, the earliest possible start time is used.
start() will require a needed arm delay time, which is specified in every mode section of the configuration file as needed_arm_delay. During this delay it tells the HPC program to start its net, accum and disk threads, and waits for the HPC program to report that it is receiving data. It then calculates the time it needs to sleep until just after the penultimate PPS signal. At that time it wakes up and arms the ROACH. The ROACH should then send the initial packet at that time.
Because the child backend start procedure is time consuming, this start merely records the start time, sets a flag, and returns. This allows the Dealer to issue starts quickly to every Player. The player’s watchdog will then pick up on the start flag, and perform the lengthy start procedure more-or-less in parallel.
Stop the hpc program and make it exit. To stop an observation use ‘stop()’ instead.
Writes the contents of the local roach register dictionary to the roach. These values will have been previously set by ‘set_register()’.
This function should only be called by instantiated class objects, not by classes that act as parent classes. It will only do something if self.roach is not None, and if the object is not in unit-test mode.
Writes the contents ‘kwargs’ to status memory.
This function does something only if the status memory object exists, and not in unit-test mode. It should only be called from instantiated classes, never parent classes.
A class which implements some of the GUPPI specific parameter calculations. This class is specific to the Incoherent BOF designs.
GuppiBackend(theBank, theMode, theRoach, theValon, unit_test)
Calculates the hardware accumulation length. The register values must be in the range of 0 to 65535, in even powers of two, minus one.
Calculates the CHAN_BW status keyword Result is bandwidth of each channel in MHz
Calculate the DS_FREQ status keyword. This is used only when an observer wants to reduce the number of channels in software, while using a higher number of hardware channels in SEARCH or COHERENT_SEARCH modes.
Calculates the number of polarizations to be recorded. Most cases it is all four, except in FAST4K, or when the user has indicated they only want 1 stokes product)
Randy/Jason indicated that the new guppi designs will have 12 taps in all modes.
Calculates the POL_TYPE status keyword. Depends upon a synthetic mode name having FAST4K for that mode, otherwise non-4k coherent mode is assumed.
Parameter ‘integration_time’: Lenght of integration, in seconds.
Tells DAQ program to enter monitor mode.
Parameter ‘nchan’: Number of channels
Parameter ‘obs_mode’: GUPPI observation mode
Returns the current state of a scan, as a tuple: (scan_running (bool), ‘NETSTAT=’ (string), and ‘DISKSTAT=’ (string))
Sets the FD_POLN (feed polarization) keyword in status memory and PSR FITS files. Legal values are ‘LIN’ (linear) or ‘CIRC’ (circular)
Sets the dispersion measure for coherent search modes. Other modes should have this set to zero.
Sets the integration time. The actual value used may be adjusted to make the interval be an even multiple of the hardware accumulation rate. (Actual value in TBIN keyword.)
For cal and fold modes, this sets the number of bins in a pulse profile. Ignored in other modes.
Sets the observing mode. Legal values for the currently selected mode are: SEARCH, FOLD, CAL, or RAW
Controls whether to ‘record only summed polarizations’ mode. Zero indicates that full stokes data should be recorded. One means to record only summed polarizations. This will be set to zero when using the ‘FAST4K’ observing mode.
Sets all the saling factors with one parameter.
Sets the hardware scaling factor for the I stokes parameter. Range is 0.0 through 65535.99998.
Sets the hardware scaling factor for the Q stokes parameter. Range is 0.0 through 65535.99998.
Sets the hardware scaling factor for the U stokes parameter. Range is 0.0 through 65535.99998.
Sets the hardware scaling factor for the V stokes parameter. Range is 0.0 through 65535.99998.
Sets the software integration time per profile for all folding and cal modes. This is ignored in other modes.
–OR–
Sets up the system for a measurement and kicks it off at the appropriate time, based on starttime. If starttime is not on a PPS boundary it is bumped up to the next PPS boundary. If starttime is not given, the earliest possible start time is used.
start() will require a needed arm delay time, which is specified in every mode section of the configuration file as ‘needed_arm_delay’. During this delay it tells the HPC program to start its net, accum and disk threads, and waits for the HPC program to report that it is receiving data. It then calculates the time it needs to sleep until just after the penultimate PPS signal. At that time it wakes up and arms the ROACH. The ROACH should then send the initial packet at that time.
A class which implements some of the GUPPI specific parameter calculations. This class is specific to the coherent mode BOF designs.
GuppiCODDBackend(theBank, theMode, theRoach, theValon, unit_test)
Calculates the CHAN_BW status keyword Result is bandwidth of each PFM channel in MHz
Read DM from the parfile if COHERENT_FOLD mode, otherwise keep the user-set value.
Calculate the DS_FREQ status keyword. This is used only when an observer wants to reduce the number of channels in software, while using a higher number of hardware channels in SEARCH or COHERENT_SEARCH modes.
Calculates the number of channels received by this node. This is always the total number of channels divided by the number of nodes for coherent modes.
The band is divided amoung the various nodes like so:
^ ^^ ^^ ctr freq ^^
| || || ^ ||
+-------++-------++-----------------++--------- ...
c0 c1 c2 c3
So to mark each node’s ctr freq c0...cn:
where:
Calculates the number of polarizations to be recorded. Most cases it is all four, except in FAST4K, or when the user has indicated they only want 1 stokes product)
Randy/Jason indicated that the new guppi designs will have 12 taps in all modes.
Calculates the POL_TYPE status keyword. This is always AABBCRCI for coherent modes.
fft_size_params(rf,bw,nchan,dm,max_databuf_mb=128):
Returns a tuple of size parameters (fftlen, overlap, blocsize) given the input rf (center of band) in MHz, bw, nchan, DM, and optional max databuf size in MB.
Tells DAQ program to enter monitor mode.
This function overrides the base class Backend net_config for a CoDD backend. If the CoDD backend is master, it will program the roach for output on 8 adapters, as configured in the config file.
Returns the current state of a scan, as a tuple: (scan_running (bool), ‘NETSTAT=’ (string), and ‘DISKSTAT=’ (string))
Sets the FD_POLN (feed polarization) keyword in status memory and PSR FITS files. Legal values are ‘LIN’ (linear) or ‘CIRC’ (circular)
Sets the bandwidth in MHz. This value should match the valon output frequency. (The sampling rate being twice the valon frequency.)
For cal and fold modes, this sets the number of bins in a pulse profile. Ignored in other modes.
Sets the observing mode. Legal values for the currently selected mode are: COHERENT_SEARCH, COHERENT_FOLD, COHERENT_CAL, and RAW
Controls whether to ‘record only summed polarizations’ mode. Zero indicates that full stokes data should be recorded. One means to record only summed polarizations. This will be set to zero when using the ‘FAST4K’ observing mode.
Sets the hardware scaling factor for the p0 polarization. Range is 0.0 through 65535.99998.
Sets the hardware scaling factor for the p1 polarization. Range is 0.0 through 65535.99998.
Sets the software integration time per profile for all folding and cal modes. This is ignored in other modes.
–OR–
Sets up the system for a measurement and kicks it off at the appropriate time, based on ‘starttime’. If ‘starttime’ is not on a PPS boundary it is bumped up to the next PPS boundary. If ‘starttime’ is not given, the earliest possible start time is used.
start() will require a needed arm delay time, which is specified in every mode section of the configuration file as ‘needed_arm_delay’. During this delay it tells the HPC program to start its net, accum and disk threads, and waits for the HPC program to report that it is receiving data. It then calculates the time it needs to sleep until just after the penultimate PPS signal. At that time it wakes up and arms the ROACH. The ROACH should then send the initial packet at that time.
Stops a scan.
A class which implements some of the VEGAS specific parameter calculations.
VegasBackend(theBank, theMode, theRoach = None, theValon = None)
Where:
Computes the actual exposure, based on the requested integration time. If the number of switching phases is > 1, then the actual exposure will be an integer multiple of the switching period. If the number of switching phases is == 1, then the exposure will be an integer multiple of hwexposr.
Computes the FPGA clock.
External CAL
cals is a list of integers where 1 indicates the external cal is ON 0 indicates the external cal is OFF
External Sig/Ref 1
sr is a list of integers where 1 indicates REF 0 indicates SIG
External Sig/Ref 2
sr is a list of integers where 1 indicates REF 0 indicates SIG
Internal CAL
cals is a list of integers where 1 indicates the external cal is ON 0 indicates the external cal is OFF
Internal Sig/Ref 1
sr is a list of integers where 1 indicates REF 0 indicates SIG
Internal Sig/Ref 2
sr is a list of integers where 1 indicates REF 0 indicates SIG
add_switching_state(duration, blank, cal, sig_ref_1):
Add a description of one switching phase. Where:
Example to set up a 8 phase signal (4-phase if blanking is not considered) with blanking, cal, and sig/ref, total of 400 mS:
be = Backend(None) # no real backend needed for example
be.clear_switching_states()
be.add_switching_state(0.01, blank = True, cal = True, sig_ref_1 = True)
be.add_switching_state(0.09, blank = False, cal = True, sig_ref_1 = True)
be.add_switching_state(0.01, blank = True, cal = True, sig_ref_1 = False)
be.add_switching_state(0.09, blank = False, cal = True, sig_ref_1 = False)
be.add_switching_state(0.01, blank = True, cal = False, sig_ref_1 = True)
be.add_switching_state(0.09, blank = False, cal = False, sig_ref_1 = True)
be.add_switching_state(0.01, blank = True, cal = False, sig_ref_1 = False)
be.add_switching_state(0.09, blank = False, cal = False, sig_ref_1 = False)
This explicitly cleans up any child processes. This will be called by the player before deleting the backend object.
Returns the spec_tick value for this backend (the HBW value)
Opens the named pipe to the fits_writer_cmd program, sends ‘cmd’, and closes the pipe. Takes care not to block on an unconnected fifo.
Tells DAQ program to enter monitor mode.
For some BOF’s there is a status register which can flag an error state.
This command writes calculated values to the hardware and status memory. This command should be run prior to the first scan to properly setup the hardware.
The sequence of commands to set up a measurement is thus typically:
be.set_param(...)
be.set_param(...)
...
be.set_param(...)
be.prepare()
Returns the current state of a scan, as a tuple: (scan_running (bool), ‘NETSTAT=’ (string), and ‘DISKSTAT=’ (string))
Sets the hwexposr value, usually the value is set from the dibas.conf configuration file. Also sets the acc_len, which falls out of the computation to ensure hwexposure is an even multiple of spec_ticks (that multiple is acc_len).
Sets the number of channels used by this mode. This is bof specific, and should match the requirements of the bof.
set_gbt_ss(period, ss_list):
adds a complete GBT style switching signal description.
Example:
b.set_gbt_ss(period = 0.1,
ss_list = ((0.0, SWbits.SIG, SWbits.CALON, 0.025),
(0.25, SWbits.SIG, SWbits.CALOFF, 0.025),
(0.5, SWbits.REF, SWbits.CALON, 0.025),
(0.75, SWbits.REF, SWbits.CALOFF, 0.025))
)
starttime: a datetime object, representing a UTC start time.
–OR–
starttime: a tuple or list(for ease of JSON serialization) of datetime compatible values: (year, month, day, hour, minute, second, microsecond), UTC.
Sets up the system for a measurement and kicks it off at the appropriate time, based on starttime. If starttime is not on a PPS boundary it is bumped up to the next PPS boundary. If starttime is not given, the earliest possible start time is used.
start() will require a needed arm delay time, which is specified in every mode section of the configuration file as needed_arm_delay. During this delay it tells the HPC program to start its net, accum and disk threads, and waits for the HPC program to report that it is receiving data. It then calculates the time it needs to sleep until just after the penultimate PPS signal. At that time it wakes up and arms the ROACH. The ROACH should then send the initial packet at that time.
If this function cannot start the measurement by starttime, an exception is thrown.
A class which implements the VEGAS HBW mode specific functionality, and which communicates with the roach and with the HPC programs via shared memory.
VegasHBWBackend(theBank, theMode, theRoach = None, theValon = None)
Where:
This command writes calculated values to the hardware and status memory. This command should be run prior to the first scan to properly setup the hardware.
The sequence of commands to set up a measurement is thus typically:
be.set_param(...)
be.set_param(...)
...
be.set_param(...)
be.prepare()
A class which implements the VEGAS LBW-specific parameter calculations.
VegasLBWBackend(theBank, theMode, theRoach = None, theValon = None)
Where:
When resources change (e.g. number of channels, subbands, etc.) We clear the initialize indicator and tell the HPC to reallocate resources.
add_switching_state(duration, blank, cal, sig_ref_1):
Add a description of one switching phase. The LBW modes require computing the length in spec_ticks for blanking phases differntly from other phases. This function takes care of this.
Example to set up a 8 phase signal (4-phase if blanking is not considered) with blanking, cal, and sig/ref, total of 400 mS:
be = Backend(None) # no real backend needed for example
be.clear_switching_states()
be.add_switching_state(0.01, blank = True, cal = True, sig_ref_1 = True)
be.add_switching_state(0.09, blank = False, cal = True, sig_ref_1 = True)
be.add_switching_state(0.01, blank = True, cal = True, sig_ref_1 = False)
be.add_switching_state(0.09, blank = False, cal = True, sig_ref_1 = False)
be.add_switching_state(0.01, blank = True, cal = False, sig_ref_1 = True)
be.add_switching_state(0.09, blank = False, cal = False, sig_ref_1 = True)
be.add_switching_state(0.01, blank = True, cal = False, sig_ref_1 = False)
be.add_switching_state(0.09, blank = False, cal = False, sig_ref_1 = False)
Sets the gain to a new value.
assumed to be the first element of the ‘gain’ property. This works for all modes, but you should be aware that for modes 20-29 you need 8 gain elements. In that case ‘gain’ should be a list with 8 gain values.
A class which implements the VEGAS L1LBW1-specific parameter calculations.
VegasL1LBWBackend(theBank, theMode, theRoach = None, theValon = None)
Where:
This command writes calculated values to the hardware and status memory. This command should be run prior to the first scan to properly setup the hardware.
The sequence of commands to set up a measurement is thus typically:
be.set_param(...)
be.set_param(...)
...
be.set_param(...)
be.prepare()
A class which implements some of the VEGAS specific parameter calculations for the L8LBW1 and L8LBW8 modes.
VegasL8LBWBackend(theBank, theMode, theRoach = None, theValon = None)
Where:
Do the quantization gain calculation and append the result to the register dictionary
This is a calculated non-user-settable parameter, which specifies the length of the LO bram tables. For now this should be the bram_size - 2 i.e. (1<<10) - 2 In the 8 subwindow mode, all mixer_cnt registers are set, in the 1 subwindow mode, only the first mixer_cnt register is set.
Sets the mode_sel register based on the number of subbands Zero specifies 8 band mode, 1 specifies 1 band mode
Selects the Number of subbands. Legal values are 1 or 8. NOTE: This should not be a user parameter, better to have it specified by config file/mode.
A list specifying the frequencies for each subband for a given bank. Should probably check to verify len(subbandfreq) is consistent with current mode.
Update status memory keywords. Calls the base class version first to get a dictionary with the default base class values set, then adds/modifies kvpairs specific to this mode, and finally writes the data to shared memory.
This command writes calculated values to the hardware and status memory. This command should be run prior to the first scan to properly setup the hardware.
The sequence of commands to set up a measurement is thus typically:
be.set_param(...)
be.set_param(...)
...
be.set_param(...)
be.prepare()
[strategy] | Design Patterns by Erich Gamma et al. |