aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_replay/axis_replay.v157
-rw-r--r--fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_replay/rfnoc_block_replay_tb.sv107
2 files changed, 158 insertions, 106 deletions
diff --git a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_replay/axis_replay.v b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_replay/axis_replay.v
index c83de1fc1..e30ee81e2 100644
--- a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_replay/axis_replay.v
+++ b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_replay/axis_replay.v
@@ -281,7 +281,7 @@ module axis_replay #(
reg_play_cmd_time <= 0;
reg_play_words_per_pkt <= REG_PLAY_WORDS_PER_PKT_INIT;
reg_item_size <= DEFAULT_ITEM_SIZE;
- items_per_word <= 'bX;
+ items_per_word <= 'bX;
rec_restart <= 0;
play_cmd_stop <= 0;
clear_cmd_fifo <= 0;
@@ -576,7 +576,7 @@ module axis_replay #(
rec_restart_clear <= 1'b0;
// Update wait timer
- if (i_tvalid || !rec_fifo_occupied) begin
+ if ((i_tvalid && i_tready) || !rec_fifo_occupied) begin
// If a new word is presented to the input FIFO, or the FIFO is empty,
// then reset the timer.
rec_wait_timer <= 0;
@@ -943,78 +943,91 @@ module axis_replay #(
//
// This section monitors the signals to/from the memory interface and
// generates the TLAST and sideband signals. We assert TLAST at the end of
- // every read transaction and after every reg_play_words_per_pkt words, so
+ // every reg_play_words_per_pkt words and at the end of the last packet, so
// that no packets are longer than the length indicated by the
// REG_PLAY_WORDS_PER_PKT register.
//
- // The sideband signals consist of the timestamp, has_time flag, and eob
- // flag. These are generated by the playback logic for each memory
- // transaction.
+ // The sideband signals consist of the timestamp, has-time flag, and EOB (end
+ // of burst) flag. Timestamp and has_time are set for the first packet of
+ // each playback. EOB applies to each packet but is only set to 1 for the
+ // last packet of a playback.
//
- // The timing of this block relies on the fact that read_ctrl_ready is not
- // reasserted by the memory interface until after TLAST gets asserted.
+ // The timing of this section relies on the fact axi_dma_master doesn't allow
+ // overlapping read transactions. This means that the next read_ctrl_ready
+ // won't be asserted until after previous memory transaction finishes being
+ // read out.
//
//---------------------------------------------------------------------------
- reg [MEM_COUNT_W-1:0] read_counter;
- reg [ WPP_W-1:0] length_counter;
- reg [ TIME_W-1:0] time_counter;
- reg play_fifo_i_tlast;
- reg has_time;
- reg eob;
+ reg [MEM_COUNT_W-1:0] read_counter; // Track outstanding words to read
+ reg [ WPP_W-1:0] length_counter; // Track packet length
+ reg [ TIME_W-1:0] timestamp; // Timestamp for the current burst
+ reg has_time; // Is current burst timed?
+ reg eob; // End of burst
+ reg play_fifo_i_tlast; // End of packet
always @(posedge clk)
begin
- if (rst) begin
- play_fifo_i_tlast <= 1'b0;
- // Don't care:
- read_counter <= {MEM_COUNT_W{1'bX}};
- length_counter <= {MEM_COUNT_W+1{1'bX}};
- time_counter <= {TIME_W{1'bX}};
- has_time <= 1'bX;
- eob <= 1'bX;
- end else begin
- // Check if we're requesting a read transaction
- if (read_ctrl_valid && read_ctrl_ready) begin
- // Initialize read_counter for new transaction
- read_counter <= read_count;
- length_counter <= reg_play_words_per_pkt;
- time_counter <= cmd_time;
- has_time <= cmd_timed;
- eob <= last_trans && (read_count < reg_play_words_per_pkt);
+ // synthesis translate_off
+ //
+ // Check our assumption about non-overlapping read transactions.
+ if (read_ctrl_ready && play_fifo_i_tvalid) begin
+ $fatal(1, "New read transaction started before the previous one completed!");
+ end
+ // synthesis translate_on
- // If read_count is 0, then the first word is also the last word
- if (read_count == 0) begin
- play_fifo_i_tlast <= 1'b1;
- end
+ if (read_ctrl_valid && read_ctrl_ready) begin
+ read_counter <= read_count;
- // Track the number of words read out by memory interface
- end else if (read_data_valid && read_data_ready) begin
- read_counter <= read_counter - 1;
- length_counter <= length_counter - 1;
- time_counter <= time_counter + items_per_word;
-
- // Check if the word currently being output is the last word of a
- // packet, which means we need to clear tlast.
- if (play_fifo_i_tlast) begin
- // But make sure that the next word isn't also the last of a memory
- // burst, for which we will need to keep tlast asserted.
- if (read_counter != 1) begin
- play_fifo_i_tlast <= 1'b0;
- end
+ // If read_count is 0, then the next word is also the last word
+ if (read_count == 0) begin
+ play_fifo_i_tlast <= 1'b1;
+ eob <= last_trans;
+ end
+ end
- // Restart length counter
- length_counter <= reg_play_words_per_pkt;
+ if (play_fifo_i_tvalid && play_fifo_i_tready) begin
+ read_counter <= read_counter - 1;
+ length_counter <= length_counter - 1;
- // Check if next packet is the end of the burst (EOB)
- eob <= last_trans && (read_counter <= reg_play_words_per_pkt);
+ // Check if the current word is the last of the packet
+ if (play_fifo_i_tlast) begin
+ length_counter <= reg_play_words_per_pkt;
- // Check if the next word to be output should be the last of a packet.
- end else if (read_counter == 1 || length_counter == 2) begin
- play_fifo_i_tlast <= 1'b1;
+ // Clear tlast, unless the first word of the next packet is also the
+ // last word of the next packet.
+ if (!(last_trans && read_counter == 1)) begin
+ play_fifo_i_tlast <= 1'b0;
end
+
+ // The timestamp only applies to the first packet, so disable for
+ // subsequent packets.
+ has_time <= 1'b0;
end
+ // Check if the next word will be the last of the packet.
+ //
+ // First, check if the next word is the last word of playback, in which
+ // case it's both the last word of the packet and the end of the burst.
+ if (last_trans && read_counter == 1) begin
+ play_fifo_i_tlast <= 1'b1;
+ eob <= 1;
+
+ // Next, check if this is the last word of the packet according to packet
+ // length. But note that the next word won't be the last if we're already
+ // outputting the last word of a burst on the current cycle.
+ end else if (length_counter == 2 && !(eob && play_fifo_i_tlast)) begin
+ play_fifo_i_tlast <= 1'b1;
+ end
+ end
+
+ if (play_state == PLAY_IDLE) begin
+ // Reset signals for the next playback
+ length_counter <= reg_play_words_per_pkt;
+ timestamp <= cmd_time_cf;
+ has_time <= cmd_timed_cf;
+ eob <= 0;
+ play_fifo_i_tlast <= 1'b0;
end
end
@@ -1053,20 +1066,6 @@ module axis_replay #(
.occupied ()
);
- reg play_fifo_i_sop = 1'b1;
-
- // Make play_fifo_i_sop true whenever the next play_fifo_i word is the start
- // of a packet.
- always @(posedge clk) begin
- if (rst) begin
- play_fifo_i_sop <= 1'b1;
- end else begin
- if (play_fifo_i_tvalid & play_fifo_i_tready) begin
- play_fifo_i_sop <= play_fifo_i_tlast;
- end
- end
- end
-
//---------------------------------------------------------------------------
// Header Info FIFO
@@ -1080,6 +1079,7 @@ module axis_replay #(
wire [(TIME_W+2)-1:0] hdr_fifo_i_tdata;
wire hdr_fifo_i_tvalid;
wire [(TIME_W+2)-1:0] hdr_fifo_o_tdata;
+ wire hdr_fifo_o_tvalid;
wire hdr_fifo_o_tready;
wire [15:0] hdr_fifo_space;
@@ -1097,20 +1097,31 @@ module axis_replay #(
.i_tready (),
//
.o_tdata (hdr_fifo_o_tdata),
- .o_tvalid (),
+ .o_tvalid (hdr_fifo_o_tvalid),
.o_tready (hdr_fifo_o_tready),
//
.space (hdr_fifo_space),
.occupied ()
);
- assign hdr_fifo_i_tdata = {has_time, eob, time_counter};
+ // synthesis translate_off
+ //
+ // The FIFO code above assumes the header info will always be available when
+ // the last word of the payload FIFO is read out. Check that assumption here.
+ always @(posedge clk) begin
+ if (hdr_fifo_o_tready && !hdr_fifo_o_tvalid) begin
+ $fatal(1, "Header FIFO read without valid data!");
+ end
+ end
+ // synthesis translate_on
+
+ assign hdr_fifo_i_tdata = {has_time, eob, timestamp };
// Pop the timestamp whenever we finish reading out a data packet
assign hdr_fifo_o_tready = o_tvalid & o_tready & o_tlast;
// Write the timestamp at the start of each packet
- assign hdr_fifo_i_tvalid = play_fifo_i_tvalid & play_fifo_i_tready & play_fifo_i_sop;
+ assign hdr_fifo_i_tvalid = play_fifo_i_tvalid & play_fifo_i_tready & play_fifo_i_tlast;
assign { o_thas_time, o_teob, o_ttimestamp } = hdr_fifo_o_tdata;
diff --git a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_replay/rfnoc_block_replay_tb.sv b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_replay/rfnoc_block_replay_tb.sv
index 9a0d9c810..5674a3cf6 100644
--- a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_replay/rfnoc_block_replay_tb.sv
+++ b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_replay/rfnoc_block_replay_tb.sv
@@ -46,6 +46,8 @@ module rfnoc_block_replay_tb#(
`include "rfnoc_block_replay_regs.vh"
+ `define MIN(X,Y) ((X)<(Y)?(X):(Y))
+
//---------------------------------------------------------------------------
// Testbench Configuration
@@ -535,6 +537,8 @@ module rfnoc_block_replay_tb#(
"Buffer size extends beyond available memory");
`ASSERT_FATAL(spp * ITEM_SIZE % MEM_WORD_SIZE == 0,
"Requested SPP must be a multiple of the memory word size");
+ `ASSERT_FATAL(spp <= 2**MTU,
+ "Requested SPP exceeds MTU");
// Update record buffer settings
write_reg_64(port, REG_REC_BASE_ADDR_LO, base_addr);
@@ -583,6 +587,7 @@ module rfnoc_block_replay_tb#(
// exp_items : Queue of the items you expect to receive
// eob : Indicates if we expect EOB to be set for the last item (set
// to 1'bX to skip this check)
+ // spp : Samples per packet to expect. Set to 0 to skip this check.
// timestamp : The timestamp we expect to receive for the first item (set to
// 'X to skip timestamp checking)
//
@@ -591,6 +596,7 @@ module rfnoc_block_replay_tb#(
output string error_msg,
input item_t exp_items[$],
input logic eob = 1'b1,
+ input int spp = SPP,
input logic [63:0] timestamp = 64'bX
);
item_t recv_items[$];
@@ -614,9 +620,9 @@ module rfnoc_block_replay_tb#(
// Check the packet length
if (item_count + recv_items.size() > exp_items.size()) begin
$sformat(error_msg,
- "On packet %0d, size exceeds expected by %0d items",
- packet_count,
- (item_count + recv_items.size()) - exp_items.size());
+ "On packet %0d, size is %0d items, which exceeds expected by %0d items.",
+ packet_count, recv_items.size(),
+ (item_count + recv_items.size()) - exp_items.size());
return;
end
@@ -645,8 +651,27 @@ module rfnoc_block_replay_tb#(
end
end
- // Check the timestamp
- if (timestamp !== 64'bX) begin
+ // Check the payload length against expected SPP
+ if (spp > 0) begin
+ // If this is NOT the last packet, then its length should match the SPP.
+ // If it is the last packet, then it can be shorter than SPP.
+ if (!pkt_info.eob) begin
+ if (recv_items.size() != spp) begin
+ $sformat(error_msg,
+ "On packet %0d, expected SPP of %0d but packet has %0d items",
+ packet_count, spp, recv_items.size());
+ end
+ end else begin
+ if (recv_items.size() > spp) begin
+ $sformat(error_msg,
+ "On packet %0d (EOB), expected SPP of %0d or less but packet has %0d items",
+ packet_count, spp, recv_items.size());
+ end
+ end
+ end
+
+ // Check the timestamp (only first packet should have a timestamp)
+ if (timestamp !== 64'bX && packet_count == 0) begin
if (!pkt_info.timestamp) begin
$sformat(error_msg,
"On packet %0d, timestamp is missing",
@@ -925,37 +950,40 @@ module rfnoc_block_replay_tb#(
// For each test below, we record two memory bursts and playback two memory
// bursts. Each time we change the playback packet size to test boundary
// conditions.
+ //
+ // Note that we can't let the SPP exceed the MTU, so if the burst size is
+ // too large, we won't be testing the full size.
// Test packet size equals burst size
- spp = MEM_BURST_LEN * MEM_WORD_SIZE / ITEM_SIZE;
+ spp = `MIN(MEM_BURST_LEN * MEM_WORD_SIZE / ITEM_SIZE, 2**MTU);
start_replay(port, send_items, buffer_size, num_items, spp);
- verify_rx_data(port, error_string, send_items, 1);
+ verify_rx_data(port, error_string, send_items, 1, spp);
`ASSERT_ERROR(error_string == "", error_string);
// Test packet is one less than burst size
- spp = (MEM_BURST_LEN-1) * MEM_WORD_SIZE / ITEM_SIZE;
+ spp = `MIN((MEM_BURST_LEN-1) * MEM_WORD_SIZE / ITEM_SIZE, 2**MTU-(MEM_WORD_SIZE / ITEM_SIZE));
start_replay(port, send_items, buffer_size, num_items, spp);
- verify_rx_data(port, error_string, send_items, 1);
+ verify_rx_data(port, error_string, send_items, 1, spp);
`ASSERT_ERROR(error_string == "", error_string);
// Test packet is one more than burst size
- spp = (MEM_BURST_LEN+1) * MEM_WORD_SIZE / ITEM_SIZE;
+ spp = `MIN((MEM_BURST_LEN+1) * MEM_WORD_SIZE / ITEM_SIZE, 2**MTU);
start_replay(port, send_items, buffer_size, num_items, spp);
- verify_rx_data(port, error_string, send_items, 1);
+ verify_rx_data(port, error_string, send_items, 1, spp);
`ASSERT_ERROR(error_string == "", error_string);
// For each test below, we record two memory bursts and playback one memory
// burst plus or minus one word, keeping the packet size the same.
- spp = MEM_BURST_LEN * MEM_WORD_SIZE / ITEM_SIZE;
+ spp = `MIN(MEM_BURST_LEN * MEM_WORD_SIZE / ITEM_SIZE, 2**MTU);
// Playback one less than burst/packet size
start_replay(port, send_items, buffer_size, spp-MEM_WORD_SIZE/ITEM_SIZE, spp);
- verify_rx_data(port, error_string, send_items[0:spp-1-MEM_WORD_SIZE/ITEM_SIZE], 1);
+ verify_rx_data(port, error_string, send_items[0:spp-1-MEM_WORD_SIZE/ITEM_SIZE], 1, spp);
`ASSERT_ERROR(error_string == "", error_string);
// Playback one more than burst/packet size
start_replay(port, send_items, buffer_size, spp+MEM_WORD_SIZE/ITEM_SIZE, spp);
- verify_rx_data(port, error_string, send_items[0:spp-1+MEM_WORD_SIZE/ITEM_SIZE], 1);
+ verify_rx_data(port, error_string, send_items[0:spp-1+MEM_WORD_SIZE/ITEM_SIZE], 1, spp);
`ASSERT_ERROR(error_string == "", error_string);
// Make sure there are no more packets
@@ -1016,8 +1044,8 @@ module rfnoc_block_replay_tb#(
// Set number of words to test
buffer_size = (3 * MEM_BURST_LEN) / 2 * MEM_WORD_SIZE; // 1.5 memory bursts in size (in bytes)
- num_items_rec = buffer_size / ITEM_SIZE; // 1.5 memory bursts in size (in CHDR words)
- num_items_play = 2 * MEM_BURST_LEN * MEM_WORD_SIZE / // 2 memory bursts in size (in CHDR words)
+ num_items_rec = buffer_size / ITEM_SIZE; // 1.5 memory bursts in size (in samples)
+ num_items_play = 2 * MEM_BURST_LEN * MEM_WORD_SIZE / // 2 memory bursts in size (in samples)
ITEM_SIZE;
// Start playback of data
@@ -1045,19 +1073,25 @@ module rfnoc_block_replay_tb#(
item_t send_items[$];
string error_string;
logic [31:0] cmd;
- int num_items, mem_words;
+ int num_items, mem_words, spp;
test.start_test("Test continuous mode", TEST_TIMEOUT);
mem_words = 70;
num_items = mem_words * MEM_WORD_SIZE / ITEM_SIZE;
+ // Make sure the spp evenly divides our test size, or else we'll end a
+ // check mid packet, which verify_rx_data doesn't support.
+ spp = num_items / 2;
+ `ASSERT_ERROR(num_items % spp == 0,
+ "num_items should be a multiple of spp for this test");
+
// Update record buffer settings
write_reg_64(port, REG_REC_BASE_ADDR_LO, 0);
write_reg_64(port, REG_REC_BUFFER_SIZE_LO, num_items*ITEM_SIZE);
write_reg_64(port, REG_PLAY_BASE_ADDR_LO, 0);
write_reg_64(port, REG_PLAY_BUFFER_SIZE_LO, num_items*ITEM_SIZE);
- write_reg (port, REG_PLAY_WORDS_PER_PKT, SPP * ITEM_SIZE/MEM_WORD_SIZE);
+ write_reg (port, REG_PLAY_WORDS_PER_PKT, spp * ITEM_SIZE/MEM_WORD_SIZE);
// Restart the record buffer
write_reg(port, REG_REC_RESTART, 0);
@@ -1071,16 +1105,15 @@ module rfnoc_block_replay_tb#(
// Make sure the REG_PLAY_CMD_NUM_WORDS value is ignored by setting it to
// something smaller than what we receive.
- write_reg_64(port, REG_PLAY_CMD_NUM_WORDS_LO, mem_words);
+ write_reg_64(port, REG_PLAY_CMD_NUM_WORDS_LO, 0);
// Send command for continuous playback
cmd = PLAY_CMD_CONTINUOUS;
- write_reg_64(port, REG_PLAY_CMD_NUM_WORDS_LO, mem_words);
write_reg(port, REG_PLAY_CMD, cmd);
// Check the output, looking for the full set of data, multiple times
repeat (5) begin
- verify_rx_data(port, error_string, send_items, 0);
+ verify_rx_data(port, error_string, send_items, 0, spp);
`ASSERT_ERROR(error_string == "", error_string);
end
@@ -1153,6 +1186,7 @@ module rfnoc_block_replay_tb#(
// Check the result
verify_rx_data(port, error_string, send_items, 1);
+ `ASSERT_ERROR(error_string == "", error_string);
// Check the fullness
read_reg_64(port, REG_REC_FULLNESS_LO, val64);
@@ -1264,15 +1298,21 @@ module rfnoc_block_replay_tb#(
item_t send_items[$];
item_t exp_items[$];
string error_string;
- int num_items, mem_words;
+ int num_items, spp;
int num_items_buf;
logic [63:0] val64;
test.start_test("Test overfilled record buffer", TEST_TIMEOUT);
// Choose the sizes we want to use for this test
- num_items = 97*MEM_WORD_SIZE/ITEM_SIZE; // Number of items to record
- num_items_buf = 43*MEM_WORD_SIZE/ITEM_SIZE; // Size of buffer to use in items
+ num_items = 98*MEM_WORD_SIZE/ITEM_SIZE; // Number of items to record
+ num_items_buf = 44*MEM_WORD_SIZE/ITEM_SIZE; // Size of buffer to use in items
+
+ // Make sure the spp evenly divides our test size, or else we'll end a
+ // check mid packet, which verify_rx_data doesn't support.
+ spp = num_items_buf / 4;
+ `ASSERT_ERROR(num_items_buf % spp == 0,
+ "num_items_buf should be a multiple of spp for this test");
// Restart the record buffer
write_reg(port, REG_REC_RESTART, 0);
@@ -1281,17 +1321,17 @@ module rfnoc_block_replay_tb#(
send_items = gen_test_data(num_items);
// Start playback of the larger size
- start_replay(port, send_items, num_items_buf*ITEM_SIZE, num_items);
+ start_replay(port, send_items, num_items_buf*ITEM_SIZE, num_items, spp);
// We should get two frames of num_items_buf, then one smaller frame to
// bring us up to num_items total.
exp_items = send_items[0 : num_items_buf-1];
for (int i = 0; i < 2; i ++) begin
- verify_rx_data(port, error_string, exp_items, 0);
+ verify_rx_data(port, error_string, exp_items, 0, spp);
`ASSERT_ERROR(error_string == "", error_string);
end
exp_items = exp_items[0 : (num_items % num_items_buf)-1];
- verify_rx_data(port, error_string, exp_items, 1);
+ verify_rx_data(port, error_string, exp_items, 1, spp);
`ASSERT_ERROR(error_string == "", error_string);
// Make sure REG_REC_FULLNESS didn't keep increasing
@@ -1447,12 +1487,11 @@ module rfnoc_block_replay_tb#(
send_items = gen_test_data(num_items);
start_replay(port, send_items, buffer_size, num_items, pkt_size_items);
- // We should get 8 small packets instead of 2 large ones, with EOB set on
- // the last packet.
+ // We should get 8 small packets with EOB set on the last packet.
for (int k = 0; k < 8; k ++) begin
verify_rx_data(port, error_string,
send_items[pkt_size_items*k : pkt_size_items*(k+1)-1],
- (k == 7 ? 1 : 0));
+ (k == 7 ? 1 : 0), pkt_size_items);
`ASSERT_ERROR(error_string == "", error_string);
end
@@ -1473,7 +1512,7 @@ module rfnoc_block_replay_tb#(
// with EOB set on the last packet.
for (int i=0; i < num_items; i += pkt_size_items) begin
verify_rx_data(port, error_string, send_items[i:i+pkt_size_items-1],
- i == num_items-pkt_size_items ? 1 : 0);
+ i == num_items-pkt_size_items ? 1 : 0, pkt_size_items);
`ASSERT_FATAL(error_string == "", error_string);
end
@@ -1507,7 +1546,7 @@ module rfnoc_block_replay_tb#(
send_items = gen_test_data(num_items);
start_replay(port, send_items, buffer_size, num_items, spp, 0, 0, timestamp);
- verify_rx_data(port, error_string, send_items, 1, timestamp);
+ verify_rx_data(port, error_string, send_items, 1, spp, timestamp);
`ASSERT_ERROR(error_string == "", error_string);
test.end_test();
@@ -1581,6 +1620,8 @@ module rfnoc_block_replay_tb#(
blk_ctrl.send_items(port+1, port1_data);
// Play back on each port
+ write_reg(port+0, REG_PLAY_WORDS_PER_PKT, SPP*ITEM_SIZE/MEM_WORD_SIZE);
+ write_reg(port+1, REG_PLAY_WORDS_PER_PKT, SPP*ITEM_SIZE/MEM_WORD_SIZE);
write_reg_64(port+0, REG_PLAY_CMD_NUM_WORDS_LO, mem_words);
write_reg_64(port+1, REG_PLAY_CMD_NUM_WORDS_LO, mem_words);
write_reg(port+0, REG_PLAY_CMD, PLAY_CMD_FINITE);
@@ -1704,7 +1745,7 @@ module rfnoc_block_replay_tb#(
// Generate a string for the name of this instance of the testbench
tb_name = $sformatf( {
"rfnoc_block_replay_tb\n",
- "CHDR_W = %03d, ITEM_W = %02d, NUM_PORTS = %d,\n",
+ "CHDR_W = %03d, ITEM_W = %02d, NUM_PORTS = %0d,\n",
"MEM_DATA_W = %03d, MEM_ADDR_W = %02d,\n",
"TEST_REGS = %03d, TEST_FULL = %02d,\n",
"STALL_PROB = %03d" },