The Quatro6x Multiprocessor Platform
3.4 Interprocessor Interaction
Much description given in this section is taken from [19], [11], and [32]. On the Quatro6x DSP board, each of the four DSP processors has FIFOLink connected to another onboard processor. The FIFOLinks are compatible with the DMA controller for high-performance interprocessor data flow. Both FIFOPort and FIFOLink have several modes that can be used: single word, full words by DMA and almost full mode. In this section, we introduce the way to use FIFOLink and DMA functions for communication between two processors.
3.4.1 FIFOLink Functions
Fig. 3.4 shows the details of a single FIFOLink interface connection and its attendant control and status signals. Each FIFOLink includes a 512-element × 32-bit bidirectional buffer with full level and interrupt control on data transmission and reception. In this
subsection, we describe some important functions used in FIFOLink. Before using FIFO (both the FIFOLink and the FIFOPort), there are some important things to do:
• Include the header file “periph.h.”
• Declare the variables used by FIFO as global variables.
FIFOLink reset
The receive FIFO may be cleared and its condition reset at any time by using the function:
reset fifo link(cpu), cpu ∈ 0, 1, 2, 3.
FIFOLink status
The current fullness of a given link may be determined by reading the status port. The low-order six bits of the status port shows the status of Full, Empty, and Almost Full from each device. The FIFO status is defined in Table 3.1. We can use the following function to get the status:
get fifo link status(cpu), cpu ∈ 0, 1, 2, 3.
FIFOLink data transfer functions using CPU
Data may be moved between memory blocks and each of the FIFOLinks using the func-tions listed in Table 3.2. These routines are coded as inline funcfunc-tions for speed. The address of FIFOLinks is defined as Periph->FLink[fifo link(cpu)]. For example, when we want to transmit a single word “a” to other CPUs through FIFOLink buffer, the used instruction as follows,
Periph->FLink[fifo link(cpu)]=a; // cpu ∈ 0, 1, 2, 3.
It’s same as fifo link split(cpu,a). If we check FIFOLink status before the transfer, that is, while(!(get fifo link status(cpu)&Tx FIFO EMPTY);
Periph->FLink[fifo link(cpu)]=a;
Table 3.1: FIFO Status Definition [19]
C #define Bits # Condition
Rx FIFO FULL 0 Receive FIFO contains 512 elements Rx FIFO EMPTY 1 Receive FIFO contains 0 elements
Rx FIFO AF 2 Receive FIFO contains more elements than pro-programmed threshold Tx FIFO FULL 3 Transmit FIFO contains 512 elements
Tx FIFO EMPTY 4 Transmit FIFO contains 0 elements
Tx FIFO AF 5 Transmit FIFO contains more elements than pro-programmed threshold
Table 3.2: FIFOLink Data Transfer Functions Using CPU [19]
C Function Description
fifo link spit(cpu,a) Write a single word to the transmit FIFO using CPU without handshaking fifo link emit(cpu,a) Write a single word to the transmit FIFO using CPU with handshaking fifo link eat(cpu) Read a single word from the receive FIFO using CPU without handshaking fifo link key(cpu) Read a single word from the receive FIFO using CPU with handshaking
fill fifo link() Write up to 512 elements from a memory buffer into the transmit FIFO using CPU bleed fifo link() Read up to 512 elements from receive FIFO into memory buffer using CPU
This is single word transfer with handshaking, and same as fifo link emit(cpu,a). Similar examples can be found in II recommended example program, TEST and TEST2.
3.4.2 DMA Transfer Functions
The DMA controller transfers data between regions in the memory map without interven-tion by the CPU. It has four independent programmable channels, allowing four different contexts for DMA operation. The DMA channels may be used to transfer data between any of the FIFOLinks and a memory buffer using the inline functions in Table 3.3. The call sequences are:
dma mem to port(int channel, int* src, int* dest, int count, int block), dma port to mem(int channel, int* src, int* dest, int count, int block), dma copy mem(int channel, int* src, int* dest, int count, int block).
For instance, the function dma copy mem(int channel, int* src, int* dest, int count, int block) copies “count” words of memory from the source buffer “src” to the destination
Table 3.3: DMA Data Transfer Functions [19]
C Function Description
dma port to mem() Read up to 65536 words from a FIFO at indicated address into a memory buffer using specified DMA channel
dma mem to port() Write up to 65536 words from a memory buffer into a FIFO using specified DMA channel
dma copy mem() Copies up to 65536 words between internal memory and external memory using specified DMA channel channel
Fig. 3.5: Code for using DMA through FIFOLink (from [32]).
buffer “dest.” This function utilizes the specified DMA channel to perform the move. If
“block” is true, the function waits until the move is completed before processing; other-wise execution continues immediately after the DMA operation starts. We give an exam-ple of using DMA through FIFOLink buffer with full level in Fig. 3.5. More details will be discussed in chapter 4.
Fig. 3.6: Transmission mechanism in the existing simulator (from [32]).
3.4.3 Transmission Mechanism [32]
Fig. 3.6 shows the transmission mechanism of the existing simulator [32]. When we ini-tialize the DSP, the SNR, initial value of scrambling codes and channel case will be set in the controller PC and downloaded to CPU0. We use FIFOLink single mode transmission to transmit the information to the modulator in CPU1. The input to modulator from the last board is received using FIFOPort almost full mode. We pass the output to the next processor after finishing one slot. The FIFOLink can transmit 512 × 32 bits of integer per time in full condition. During the process, a stop signal will be transmitted through all processors. The stop command is given by the first processor or the host PC. We use single word mode to pass the signal in FIFO.
Table 3.4: Unlucky Style
noise.h & channel.c data.h & modulation.c CCS MPO 1 short noisereal[298801]={...}; unsigned short input[330]={...}; Can Can
short noiseim[298801]={...}; index=count*10; Run Not j=(slot*10240+...)%298801; j=(input[330+count]...; Order Begin 2 short noisereal[11]={...}; unsigned short input[330]={...}; Can Can
short noiseim[11]={...}; index=count*10; Run Not
j=(slot*10240+...)%11; j=(input[330+count]...; Finish