[test] Add an FPGA test executor, similar to the Verilator executor.

The new test executor, functional_fpga_test.py, is similar to the
existing Verilator executor, but rather than accepting the Verilator
model, a boot loader, and a binary (in vmem form) it accepts a spiflash
executable, a /dev path (the UART port for the FPGA) and the binary.
Much like the Verilator test requires building the Verilator model,
this test expects a ROM-spliced bitfile has already been flashed to the
FPGA.

This test does not provide everything necessary to do a full FPGA test;
it instead serves as a starting point for future test executors and,
more importantly, provides a smoketest for the FPGA flow.
diff --git a/test/systemtest/conftest.py b/test/systemtest/conftest.py
index c81bfb7..1178d85 100644
--- a/test/systemtest/conftest.py
+++ b/test/systemtest/conftest.py
@@ -20,7 +20,8 @@
     parser.addoption("--verilator_model", action="store", default="")
     parser.addoption("--openocd", action="store", default="openocd")
     parser.addoption("--uart_timeout", action="store", default="60")
-
+    parser.addoption("--fpga_uart", action="store", default="")
+    parser.addoption("--spiflash", action="store", default="")
 
 @pytest.hookimpl(tryfirst=True)
 def pytest_exception_interact(node, call, report):
@@ -108,3 +109,17 @@
 def uart_timeout(pytestconfig):
     """Return the timeout in seconds for UART to print PASS."""
     return int(pytestconfig.getoption('uart_timeout'))
+
+@pytest.fixture(scope="session")
+def fpga_uart(pytestconfig):
+    """Return the path to the UART attached to the FPGA."""
+    path = Path(pytestconfig.getoption('fpga_uart')).resolve()
+    assert path.is_file()
+    return path
+
+@pytest.fixture(scope="session")
+def spiflash(pytestconfig):
+    """Return the path to the spiflash executable."""
+    path = Path(pytestconfig.getoption('spiflash')).resolve()
+    assert path.is_file()
+    return path