The Scalable System Port (SSP) Stub is a verification tool intended to help simulate and verify an algorithm designed for a RASC Field Programmable Gate Array (FPGA). This tool has been created to assist in initial testing and debugging of an algorithm in simulation prior to loading the algorithm onto the FPGA. Used with VCS/Virsim, the Stub allows the user to simulate sending/receiving SSP packets to/from the RASC FPGA to transfer data, start and stop the algorithm, and check status. This appendix covers the following topics:
Related and recommended documents include the following:
VCS User Guide
GNU Make Manual (or equivalent text on the Make utility)
The VCS User Guide and GNU Make Manual are available through the world-wide web.
Provided with the SSP Stub is a verification environment and sample testbench. This consists of the files which make up the SSP Stub as well as supporting files located in a directory tree. The directory tree, testbench, and sample tests are intended to help you quickly gain proficiency in creating tests for a specific algorithm. This section covers the following topics:
The SSP Stub is intended for use on Verilog designs and is customized for use with the VCS/Virsim simulator. To insure that SSP Stub and sample testbench function properly, the following environment variables must be set to the correct directories:
VCS_HOME (your_vcs_install_directory)
VCSPLIDIR $VCS_HOME/gui/virsim/linux/vcdplus/vcs (your_vcs_version)
PATH $PATH\:$VCS_HOME/bin
The SSP Stub consists of Verilog modules as well as PLI calls to functions written in C code. The stub is instantiated in a sample Verilog testbench along with the RASC FPGA. The C-code and top-level stub modules are located in the your_root/dv/sample_tb directory. Here, your_root is the installation directory of the RASC Core Services design and verification tree. The RASC Core Services modules are located in the design branch of the tree under the your_root/design directory. The algorithm being tested must be created in the design branch of the tree, located in the directory your_root/design/alg_core/alg_name. See existing sample algorithms for exact file locations. The sample test bench relies on the algorithm to be in this location for compiling.
The primary Verilog modules in the SSP Stub and other files are listed below. They can be found in the sample_tb directory.
top.v: Top level of the Sample Test Bench containing the SSP Stub, Algorithm FPGA, clock generator, and SRAM instances. Note that there are five physical SRAM instances in top.v while there are three logical SRAMs. The SRAMs are used in pairs to form a single logical SRAM. This structure mirrors the real hardware.
ssp_stub.v: Top level Verilog of the SSP Stub which passes signals to and from conversion modules.
init_sram0_good_parity.dat, init_sram2_good_parity.dat, init_sram1_good_parity.dat, init_sram3_good_parity.dat, and init_sram3_good_parity.dat: These SRAM initialization files contain data which is automatically loaded into the respective SRAM simulation models at the beginning of simulation. The data is in a format which the SRAM simulation model uses (one bit of parity per byte of data is shifted in with the data). These default files can be overridden by the user on the command line at runtime.
final_sram0.dat, final_sram1.dat, final_sram2.dat, final_sram3.dat, and final_sram4.dat:These files contain data extracted from the respective SRAM simulation models at the end of simulation. These default files can be overridden by the user on the command line at runtime.
timescale.v: This file contains the Verilog timescale of each of the components of the SSP Stub, as well as the algorithm FPGA design files. It is required that the algorithm being simulated makes use of the same timescale as the rest of the design.
For simulation, the Verilog timescale of each of the components of the SSP Stub, as well as the RASC FPGA design files, is set by the timescale.v file in the sample_tb directory. It is required that the algorithm being simulated makes use of the same timescale as the rest of the design.
The SSP Stub consists of the following files:
ssp_stub.v: Top level Verilog of the SSP Stub which passes signals to and from conversion modules.
cx_stub_ssr.v: A component of the SSP Stub which converts the raw 64-bit Double Data Rate (DDR) flits from the SSP link into 128-bit Single Data Rate (SDR) flits for use in the stub.
ssp_rcv_recap.v: A component of the SSP Stub which captures data (from cx_stub_ssr.v) on rising edge.
cx_stub_ssd.v: A component of the SSP Stub which converts the 128-bit SDR data from the stub to 64-bit DDR data for transmitting over the SSP link.
ssp_sdr_stub.v: A component of the SSP Stub which passes 128-bit data to and from C-code.
tio_shrd_ecc_generate.v: A component of the SSP Stubh which generates ECC bits in accordance with SSP protocol.
pli.tab: This PLI file links the $start_ssp call from the Verilog to the start_ssp() routine in C code.
start_ssp.c: This file directs the initialization of the stub. It opens the diag file, parses the commands, sets up the packet queues, initializes counters, and calls send_rcv_flits() to enter the main loop.
user_const.h: A header file containing user specified constants (e.g. simulation timeout, maximum size of the input file, maximum number of commands). Additional constants may be added to this file as needed by the user.
ssp_defines.h: This header file contains macros for the program, such as the names of packet types.
send_rcv_flits.h: This header file contains the main loop function, send_rcv_flits(), which calls itself once every clock cycle through the tf_setdelay(5) PLI call [tf_setdelay(time) waits for the specified amount of time, then calls misctf with input "reason_reactivate"; in the pli.tab file, the misc function is specified to be sent to "send_rcv_flits"]. send_rcv_flits() runs through the various conditions for sending, receiving, timing out, printing, delaying, and polling. It uses the function process_pkt to get information about error packets (in the syntax used for the input diag file) and the function get_fields to get a breakdown of the command word for logging purposes. It uses the sub-functions send_flit(), rcv_flit(), snd_poll(), and rcv_poll() to place data on the outgoing lines and read data off of the incoming lines. It calls finish_ssp() to print success and exit. send_flit() puts data for the next flit on the outgoing lines. rcv_flit() takes data from the incoming lines and stores it after comparing it with expected data. snd_poll() sends out a PIO 8-Byte Read Request packet for a given address. rcv_poll() takes the read response to a poll request, and checks the bit in question to see if it has been set.
queue_pkt.h: This file contains the mechanism for reading an input command line from the diag and converting it into data values representing the packet that will need to be sent/received OR the information for a print/delay/poll. queue_pkt(string) goes to tokenizes the input string and extracts data from each field. q_string_it(token, pkt_string) appends the latest token to the stored packet string (for logging purposes). strtok_checked(s1, s2) calls strtok on the inputs and throws an error if the resulting token is NULL when it should not be.
setup_pkt.h: This file contains the function setup_pkt(snd_rcv), which takes care of setting up packets for regular sends and receives (not poll packets), based on the information stored by queue_pkt(string). It uses the functions in snd_rcv_fns.h to get the data for each flit, and sets up the remaining fields individually (head, tail, error, req_dval, rsp_dval).
snd_rcv_fns.h: This file contains the equivalent of the eleven packet functions available to the diag, but with an extra field for the pkt[] array which will contain their results. Each function passes the appropriate type and fields to the construct_pkt(type, tnum, addr, data, error, pkt, snd_rcv_n) function.
construct_pkt.h: This file takes the packet information from snd_rcv_fns.h and turns it into 64-bit segments of data. construct_pkt(type, tnum, address, data, error, pkt, to_from_n) takes the input information and creates appropriate data, storing this data in pkt. pkt_size(type) takes the type and returns a value for the number of flits in that packet (1, 2, 9, or 10).
make_command.h: This file takes the type, transaction number, error bit, and direction of a packet and constructs an SSP command word, which it returns as an int.
get_fields.h: This file takes input of the type of packet to deconstruct (i.e., send, receive, incoming, poll request, poll response, poll expected) and returns the command word with its decomposed fields as well as any address or data fields. It also contains a helper function, f_string_it(token), which appends information to its destination string (data_fields[]) as it proceeds.
process_pkt.h: This file takes the type of packet (either incoming or poll response) and turns the data from that receive packet into a string following the syntax of the diag file. It has a helper function p_string_it(token) that behaves the same as f_string_it(token), but stores its data in processed_string[].
Compiling the sample testbench is done using the provided Makefile. In order to compile the sample testbench including the SSP Stub and the RASC Core Services logic, an algorithm must be specified. This algorithm is specified to the make utility on the command line, (change directory to the sample_tb directory and enter the following command) as follows:
% cd your_root/dv/sample_tb % make ALG=your_algorithm |
The Makefile uses your_algorithm to find the directory in the tree where you algorithm design files exist (for example, ALG=alg0). For the case where no ALG=your_algorithm is specified, the default algorithm is used from your_root/examples/alg_simple_v. As mentioned ealier, it is required that user generated algorithms are saved in a corresponding directory (for example,. your_root/examples/my_alg/*.v).
To run a test, remain in the sample_tb directory and enter the following command:
% make run DIAG=diag_filename ALG=your_algorithm SRAM0_IN=sram0_input_filename SRAM1_IN=sram1_input_filename SRAM2_IN=sram2_input_filename SRAM3_IN=sram3_input_filename SRAM0_OUT=sram0_output_filename SRAM1_OUT=sram1_output_filename SRAM2_OUT=sram2_output_filename SRAM3_OUT=sram3_output_filename |
The diag_filename specifies the diag to be run and should be relative to the current directory. Again, the algorithm must be specified using the ALG=your_algorithm command line option. If none is specified, the runtime command uses same default as above . The ALG option allows the user to reuse the same diag for multiple algorithms. The input and output data files for the three SRAMs may be specified; if they are not specified, they default to:
SRAM0_IN=init_sram0_good_parity.dat SRAM1_IN=init_sram1_good_parity.dat SRAM2_IN=init_sram2_good_parity.dat SRAM3_IN=init_sram3_good_parity.dat SRAM4_IN=init_sram4_good_parity.dat SRAM0_OUT=final_sram0.dat SRAM1_OUT=final_sram1.dat SRAM2_OUT=final_sram2.dat SRAM3_OUT=final_sram3.dat SRAM4_OUT=final_sram4.dat |
As the test runs, it will output status to the screen and to an output file named diag_filename.your_algorithm.run.log. This log file will appear in the same directory that the diagnostic is located in. The contents of each SRAM at the end of simulation will be dumped into .dat files which can be either the default filenames or user-specified. Each time a diagnostic is run, the file vcdplus.vpd is generated in the sample_tb directory. This file can be input to Virsim for viewing the waveform. Since the file vcdplus.vpd is generally large, it is overwritten for each diagnostic run. To save the waveform for a given diagnostic, copy corresponding vcdplus.vpd file to a new name.
To view the waveform saved in the vcdplus.vpd file, use the following command:
% vcs -RPP vcdplus.vpd |
When the stub receives an incorrect packet, it will output, in order, the following information: the command for the next expected packet, SSP fields of the expected packet, the command translation (if one exists) for the received packet, and the SSP fields of the received packet.
The Stub retrieves instructions from a test through a text input file, the diagnostic. The SSP Stub parses this file at each semicolon to extract commands which the Stub executes. Many of the allowed commands in a diagnostic correspond to SSP packets. The SSP Stub supports other commands that are used for diagnostic writing and debugging. The primary components of the diagnostic file are, packet commands, other commands, and comments.
It is important to note that most SSP packets come in pairs, a request and a response. For these types of packets, the request command and response command must be listed sequentially in a diagnostic. This method of keeping requests and response paired is used by the stub to associate request and response packets with the corresponding tnums. Also, when running the DMA engines, all transactions related to that sequence of events should be grouped together. See the sample diagnostic included later in this document for an example of how this is done.
RASC makes use of a subset of the available SSP packet types. The packet types used by the SSP Stub are included in the table below.
Table B-1. Packet Types used by SSP
Type | Transaction | Valid
Transactions | Valid
Transactions |
|---|---|---|---|
Reads | PIO 8-Byte Read | Yes | No |
| PIO Partial 128-Byte Read | Yes | No |
| Memory Full 128-Byte Read | No | Yes |
Writes | PIO 8-Byte Write | Yes | Yes |
| PIO Partial 128-Byte Write | Yes | No |
| Memory Full 128-Byte Write | No | Yes |
Invalidate-Cache Flush | Invalidate-Cache Flush | Yes | No |
Of the standard SSP packet types listed in the SSP Specification, this stub does NOT support FPGA-to-Stub Processor Input/Output (PIO) 8-Byte Reads, FPGA-to-Stub Memory Partial 128-Byte Writes, FPGA-to-Stub PIO Partial 128-Byte Reads or Writes, or Graphics Writes. It does, however, support all SSP packets that are used or accepted by the RASC Core Services.
Packet commands begin with the name “snd_” or “rcv_”, contain fields within parentheses separated by commas, and end with a semicolon, for example:
snd_wr_req(PIO, DW, ANY, 0x0000000000000000, 0x000000000000FFFF); |
There are two categories of stub commands: sends and receives. The diagnostic should specify both the requests and responses it wishes to send as well as the requests and responses it expects to receive from the FPGA.
Below is a list of the various fields used by packet commands. A list of allowable values and their corresponding meanings is also included.
Field: PIO/MEM
PIO (Processor Input/Output): Use for read/write requests initiated by the stub, also used for interrupt packets from the FPGA.
MEM (Memory): Use for read/write requests initiated by the FPGA (except interrupts).
Field: Size
DW (Double Word): Use for 8-Byte transactions (MMRs and Interrupts)
FCL (Full Cache-Line): Use for Full 128-Byte transactions (usually DMA's).
Field: Tnum
0x0 - 0xff: Correspond to the tnum of a packet.
ANY: Used when any tnum is allowable or when responding with the tnum of the corresponding request.
For outgoing requests, the tnum may be specified (though overlapping tnums for the same type of transactions should not be used per the SSP Specifiation). If “ANY” is specified for an outgoing request, the Stub will assign a tnum automatically. For incoming responses, the tnum may be specified if the tnum of the corresponding request was specified; in all other cases, specifying “ANY” will allow the stub to accept any tnum for the incoming packet.
Also, note that the RASC FPGA will send out PIO Write Requests to the stub with tnums always in the range 0xf0 - 0xff. The RASC FPGA should not use tnums in this range for any other purpose.
Field: Address
Any 64-bit value: Used to specifiy the intended or expected address of a packet (note that actual addresses are 56-bit values). For all requests, this field specifies the SRAM, MMR, or Memory address location.
Field: Data
A list of 64-bit values, dependent on the size specified. Each 64-bit data segment (from least-significant to most-significant) is separated by a comma. For DWs, there is just one data segment. For FCLs, there are 16 segments. The sample diagnostic included later in this document contains examples.
Field: Error
0: No error is reported in the header of the SSP packet.
1: An error is reported/expected in the corresponding packet.
The error field is required for all responses, whether received or sent. The error bit is one when there has been some error in the transaction; for example, the type of request may not be valid or the address may be invalid.
snd_wr_req
The syntax of the snd_wr_req function is, as follows:
snd_wr_req(pio_mem_n, size, tnum, addr, data): |
The snd_wr_req function is used to send PIO writes to the memory-mapped registers (MMRs) (8-Byte).
pio_mem_n = PIO
size = DW
tnum = ANY or user-specified
addr = address of MMR or in SRAM
data = data to be written
snd_rd_req
The syntax of the snd_rd_req function is, as follows:
snd_rd_req(pio_mem_n, size, tnum, addr): |
The snd_rd_req function is used to request PIO reads from the MMRs (8-Byte) and SRAMs (Full 128-Byte).
pio_mem_n = PIO
size = DW or FCL
tnum = ANY or user-specified
addr = address of MMR or in SRAM
snd_wr_rsp
The syntax of the snd_wr_rsp function is, as follows:
snd_wr_rsp(pio_mem_n, size, tnum, error): |
The snd_wr_rsp function is used to respond to write requests from the FPGA during DMAs (Full 128-Byte) and interrupts (8-Byte).
pio_mem_n = PIO (interrupts) or MEM (DMAs)
size = DW (interrupts) or FCL (DMAs)
tnum = ANY or user-specified
error = 0 or 1
snd_rd_rsp
The syntax of the snd_rd_rsp function is, as follows:
snd_rd_rsp(pio_mem_n, size, tnum, error, data): |
The snd_rd_rsp function is used to respond to read requests from the FPGA: DMAs (Full 128-Byte).
pio_mem_n = MEM
size = FCL
tnum = ANY or user-specified
error = 0 or 1
data = 0 if this is an error response, otherwise a list of 16 64-bit data values, separated by commas.
tnum = ANY or user-specified
inv_flush
The syntax of the inv_flush function is, as follows:
inv_flush(tnum): |
tnum = ANY or user-specified
rcv_wr_rsp
The syntax of the rcv_wr_rsp function is, as follows:
rcv_wr_rsp(pio_mem_n, size, tnum, error): |
The rcv_wr_rsp function is used to receive write responses from the FPGA (after writes to MMRs).
pio_mem_n = PIO
size = DW
tnum = ANY or user-specified
error = 0 or 1
rcv_rd_rsp
The syntax of the rcv_rd_rsp function is, as follows:
rcv_rd_rsp(pio_mem_n, size, tnum, error, data): |
The rcv_rd_rsp function is used to receive read responses from the FPGA (after read requests to the MMRs).
pio_mem_n = PIO
size = DW
tnum = ANY or user-specified
error = 0 or 1
data = 0 if an error response, one 64-bit value otherwise
rcv_wr_req
The syntax of the rcv_wr_req function is, as follows:
rcv_wr_req(pio_mem_n, size, tnum, addr, data): |
The rcv_wr_req function is used to receive write request from the FPGA (interrupts and DMA writes).
pio_mem_n = PIO (interrupts) or MEM (DMAs)
size = DW (interrupts) or FCL (DMAs)
tnum = ANY or user-specified
addr = address specified for interrupts or system memory address (64-bits)
data = one 64-bit value for interrupts; 16 64-bit values for DMAs
rcv_rd_req
The syntax of the rcv_rd_req function is, as follows:
rcv_rd_req(pio_mem_n, size, tnum, addr): |
The rcv_rd_req function is used to receive read requests from the FPGA (DMA reads).
pio_mem_n = MEM
size = FCL
tnum = ANY or user-specified
addr = system memory address
print “text”; |
The user can output information from the diagnostic through the print command. These are indicated by the keyword “print” followed by the output text enclosed in quotation marks and followed by a semicolon:
print “Done initializing registers.\n”; |
The stub will output the characters in between the quotation marks verbatim, with three exceptions: `\n', `\t', and `\v' are treated as “newline,” “horizontal tab,” and “vertical tab,” respectively. The print command will execute immediately after the command above it is executed. The SSP Stub will not wait for a print command to be executed before proceeding with the rest of the diagnostic.
delay(cycles);
The user can specify a specific delay between sending packets. The value specified in the delay command is the number of 5 ns clock cycles to wait before continuing to execute commands in the diagnostic. This can be used to wait for the algorithm to execute steps or finish executing entirely.
poll(address, bit, interval);
The user can specify a bit to read at a specified interval to see if a process is finished (for example, if the algorithm, DMA read engine, or DMA write engine is complete). The stub will read the MMR of address on the specified interval until the bit is set to 1
| Note: NOTE: If the interval chosen is smaller than the time necessary to complete the read transaction (approximately 44 clock cycles), the stub will wait until it receives a response to its last request before proceeding with the next read request (that is, the actual time between reads may be greater than the specified interval). |
address = address of MMR to be read
bit = bit in register to be checked
interval = number of clock cyles in between register reads
The table below provides a summary of packet commands and their possible usages.
Command | Packet Type | PIO/ MEM | Size | Tnum | Error | Address | Data |
|---|---|---|---|---|---|---|---|
snd_wr_req | PIO 8-Byte | PIO | DW | User-specified or ANY | - | MMR or SRAM Address | 1 64-bit value |
snd_rd_req | PIO 8-Byte | PIO | DW | User-specified or ANY | - | MMR Address | - |
| Memory Full 128-Byte | MEM | FCL | User-specified or ANY | - | SRAM Address | - |
snd_wr_rsp | PIO 8-Byte | PIO | DW | User-specified or ANY | 0 or 1 | - | - |
| Memory Full 128-Byte | MEM | FCL | User-specified or ANY | 0 or 1 | - | - |
snd_rd_rsp | Memory Full 128-Byte | MEM | FCL | User-specified or ANY | 0 or 1 | - | 16 64-bit values |
inv_flush | Invalidate Cache-Flush Request | - | - | User-specified or ANY | - | - | - |
rcv_wr_rsp | PIO 8-Byte | PIO | DW | User-specified or ANY | 0 or 1 | - | - |
rcv_rd_rsp | PIO 8-Byte | PIO | DW | User-specified or ANY | 0 or 1 | - | 1 64-bit value |
rcv_wr_req | PIO 8-Byte | PIO | DW | User-specified or ANY | - | Interrupt Destination Address | 1 64-bit value |
| Memory 128-Byte | MEM | FCL | User-specified or ANY | - | System Memory Address | 16 64-bit values |
rcv_rd_req | Memory 128-Byte | MEM | FCL | User-specified or ANY | - | System Memory Address | - |
The code listed below comprises a diagnostic which exercises the basic functionality of the RASC FPGA outlined in the following steps:
Initializes the RASC FPGA Core Services (primarily MMR Writes)
Executes DMA Reads to send data to the FPGA
Starts the Algorithm (A & B | C) and polls the MMR's to see when the Algorithm is done
Executes DMA Writes to retrieve the Algorithm's results
Checks the error status in the MMR's to verify that no errors were flagged.
####### Initialization packets. ####### # Arm reigsters by setting the REARM_STAT_REGS bit in the CM_CONTROL register. snd_wr_req ( PIO, DW, ANY, 0x00000000000020, 0x0000000600f00003 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # Clear the CM_ERROR_STATUS register by writing all zeroes. snd_wr_req ( PIO, DW, 3, 0x00000000000060, 0x0000000000000000 ); rcv_wr_rsp ( PIO, DW, 3, 0); # Enable CM_ERROR_DETAIL_* regs by writing all zeroes to CM_ERROR_DETAIL_1. snd_wr_req ( PIO, DW, ANY, 0x00000000000010, 0x0000000000000000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # Enable desired interrupt notification in the CM_ERROR_INTERRUPT_ENABLE register. snd_wr_req ( PIO, DW, 4, 0x00000000000070, 0xFFFFFFFFFFFFFFFF ); rcv_wr_rsp ( PIO, DW, 4, 0 ); # Set up the Interrupt Destination Register. snd_wr_req ( PIO, DW, ANY, 0x00000000000038, 0x0000000000000000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); print "\n\n*******Initialization finished\n\n"; ####### Configure DMA Engines and Algorithm. ####### ####### Configure the Read DMA Engine Registers. ####### print "\n\n*******Configure Read DMA Engine. Tell it to fill 32 cache lines of data.\n\n"; # RD_DMA_CTRL register. snd_wr_req ( PIO, DW, ANY, 0x00000000000110, 0x0000000000100020 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # RD DMA System Address. snd_wr_req ( PIO, DW, ANY, 0x00000000000100, 0x0000000000100000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # RD DMA Local Address. snd_wr_req ( PIO, DW, ANY, 0x00000000000108, 0x0000000000000000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # RD_DMA_DEST_INT snd_wr_req ( PIO, DW, ANY, 0x00000000000120, 0x0000000200002000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); ####### Configure the Write DMA Engine Registers. ####### print "\n\n*******Configure Write DMA Engine.\n\n"; # Write to the WR_DMA_CTRL register. snd_wr_req ( PIO, DW, ANY, 0x00000000000210, 0x0000000000100020 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # WR_DMA_SYS_ADDR snd_wr_req ( PIO, DW, ANY, 0x00000000000200, 0x0000000000100000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # WR_DMA_LOC_ADDR snd_wr_req ( PIO, DW, ANY, 0x00000000000208, 0x0000000000000000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # WR_DMA_INT_DEST snd_wr_req ( PIO, DW, ANY, 0x00000000000220, 0x0000000400004000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); ####### Configure the Algorithm Registers. ####### print "\n\n*******Configure Algorithm Registers\n\n"; snd_wr_req ( PIO, DW, ANY, 0x00000000000300, 0x0000000000000000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); snd_wr_req ( PIO, DW, ANY, 0x00000000000308, 0x0000000600006000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); ####### Start Read DMA Engine for Read DMA 1 ####### print "\n\n*******Start Read DMA Engine for SRAM0\n\n"; # Set Bit 36 of the CM_CONTROL Reg to 1. snd_wr_req ( PIO, DW, ANY, 0x00000000000020, 0x0000001400f00003 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # 1 of 32 rcv_rd_req ( MEM, FCL, ANY, 0x00000000100000 ); snd_rd_rsp ( MEM, FCL, ANY, 0, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF ); # Other Read DMA Transactions omitted here # 32 of 32 rcv_rd_req ( MEM, FCL, ANY, 0x00000000100F80 ); snd_rd_rsp ( MEM, FCL, ANY, 0, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF ); print "\n\n*******Done storing 32 cache lines of data in SRAM0.\n\n"; print "\n\n*******Polling for DMA RD-SRAM0 done (bit 42 of CM_STATUS).\n\n"; poll (0x8, 42, 20); ####### Reconfigure DMA Engine for Read DMA 2 ####### # RD_DMA_SYS_ADDR snd_wr_req ( PIO, DW, ANY, 0x00000000000100, 0x0000000000100000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # RD_DMA_LOC_ADDR snd_wr_req ( PIO, DW, ANY, 0x00000000000108, 0x0000000000200000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); ####### Start Read DMA Engine for Read DMA 2 ####### print "\n\n*******Start Read DMA Engine for SRAM1\n\n"; # Set Bit 36 of the CM_CONTROL Reg to 1. snd_wr_req ( PIO, DW, ANY, 0x00000000000020, 0x0000001400f00003 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # 1 of 32 rcv_rd_req ( MEM, FCL, ANY, 0x00000000100000 ); snd_rd_rsp ( MEM, FCL, ANY, 0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0 ); # Other Read DMA Transactions omitted here # 32 of 32 rcv_rd_req ( MEM, FCL, ANY, 0x00000000100F80 ); snd_rd_rsp ( MEM, FCL, ANY, 0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0 ); print "\n\n*******Done storing 32 cache lines of data in SRAM1.\n\n"; print "\n\n*******Polling for DMA RD-SRAM1 done (bit 42 of CM_STATUS).\n\n"; poll (0x8, 42, 200); ####### Reconfigure DMA Engine for Read DMA 3 ####### # RD DMA addresses. snd_wr_req ( PIO, DW, ANY, 0x00000000000100, 0x0000000000100000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); snd_wr_req ( PIO, DW, ANY, 0x00000000000108, 0x0000000000400000 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); ####### Start Read DMA Engine for Read DMA 3 ####### print "\n\n*******Start Read DMA Engine for SRAM2\n\n"; # Set Bit 36 of the CM_CONTROL Reg to 1. snd_wr_req ( PIO, DW, ANY, 0x00000000000020, 0x0000001400f00003 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # 1 of 32 rcv_rd_req ( MEM, FCL, ANY, 0x00000000100000 ); snd_rd_rsp ( MEM, FCL, ANY, 0, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C ); # Other Read DMA Transactions omitted here # 32 of 32 rcv_rd_req ( MEM, FCL, ANY, 0x00000000100F80 ); snd_rd_rsp ( MEM, FCL, ANY, 0, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C, 0x0C0C0C0C0C0C0C0C ); print "\n\n*******Done storing 32 cache lines of data in SRAM 3.\n\n"; print "\n\n*******Polling for DMA RD-SRAM2 done (bit 42 of CM_STATUS).\n\n"; poll (0x8, 42, 200); ####### Start the Algorithm ####### # Set bit 38 of CM Control Register to 1 to start algorithm. snd_wr_req ( PIO, DW, ANY, 0x00000000000020, 0x0000004400f00003 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); print "\n\n*******Started Algorithm.\n\n"; # Poll for ALG_DONE bit in CM_STATUS. poll ( 0x8, 48, 200 ); ####### Start Write DMA Engine. ####### # Set bit 37 of CM Control Register to 1 to start Write DMA Engine. snd_wr_req ( PIO, DW, ANY, 0x00000000000020, 0x0000002400f00003 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); print "\n\n*******Started Write DMA Engine.\n\n"; # 1 of 32 rcv_wr_req ( MEM, FCL, ANY, 0x00000000100000, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC ); snd_wr_rsp ( MEM, FCL, ANY, 0 ); # Other Write DMA Transactions omitted here # 32 of 32 rcv_wr_req ( MEM, FCL, ANY, 0x00000000100F80, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC, 0xDCACBCECDCACBCEC ); snd_wr_rsp ( MEM, FCL, ANY, 0 ); print "\n\n*******Polling for DMA WR-SRAM0 done (bit 45 of CM_STATUS).\n\n"; poll (0x8, 45, 200); ####### Finish Up ###### # dma_clear(). Set bits 39, 40, and 41 to 1 in CM_CONTROL. snd_wr_req ( PIO, DW, ANY, 0x00000000000020, 0x0000038400f00003 ); rcv_wr_rsp ( PIO, DW, ANY, 0 ); # finalcheck_ccc() Check CACHE_RD_DMA_FSM. snd_rd_req ( PIO, DW, ANY, 0x00000000000130 ); rcv_rd_rsp ( PIO, DW, ANY, 0, 0x0000000000400000 ); print "Reading the Error Status Register to insure no errors were logged.\n"; snd_rd_req ( PIO, DW, ANY, 0x00000000000060 ); rcv_rd_rsp ( PIO, DW, ANY, 0, 0x0000000000000000 ); |
Because the SSP Stub is a very simple verification tool intended only for sandbox testing of new algorithm designs, capabilities and support for this stub are minimal. The main intent is to provide the user with a means to simulate loading data, running their algorithm, and reading the results. More comprehensive testing should be done on real hardware. Due to limitations of the stub, below are some guidelines/rules for writing a diagnostic which will help the user quickly create functional tests.
Commands in the stub MUST alternate between request and responses. This allows the stub to associate transaction pairs and calculate transaction numbers accordingly.
Comments operate as follows: when the stub encounters a `#' character, it ignores all text from that character until it reaches the end of that line. Print statements are an exception to this rule; if the stub encounters a `#' in between the quotation marks of a print statement, it does NOT recognize this as a comment.
A command should ALWAYS be followed by a semicolon.
The parser checks for the correct number of inputs to a function, but it does NOT check the validity of these inputs. Misplaced semicolons may also lead to unpredictable behavior.
Because the input file is in text format, no mathmatical operations, functions, or variables are available. The diagnostic writer must know the full data value to be written to a register.
Diagnostic files must ALWAYS end with a newline character.
Always follow a long sequence of DMA transactions with a poll() command of the WR_DMA_DONE bit or RD_DMA_DONE bit. Enabling Interrupts will help test for the completion of a long set of transactions.
Other typical errors include the following:
diagnostic is too long. If you are running into memory-related errors, try increasing the FILE_MAX or COMMAND_MAX constants in user_const.h (number of characters allowed in diagnostic file).
Timed out while waiting for an operation to complete. If you are timing out before you receive your algorithm or interrupt, increase TIME_OUT in user_const.h. If you are timing out during a poll, increase POLL_MAX in user_const.h.
Read the Error Status Register at the end of a diagnostic to insure that no unreported errors were logged during the diagnostic.