| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| |
| import logging |
| import re |
| |
| import pytest |
| |
| from .. import config, utils |
| |
| log = logging.getLogger(__name__) |
| |
| |
| @pytest.fixture(scope="module") |
| def localconf_nexysvideo(localconf): |
| assert 'boards' in localconf |
| assert 'nexysvideo' in localconf['boards'] |
| boardconf = localconf['boards']['nexysvideo'] |
| |
| assert 'uart_device' in boardconf |
| assert 'uart_speed' in boardconf |
| return boardconf |
| |
| |
| @pytest.fixture(scope="module") |
| def uart_persistent(localconf_nexysvideo, tmp_path_factory): |
| """ |
| A UART device connected to the FPGA board, which is kept active for |
| for multiple tests. |
| |
| Use the `uart` fixture for per-test access to the UART device. |
| """ |
| uart_device = localconf_nexysvideo['uart_device'] |
| uart_speed = localconf_nexysvideo['uart_speed'] |
| log_dir_path = tmp_path_factory.mktemp('uart') |
| log.debug("Opening UART on device {} ({} baud)".format( |
| uart_device, uart_speed)) |
| with utils.LoggingSerial(uart_device, |
| uart_speed, |
| timeout=1, |
| log_dir_path=log_dir_path, |
| default_filter_func=utils. |
| filter_remove_device_sw_log_prefix) as uart: |
| |
| yield uart |
| |
| |
| @pytest.fixture |
| def uart(uart_persistent, request): |
| """ A UART device connected to the FPGA board. |
| |
| The UART is drained between test runs to give better isolation between the |
| tests. |
| """ |
| |
| uart_persistent.log_add_marker("===== TEST {} START =====\n".format( |
| request.node.name)) |
| |
| yield uart_persistent |
| |
| # Read all remaining data from UART to have it available in the log file. |
| uart_persistent.drain_in() |
| |
| uart_persistent.log_add_marker("===== TEST {} DONE =====\n\n".format( |
| request.node.name)) |
| |
| |
| @pytest.fixture(scope="module") |
| def nexysvideo_earlgrey(tmp_path_factory, topsrcdir, bin_dir, localconf_nexysvideo): |
| """ A Nexys Video board flashed with an Earl Grey bitstream """ |
| |
| bitstream = bin_dir / "hw/top_earlgrey/lowrisc_systems_top_earlgrey_nexysvideo_0.1.bit" |
| assert bitstream.is_file(), ("Bitstream not found at %s." % str(bitstream)) |
| |
| cmd_pgm = [ |
| topsrcdir / 'util/opentitan-pgm-fpga/opentitan-pgm-fpga', |
| 'xc7a200tsbg484-1', |
| bitstream, |
| ] |
| |
| # Explicitly use a certain hardware server (if set) |
| if 'hw_server_url' in localconf_nexysvideo: |
| cmd_pgm += [ |
| '--hw-server-url', |
| localconf_nexysvideo['hw_server_url'], |
| ] |
| |
| log.debug("Flashing Nexys Video board with bitstream {}".format( |
| str(bitstream))) |
| tmp_path = tmp_path_factory.mktemp('nexysvideo_earlgrey') |
| p_pgm = utils.Process(cmd_pgm, logdir=tmp_path, cwd=tmp_path) |
| p_pgm.run() |
| p_pgm.proc.wait(timeout=300) |
| assert p_pgm.proc.returncode == 0 |
| |
| |
| @pytest.fixture(params=config.TEST_APPS_SELFCHECKING) |
| def app_selfchecking_bin(request, bin_dir): |
| test_filename = request.param + '_fpga_nexysvideo.bin' |
| bin_path = bin_dir / 'sw/device/tests' / test_filename |
| assert bin_path.is_file() |
| return bin_path |
| |
| |
| def test_apps_selfchecking(tmp_path, localconf_nexysvideo, nexysvideo_earlgrey, |
| app_selfchecking_bin, bin_dir, uart): |
| """ Load a simple application, and check its output. """ |
| |
| spiflash = bin_dir / 'sw/host/spiflash/spiflash' |
| utils.load_sw_over_spi(tmp_path, spiflash, app_selfchecking_bin) |
| |
| # We need to wait for this message to ensure we are asserting on the output |
| # of the newly flashed software, not the software which might be already on |
| # the chip (which might get re-executed when running spiflash). |
| bootstrap_done_exp = b'Bootstrap: DONE!' |
| assert uart.find_in_output(bootstrap_done_exp, timeout=60) |
| |
| bootmsg_exp = b'Boot ROM initialisation has completed, jump into flash!' |
| assert uart.find_in_output(bootmsg_exp, |
| timeout=10), "End-of-bootrom string not found." |
| |
| log.debug("Waiting for pass string from device test") |
| |
| result_match = uart.find_in_output(re.compile(br'^(PASS|FAIL)!$'), |
| timeout=60) |
| assert result_match is not None, "PASS/FAIL indication not found in test output." |
| |
| result_msg = result_match.group(1) |
| log.info("Test ended with {}".format(result_msg)) |
| assert result_msg == b'PASS' |