Software APIs
usbdev_stream_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 //
5 // USB streaming data test
6 //
7 // This test requires interaction with the USB DPI model or a test application
8 // on the USB host. The test initializes the USB device and configures a set of
9 // endpoints for data streaming using bulk transfers.
10 //
11 // The DPI model mimicks a USB host. After device initialization, it detects
12 // the assertion of the pullup and first assigns an address to the device.
13 // For this test it will then repeatedly fetch data via IN requests to
14 // each stream and propagate that data to the corresponding OUT endpoints.
15 //
16 // The data itself is pseudo-randomly generated by the sender and,
17 // independently, by the receiving code to check that the data has been
18 // propagated unmodified and without data loss, corruption, replication etc.
19 
23 #include "sw/device/lib/testing/pinmux_testutils.h"
24 #include "sw/device/lib/testing/test_framework/check.h"
26 #include "sw/device/lib/testing/usb_testutils.h"
27 #include "sw/device/lib/testing/usb_testutils_controlep.h"
28 #include "sw/device/lib/testing/usb_testutils_diags.h"
29 #include "sw/device/lib/testing/usb_testutils_streams.h"
30 
31 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
32 
33 // Number of streams to be tested
34 #ifndef NUM_STREAMS
35 #define NUM_STREAMS USBUTILS_STREAMS_MAX
36 #endif
37 
38 #define TRANSFER_BYTES_SILICON (8U << 20)
39 // 16MiB takes about 256s presently with 10MHz CPU in CW310 FPGA and physical
40 // USB with randomized packet sizes and the default memcpy implementation;
41 // The _MEM_FASTER switch drops the run time to 187s. In CI, we want to keep
42 // tests short so we reduce the amount transfered.
43 #define TRANSFER_BYTES_FPGA (0x10U << 16)
44 
45 // This is appropriate for a Verilator chip simulation with 15 min timeout
46 #define TRANSFER_BYTES_VERILATOR 0x2400U
47 
48 // For top-level DV simulation (regression runs, deterministic behavior)
49 #define TRANSFER_BYTES_DVSIM 0x800U
50 
51 // This is about the amount that we can transfer within a 1 hour 'eternal' test
52 // #define TRANSFER_BYTES_LONG (0xD0U << 20)
53 
54 /**
55  * Configuration values for USB.
56  */
57 static const uint8_t config_descriptors[] = {
58  USB_CFG_DSCR_HEAD(USB_CFG_DSCR_LEN + NUM_STREAMS * (USB_INTERFACE_DSCR_LEN +
59  2 * USB_EP_DSCR_LEN),
60  NUM_STREAMS),
61 
62  // Up to 11 interfaces and NUM_STREAMS in the descriptor head specifies how
63  // many of the interfaces will be declared to the host
64  VEND_INTERFACE_DSCR(0, 2, 0x50, 1),
65  USB_BULK_EP_DSCR(0, 1U, USBDEV_MAX_PACKET_SIZE, 0),
66  USB_BULK_EP_DSCR(1, 1U, USBDEV_MAX_PACKET_SIZE, 0),
67 
68  VEND_INTERFACE_DSCR(1, 2, 0x50, 1),
69  USB_BULK_EP_DSCR(0, 2U, USBDEV_MAX_PACKET_SIZE, 0),
70  USB_BULK_EP_DSCR(1, 2U, USBDEV_MAX_PACKET_SIZE, 0),
71 
72  VEND_INTERFACE_DSCR(2, 2, 0x50, 1),
73  USB_BULK_EP_DSCR(0, 3U, USBDEV_MAX_PACKET_SIZE, 0),
74  USB_BULK_EP_DSCR(1, 3U, USBDEV_MAX_PACKET_SIZE, 0),
75 
76  VEND_INTERFACE_DSCR(3, 2, 0x50, 1),
77  USB_BULK_EP_DSCR(0, 4U, USBDEV_MAX_PACKET_SIZE, 0),
78  USB_BULK_EP_DSCR(1, 4U, USBDEV_MAX_PACKET_SIZE, 0),
79 
80  VEND_INTERFACE_DSCR(4, 2, 0x50, 1),
81  USB_BULK_EP_DSCR(0, 5U, USBDEV_MAX_PACKET_SIZE, 0),
82  USB_BULK_EP_DSCR(1, 5U, USBDEV_MAX_PACKET_SIZE, 0),
83 
84  VEND_INTERFACE_DSCR(5, 2, 0x50, 1),
85  USB_BULK_EP_DSCR(0, 6U, USBDEV_MAX_PACKET_SIZE, 0),
86  USB_BULK_EP_DSCR(1, 6U, USBDEV_MAX_PACKET_SIZE, 0),
87 
88  VEND_INTERFACE_DSCR(6, 2, 0x50, 1),
89  USB_BULK_EP_DSCR(0, 7U, USBDEV_MAX_PACKET_SIZE, 0),
90  USB_BULK_EP_DSCR(1, 7U, USBDEV_MAX_PACKET_SIZE, 0),
91 
92  VEND_INTERFACE_DSCR(7, 2, 0x50, 1),
93  USB_BULK_EP_DSCR(0, 8U, USBDEV_MAX_PACKET_SIZE, 0),
94  USB_BULK_EP_DSCR(1, 8U, USBDEV_MAX_PACKET_SIZE, 0),
95 
96  VEND_INTERFACE_DSCR(8, 2, 0x50, 1),
97  USB_BULK_EP_DSCR(0, 9U, USBDEV_MAX_PACKET_SIZE, 0),
98  USB_BULK_EP_DSCR(1, 9U, USBDEV_MAX_PACKET_SIZE, 0),
99 
100  VEND_INTERFACE_DSCR(9, 2, 0x50, 1),
101  USB_BULK_EP_DSCR(0, 10U, USBDEV_MAX_PACKET_SIZE, 0),
102  USB_BULK_EP_DSCR(1, 10U, USBDEV_MAX_PACKET_SIZE, 0),
103 
104  VEND_INTERFACE_DSCR(10, 2, 0x50, 1),
105  USB_BULK_EP_DSCR(0, 11U, USBDEV_MAX_PACKET_SIZE, 0),
106  USB_BULK_EP_DSCR(1, 11U, USBDEV_MAX_PACKET_SIZE, 0),
107 };
108 
109 /**
110  * Test flags specifying the nature and direction of the data stream(s)
111  */
112 static usbdev_stream_flags_t test_flags;
113 
114 /**
115  * Test descriptor
116  */
117 static uint8_t test_descriptor[USB_TESTUTILS_TEST_DSCR_LEN];
118 
119 /**
120  * USB device context types.
121  */
122 static usb_testutils_ctx_t usbdev;
123 static usb_testutils_controlep_ctx_t usbdev_control;
124 
125 /**
126  * Pinmux handle
127  */
128 static dif_pinmux_t pinmux;
129 
130 /**
131  * State information for streaming data test
132  */
133 static usb_testutils_streams_ctx_t stream_test;
134 
135 /**
136  * Specify whether to perform verbose logging, for visibility
137  * (Note that this substantially alters the timing of interactions with the
138  * DPI model and will increase the simulation time)
139  */
140 static const bool kVerbose = false;
141 
142 /*
143  * These switches may be modified manually to experimentally measure the
144  * performance of IN traffic in isolation, or IN/OUT together etc.
145  *
146  * Are we sending data?
147  */
148 static const bool kSending = true;
149 
150 /**
151  * Are we generating a valid byte sequence?
152  */
153 static const bool kGenerating = true;
154 
155 /**
156  * Do we want the host to retry transmissions? (DPI model only; we cannot
157  * instruct a physical host to fake delivery failure/packet corruption etc)
158  */
159 static const bool kRetrying = true;
160 
161 /**
162  * Are we expecting to receive data?
163  */
164 static const bool kRecving = true;
165 
166 /**
167  * Send only maximal length packets?
168  * (important for performance measurements on the USB, but obviously undesirable
169  * for testing reliability/function)
170  */
171 static const bool kMaxPackets = false;
172 
173 /**
174  * Number of streams to be created
175  */
176 static const unsigned nstreams = NUM_STREAMS;
177 
178 OTTF_DEFINE_TEST_CONFIG();
179 
180 bool test_main(void) {
181  // Context state for streaming test
182  usb_testutils_streams_ctx_t *ctx = &stream_test;
183 
184  LOG_INFO("Running USBDEV Stream Test");
185 
186  // Check we can support the requested number of streams
187  CHECK(nstreams && nstreams < USBDEV_NUM_ENDPOINTS);
188 
189  // Decide upon the number of bytes to be transferred for the entire test
190  uint32_t transfer_bytes = TRANSFER_BYTES_FPGA;
191  switch (kDeviceType) {
192  case kDeviceSimVerilator:
193  transfer_bytes = TRANSFER_BYTES_VERILATOR;
194  break;
195  case kDeviceSimDV:
196  transfer_bytes = TRANSFER_BYTES_DVSIM;
197  break;
198  case kDeviceSilicon:
199  transfer_bytes = TRANSFER_BYTES_SILICON;
200  break;
201  case kDeviceFpgaCw340:
202  break;
203  default:
204  CHECK(kDeviceType == kDeviceFpgaCw310);
205  break;
206  }
207  transfer_bytes = (transfer_bytes + nstreams - 1) / nstreams;
208  LOG_INFO(" - %u stream(s), 0x%x bytes each", nstreams, transfer_bytes);
209 
210  CHECK_DIF_OK(dif_pinmux_init(
212  pinmux_testutils_init(&pinmux);
213  CHECK_DIF_OK(dif_pinmux_input_select(
216 
217  // Construct the test/stream flags to be used
218  test_flags = (kSending ? kUsbdevStreamFlagRetrieve : 0U) |
219  (kGenerating ? kUsbdevStreamFlagCheck : 0U) |
220  (kRetrying ? kUsbdevStreamFlagRetry : 0U) |
221  (kRecving ? kUsbdevStreamFlagSend : 0U) |
222  // Note: the 'max packets' test flag is not required by the DPI
223  (kMaxPackets ? kUsbdevStreamFlagMaxPackets : 0U);
224 
225  // Initialize the test descriptor
226  // Note: the 'max packets' test flag is not required by the DPI model
227  const uint8_t desc[] = {
228  USB_TESTUTILS_TEST_DSCR(1, NUM_STREAMS | (uint8_t)test_flags, 0, 0, 0)};
229  memcpy(test_descriptor, desc, sizeof(test_descriptor));
230 
231  // Remember context state for usb_testutils context
232  ctx->usbdev = &usbdev;
233 
234  // Call `usbdev_init` here so that DPI will not start until the
235  // simulation has finished all of the printing, which takes a while
236  // if `--trace` was passed in.
237  CHECK_STATUS_OK(usb_testutils_init(ctx->usbdev, /*pinflip=*/false,
238  /*en_diff_rcvr=*/true,
239  /*tx_use_d_se0=*/false));
240  CHECK_STATUS_OK(usb_testutils_controlep_init(
241  &usbdev_control, ctx->usbdev, 0, config_descriptors,
242  sizeof(config_descriptors), test_descriptor, sizeof(test_descriptor)));
243 
244  // Proceed only when the device has been configured; this allows host-side
245  // software to establish communication.
246  CHECK_STATUS_OK(
247  usb_testutils_controlep_config_wait(&usbdev_control, &usbdev));
248 
249  // Describe the transfer type of each stream;
250  // Note: for now we support only Bulk Transfer streams but this should change
251  // in future, eg. in response to test configuration.
252  usb_testutils_transfer_type_t xfr_types[USBUTILS_STREAMS_MAX];
253  for (unsigned s = 0U; s < nstreams; s++) {
254  xfr_types[s] = kUsbTransferTypeBulk;
255  }
256 
257  // Initialise the state of the streams
258  CHECK_STATUS_OK(usb_testutils_streams_init(
259  ctx, nstreams, xfr_types, transfer_bytes, test_flags, kVerbose));
260 
261  USBUTILS_USER_PROMPT("Start host-side streaming software");
262 
263  // Streaming loop; most of the work is done by the usb_testutils_streams base
264  // code and we don't need to specialize its behavior for this test.
265  bool done = false;
266  do {
267  CHECK_STATUS_OK(usb_testutils_streams_service(ctx));
268 
269  // See whether any streams still have more work to do
270  done = usb_testutils_streams_completed(ctx);
271  } while (!done);
272 
273  // Determine the total counts of bytes sent and received
274  uint32_t tx_bytes = 0U;
275  uint32_t rx_bytes = 0U;
276  for (uint8_t s = 0U; s < nstreams; s++) {
277  uint32_t tx, rx;
278  CHECK_STATUS_OK(usb_testutils_stream_status(ctx, s, NULL, &tx, &rx));
279  tx_bytes += tx;
280  rx_bytes += rx;
281  }
282 
283  LOG_INFO("USB sent 0x%x byte(s), received and checked 0x%x byte(s)", tx_bytes,
284  rx_bytes);
285 
286  if (kSending) {
287  CHECK(tx_bytes == nstreams * transfer_bytes,
288  "Unexpected count of byte(s) sent to USB host");
289  }
290  if (kRecving) {
291  CHECK(rx_bytes == nstreams * transfer_bytes,
292  "Unexpected count of byte(s) received from USB host");
293  }
294 
295  return true;
296 }