| #!/usr/bin/env python3 |
| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| r"""Runs a binary on an FPGA, which is expected to write |
| one of "PASS!\r\n" or "FAIL!\r\n" to the UART to determine success or failure. |
| Failing to write either will result in a timeout. |
| |
| This test requires some setup and some configuration. This test expects you |
| to have: |
| - A supported FPGA connected to your workstation. |
| - That FPGA must be flashed with a synthesized EarlGrey bitfile, which has |
| been spliced with the OpenTitan bootloader. |
| - A prebuilt spiflash executable. |
| |
| You must then provide this test with the .bin file for the test, the UART |
| device path for the FPGA, and the spiflash executable. For example: |
| |
| $ cd ${REPO_TOP} |
| $ pytest -s -v test/systemtest/functional_fpga_test.py \ |
| --test_bin sw/tests/hmac/sw.bin \ |
| --fpga_uart /dev/ttyUSB2 \ |
| --spiflash sw/host/spiflash/spiflash |
| """ |
| |
| import logging |
| from pathlib import Path |
| import re |
| |
| import pytest |
| |
| import test_utils |
| |
| logging.basicConfig(level=logging.DEBUG) |
| |
| |
| class TestFunctionalFpga: |
| """ |
| Execute a test binary on a locally connected FPGA, using UART |
| output to validate test success or failure. |
| """ |
| @pytest.fixture |
| def spiflash_proc(self, tmp_path, spiflash, sw_test_bin): |
| cmd_flash = [str(spiflash), '--input', str(sw_test_bin)] |
| p_flash = test_utils.Process(cmd_flash, |
| logdir=str(tmp_path), |
| cwd=str(tmp_path), |
| startup_done_expect='Running SPI flash update.', |
| startup_timeout=10) |
| p_flash.run() |
| |
| yield p_flash |
| |
| p_flash.terminate() |
| |
| def test_execute_binary(self, spiflash_proc, fpga_uart, uart_timeout): |
| """ |
| Executes the binary and inspects its UART for "PASS!\r\n" or "FAIL!\r\n". |
| """ |
| |
| logger = logging.getLogger(__name__) |
| |
| # Open the UART device and read line by line until we pass or fail. |
| with fpga_uart.open('rb') as uart_device: |
| uart_fd = uart_device.fileno() |
| pattern = re.compile('.*?(PASS!\r\n|FAIL!\r\n)') |
| match = test_utils.stream_fd_to_log(uart_fd, logger, pattern, |
| uart_timeout) |
| |
| if match == None: |
| pytest.fail('Deadline exceeded: did not see PASS! or FAIL! within %ds.', uart_timeout) |
| |
| if match.group(1) == 'PASS!\r\n': |
| logger.debug('Got PASS! from binary.') |
| else: |
| pytest.fail('Got FAIL! from binary.') |