[DVsim] Add support for Verilator

This commit adds support for Verilator within DVSim.

Signed-off-by: Srikrishna Iyer <sriyer@google.com>
diff --git a/hw/dv/tools/dvsim/verilator.hjson b/hw/dv/tools/dvsim/verilator.hjson
new file mode 100644
index 0000000..1306435
--- /dev/null
+++ b/hw/dv/tools/dvsim/verilator.hjson
@@ -0,0 +1,144 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+{
+  // Replicate settings from `common_sim_cfg.hjson`.
+  //
+  // Unfortunately, that file assumes that the tools are invoked natively as
+  // opposed to via FuseSoC. Verilator is setup to be invoked via FuseSoC,
+  // which causes FuseSoC to fail due to unknown {build_opts}. Hence, contents
+  // from `common_sim_cfg.hjson` are replicated here as appropriate.
+  // -- START --
+  dv_root:          "{proj_root}/hw/dv"
+  flow:             sim
+  flow_makefile:    "{dv_root}/tools/dvsim/sim.mk"
+
+  import_cfgs:      ["{proj_root}/hw/data/common_project_cfg.hjson",
+                     "{dv_root}/tools/dvsim/common_modes.hjson",
+                     "{dv_root}/tools/dvsim/fusesoc.hjson",
+                     ]
+
+  // Default directory structure for the output
+  build_dir:          "{scratch_path}/{build_mode}"
+  run_dir_name:       "{index}.{test}"
+  run_dir:            "{scratch_path}/{run_dir_name}/out"
+  sw_build_dir:       "{scratch_path}"
+  sw_root_dir:        "{proj_root}/sw"
+
+  regressions: [
+    {
+      name: smoke
+      reseed: 1
+    }
+    {
+      name: all
+    }
+    {
+      name: all_once
+      reseed: 1
+    }
+    {
+      name: nightly
+    }
+  ]
+  // -- END --
+
+  build_cmd:  "fusesoc {fusesoc_cores_root_dirs} run"
+  ex_name:    "{eval_cmd} echo \"{fusesoc_core}\" | cut -d: -f3"
+  run_cmd:    "{build_dir}/sim-verilator/V{ex_name}"
+
+  // Indicate the tool specific helper sources - these are copied over to the
+  // {tool_srcs_dir} before running the simulation.
+  // TODO: none at the moment.
+  tool_srcs:  []
+
+  // TODO: Verilator has a few useful build switches. Need to figure out how to
+  // pass them via FuseSoC.
+
+  build_opts: ["--flag=fileset_{design_level}",
+               "--target=sim",
+               "--build-root={build_dir}",
+               "--setup",
+               "--build",
+               "{fusesoc_core}"
+               // "--timescale 1ns/1ps",
+               // Enable all assertions.
+               // "--assert",
+               // Flush streams immediately after all $displays.
+               // "--autoflush",
+               // Enable multi-threading.
+               // "--threads 4",
+               // Randomize all 2-state vars if driven to unknown 'X'.
+               // "--x-assign unique",
+               // "--x-initial unique",
+               ]
+
+  run_opts: [// Set random seed.
+             // "+verilator+seed+{seed}",
+             ]
+
+  // Supported wave dumping formats (in order of preference).
+  supported_wave_formats: ["fst"]
+
+  // Vars that need to exported to the env.
+  exports: [
+  ]
+
+  // pass and fail patterns
+  build_pass_patterns: []
+  build_fail_patterns: [// Verilator compile error.
+                        "^%Error.*?:",
+                        // FuseSoC build error.
+                        "^ERROR:.*$",
+                        ]
+  run_pass_patterns:   ["^TEST PASSED CHECKS$"]
+  run_fail_patterns:   [// $warning/error/fatal messages.
+                        "^\\[[0-9]+\\] %Warning.*?: ",
+                        "^\\[[0-9]+\\] %Error.*?: ",
+                        "^\\[[0-9]+\\] %Fatal.*?: ",
+                        // Ninja / SW compile failure.
+                        "^FAILED: ",
+                        " error: ",
+                        // Failure signature pattern.
+                        "^TEST FAILED CHECKS$"
+                        ]
+
+  // Coverage related.
+  cov_db_dir: ""
+  cov_db_test_dir: ""
+
+  build_modes: [
+    {
+      name: verilator_waves
+      is_sim_mode: 1
+      // build_opts: ["--trace",
+      //              "--trace-fst"
+      //              "--trace-structs",
+      //              "--trace-params",
+      //              "-CFLAGS \"-DVM_TRACE_FMT_FST\"",
+      //              ]
+      run_opts: ["--trace"]
+    }
+    // TODO: These need to be fine-tuned.
+    {
+      name: verilator_cov
+      is_sim_mode: 1
+      // build_opts: ["--coverage"]
+    }
+    {
+      name: verilator_xprop
+      is_sim_mode: 1
+    }
+    {
+      name: verilator_profile
+      is_sim_mode: 1
+      // build_opts: ["--prof-cfuncs",
+      //              "--prof-threads",
+      //             ]
+    }
+    {
+      name: verilator_loopdetect
+      is_sim_mode: 1
+    }
+  ]
+}
diff --git a/hw/top_earlgrey/dv/verilator_sim_cfg.hjson b/hw/top_earlgrey/dv/verilator_sim_cfg.hjson
new file mode 100644
index 0000000..bbc8b10
--- /dev/null
+++ b/hw/top_earlgrey/dv/verilator_sim_cfg.hjson
@@ -0,0 +1,165 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+{
+  // Name of the sim cfg - typically same as the name of the DUT.
+  name: top_earlgrey_verilator
+
+  // Top level dut name (sv module).
+  dut: "{name}"
+
+  // Top level testbench name (sv module).
+  tb: "{name}"
+
+  // Default simulator used to sign off.
+  tool: verilator
+
+  // Fusesoc core file used for building the file list.
+  fusesoc_core: "lowrisc:systems:{name}:0.1"
+
+  // Testplan hjson file.
+  # testplan: "{proj_root}/hw/top_earlgrey/data/chip_testplan.hjson"
+
+  // Import additional common sim cfg files.
+  import_cfgs: [// Project wide common sim cfg file
+                "{proj_root}/hw/dv/tools/dvsim/verilator.hjson",
+               ]
+
+  overrides: [
+    // Use FuseSoC to build the Verilator executable. Skip the SV file list
+    // generation step entirely.
+    {
+      name: sv_flist_gen_cmd
+      value: ""
+    }
+    {
+      name: sv_flist_gen_opts
+      value: []
+    }
+    {
+      name: sv_flist_gen_dir
+      value: "{build_dir}"
+    }
+    // This defaults to 'ip' in `hw/data/common_project_cfg.hjson`. Override
+    // since we are building the top level.
+    {
+      name: design_level
+      value: top
+    }
+  ]
+
+  // Common run parameters. Each test entry can override any of these as needed.
+  reseed: 1
+  sw_build_device: sim_verilator
+
+  // Add run modes.
+  run_modes: [
+    {
+      name: sw_test_mode
+      sw_images: ["sw/device/boot_rom/boot_rom:0"]
+      run_opts: [
+        // The following shell snippet converts the SW images specification to what's
+        // needed as a run time switch to Verilator.
+        '''{eval_cmd} \
+        opts=;  \
+        types=(rom flash); \
+        images=`echo {sw_images}`; \
+        for image in $images; do \
+          path=`echo $image | cut -d: -f 1`;  \
+          index=`echo $image | cut -d: -f 2`; \
+          opts="$opts --meminit=${types[$index]},{sw_build_dir}/build-bin/$path""_{sw_build_device}.elf"; \
+        done; \
+        echo "$opts"''',
+      ]
+    }
+  ]
+
+  // All tests are SW based, so enable this by default.
+  en_run_modes: ["sw_test_mode"]
+
+  // List of test specifications.
+  //
+  // If you are adding a test that has been generated from the `sw_tests`
+  // dictionary declared in `sw/device/tests/meson.build`, the `sw_images` list
+  // below should contain `sw/device/tests/<sw_test_name>` (without any more
+  // subdirectories) because that is where the meson target is created. For
+  // example `dif_plic_smoketest` is added to `sw_tests` in
+  // `sw/device/tests/dif/meson.build`, but the final meson targets all start
+  // `sw/device/tests/dif_plic_smoketest_`.
+  //
+  // Each entry in `sw_images` is followed by an index separated with ':' which
+  // is used by the testbench to know what type of image is it:
+  // - 0 for boot_rom,
+  // - 1 for SW test,
+  // - 2 for OTBN and so on
+  // This allows an arbitrary number of SW images to be supplied to the TB.
+  tests: [
+    {
+      name: aes_test
+      sw_images: ["sw/device/tests/aes_test:1"]
+    }
+    {
+      name: crt_test
+      sw_images: ["sw/device/tests/crt_test:1"]
+    }
+    {
+      name: dif_otbn_smoketest_rtl
+      sw_images: ["sw/device/tests/dif_otbn_smoketest:1"]
+      run_opts: ['+OTBN_USE_MODEL=0']
+    }
+    // Using the model in CI isn't possible until #4097 is resolved.
+    //{
+    //  name: dif_otbn_smoketest_model
+    //  sw_images: ["sw/device/tests/dif_otbn_smoketest:1"]
+    //  run_opts: ['+OTBN_USE_MODEL=0']
+    //}
+    {
+      name: dif_otp_ctrl_smoketest
+      sw_images: ["sw/device/tests/dif_otp_ctrl_smoketest:1"]
+    }
+    {
+      name: dif_plic_smoketest
+      sw_images: ["sw/device/tests/dif_plic_smoketest:1"]
+    }
+    {
+      name: dif_rstmgr_smoketest
+      sw_images: ["sw/device/tests/dif_rstmgr_smoketest:1"]
+    }
+    {
+      name: dif_rv_timer_smoketest
+      sw_images: ["sw/device/tests/dif_rv_timer_smoketest:1"]
+    }
+    {
+      name: dif_uart_smoketest
+      sw_images: ["sw/device/tests/dif_uart_smoketest:1"]
+    }
+    {
+      name: flash_ctrl_test
+      sw_images: ["sw/device/tests/flash_ctrl_test:1"]
+    }
+    {
+      name: pmp_smoketest_napot
+      sw_images: ["sw/device/tests/pmp_smoketest_napot:1"]
+    }
+    {
+      name: pmp_smoketest_tor
+      sw_images: ["sw/device/tests/pmp_smoketest_tor:1"]
+    }
+    {
+      name: sha256_test
+      sw_images: ["sw/device/tests/sha256_test:1"]
+    }
+    {
+      name: usbdev_test
+      sw_images: ["sw/device/tests/usbdev_test:1"]
+    }
+  ]
+
+  // List of regressions.
+  regressions: [
+    {
+      name: smoke
+      tests: []
+    }
+  ]
+}