Merge "Add a verilator test to test hello_world gpio-write function"
diff --git a/sw/device/examples/hello_world/BUILD b/sw/device/examples/hello_world/BUILD
index fa9fce8..e6d7f3a 100644
--- a/sw/device/examples/hello_world/BUILD
+++ b/sw/device/examples/hello_world/BUILD
@@ -65,3 +65,25 @@
         "verilator",
     ],
 )
+
+sh_test(
+    name = "verilator_hello_world_gpio_test",
+    timeout = "long",
+    srcs = [":run_verilator_hello_world.sh"],
+    args = [
+        "$(location //hw:verilator)",
+        "$(location //sw/device/lib/testing/test_rom:test_rom_sim_verilator_scr_vmem)",
+        "$(location :hello_world_sim_verilator_vmem)",
+        "$(location //hw/top_matcha/data:otp_img_rma)",
+        "gpio_test",
+    ],
+    data = [
+        ":hello_world_sim_verilator_vmem",
+        "//hw:verilator",
+        "//hw/top_matcha/data:otp_img_rma",
+        "//sw/device/lib/testing/test_rom:test_rom_sim_verilator_scr_vmem",
+    ],
+    tags = [
+        "verilator",
+    ],
+)
diff --git a/sw/device/examples/hello_world/hello_world.c b/sw/device/examples/hello_world/hello_world.c
index 216178b..577e7c5 100644
--- a/sw/device/examples/hello_world/hello_world.c
+++ b/sw/device/examples/hello_world/hello_world.c
@@ -107,7 +107,11 @@
   // Now have UART <-> Buttons/LEDs demo
   // all LEDs off
   CHECK_DIF_OK(dif_gpio_write_all(&gpio, 0x0000));
-  LOG_INFO("Try out the switches on the board");
+  if (kDeviceType == kDeviceFpgaNexus) {
+    LOG_INFO("Try out the switches on the board");
+  } else if (kDeviceType == kDeviceSimVerilator) {
+    LOG_INFO("Try out the GPIO switches 28, 29, 31");
+  }
   LOG_INFO("or type anything into the console window.");
   LOG_INFO(
       "The LEDs show the bits of the ASCII code of the last "
diff --git a/sw/device/examples/hello_world/run_verilator_hello_world.sh b/sw/device/examples/hello_world/run_verilator_hello_world.sh
index e85af45..e220a8a 100755
--- a/sw/device/examples/hello_world/run_verilator_hello_world.sh
+++ b/sw/device/examples/hello_world/run_verilator_hello_world.sh
@@ -17,7 +17,7 @@
 # Run verilator interactive simulation on sw/device/examples/hello_world.
 
 function print_usage {
-  echo "Usage: run_verilator_hello_world.sh <verilator testbench> <rom binary> <flash binary> <otp binary>"
+  echo "Usage: run_verilator_hello_world.sh <verilator testbench> <rom binary> <flash binary> <otp binary> [gpio_test]"
 }
 
 if [[ $1 == "--help" ]]; then
@@ -25,7 +25,7 @@
   exit 0
 fi
 
-if [[ $# -ne 4 ]]; then
+if [[ $# -lt 4 ]]; then
   print_usage
   exit 1
 fi
@@ -35,8 +35,16 @@
   exit 1
 fi
 
+# This cycle count is tuned so we don't need to wait too long for the test to
+# finish.
+TEST_CYCLES=700000
 
-TEST_CYCLES=650000
+GPIO_TEST=0
+
+if [[ $# -eq 5 ]] && [[ $5 == "gpio_test" ]]; then
+  GPIO_TEST=1
+  TEST_CYCLES=900000
+fi
 
 VCHIP_TB=$1
 ROM_BIN=$2
@@ -62,19 +70,37 @@
 
 VERILATOR_PID=$!
 
-# Pipe GPIO output to a log file
-sleep 5
-cat gpio0-read | tee "${TEST_UNDECLARED_OUTPUTS_DIR}/gpio0_read.log" &
+if (( ${GPIO_TEST} == 0 )); then
+  # Pipe GPIO output to a log file
+  sleep 5
+  cat gpio0-read | tee "${TEST_UNDECLARED_OUTPUTS_DIR}/gpio0_read.log" &
 
-# Wait for 300s to reach the end of the hello_world initialization.
-sleep 300
-echo 'led gpio test' > "${TEST_UNDECLARED_OUTPUTS_DIR}/uart0_device"
+  # Wait for 300s to reach the end of the hello_world initialization.
+  # Note: The value is tuned for the CICD to run. For local failing tests,
+  # consider to reduce the wait or increase the TEST_CYCLES.
+  sleep 300
+  echo 'led gpio test' > "${TEST_UNDECLARED_OUTPUTS_DIR}/uart0_device"
 
-# Wait up to another 350s to complete the verilator simulation.
-timeout 350 tail --pid=${VERILATOR_PID} -f /dev/null
+  tail --pid=${VERILATOR_PID} -f /dev/null
 
-# Check results in GPIO and UART logs.
-cat "${TEST_UNDECLARED_OUTPUTS_DIR}/uart0.log" | grep -q "led gpio test" || exit 1
+  # Check results in GPIO and UART logs.
+  cat "${TEST_UNDECLARED_OUTPUTS_DIR}/uart0.log" | grep -q "led gpio test" || exit 1
 
-diff -q "${TEST_UNDECLARED_OUTPUTS_DIR}/gpio0_read.log" \
-  "sw/device/examples/hello_world/hello_world_test_expected_gpio.txt" || exit 1
+  diff -q "${TEST_UNDECLARED_OUTPUTS_DIR}/gpio0_read.log" \
+    "sw/device/examples/hello_world/hello_world_test_expected_gpio.txt" || exit 1
+else
+  # Wait for 260s to reach the end of the hello_world initialization.
+  # Note: This value may need to tuned by the machine performance. Need to
+  # reduce the wait if the verilator simulation is fast (or increase the
+  # TEST_CYCLES variable).
+  sleep 260
+  echo 'h28 h29 h31' > gpio0-write
+
+  tail --pid=${VERILATOR_PID} -f /dev/null
+
+  # Check GPIO toggle result in the UART log
+  for switch in "9" "10" "11"; do
+    cat "${TEST_UNDECLARED_OUTPUTS_DIR}/uart0.log" | \
+      grep -q "GPIO switch #${switch} changed to 1" || exit 1
+  done
+fi