CIRCT 24.0.0git
Loading...
Searching...
No Matches
test_verilator.py
Go to the documentation of this file.
1"""Unit tests for the Verilator cosim backend.
2
3These tests exercise the command-generation and CMake-template logic of the
4Verilator class *without* requiring the compiled ``esiCppAccel`` C++
5extension. We achieve this by inserting a ``MagicMock`` for the extension
6module before the real package is imported.
7"""
8
9import os
10import runpy
11import shutil
12import sys
13from pathlib import Path
14from unittest import mock
15from unittest.mock import MagicMock
16
17import pytest
18
19# ---------------------------------------------------------------------------
20# Provide a comprehensive mock for the native extension so we can import the
21# pure-Python cosim modules without a full C++ build.
22# ---------------------------------------------------------------------------
23_accel_mock = MagicMock()
24sys.modules["esiaccel.esiCppAccel"] = _accel_mock
25
26# Now we can safely import the cosim modules.
27from esiaccel.cosim.verilator import Verilator # noqa: E402
28from esiaccel.cosim.simulator import (
29 available_simulators, # noqa: E402
30 get_simulator,
31 is_simulator_available,
32 SourceFiles)
33
34
35def _make_verilator(run_dir,
36 top="TestTop",
37 debug=False,
38 dpi_so=None,
39 macros=None):
40 """Create a Verilator instance with minimal setup."""
41 sources = SourceFiles(top)
42 if dpi_so is not None:
43 sources.dpi_so = dpi_so
44 return Verilator(
45 sources=sources,
46 run_dir=run_dir,
47 debug=debug,
48 make_default_logs=False,
49 macro_definitions=macros,
50 )
51
52
53def _make_cmake_verilator(tmp_path, monkeypatch):
54 root = tmp_path / "verilator"
55 fake_bin = root / "bin" / "verilator_bin"
56 fake_bin.parent.mkdir(parents=True)
57 fake_bin.touch()
58 (root / "include").mkdir()
59 (root / "include" / "verilated.h").touch()
60 monkeypatch.setenv("VERILATOR_PATH", str(fake_bin))
61 monkeypatch.setenv("VERILATOR_ROOT", str(root))
62 monkeypatch.chdir(tmp_path)
63 monkeypatch.setattr(Verilator, "_use_cmake", property(lambda self: True))
64 monkeypatch.setattr(Verilator, "_raise_stack_limit",
65 staticmethod(lambda: None))
66 return _make_verilator(tmp_path)
67
68
69requires_verilator_bin = pytest.mark.skipif(
70 not is_simulator_available("verilator"), reason="verilator not found")
71
72
74
76 with pytest.raises(ValueError):
77 is_simulator_available("bogus")
78
80 monkeypatch.delenv("VERILATOR_PATH", raising=False)
81 monkeypatch.delenv("VERILATOR_ROOT", raising=False)
82 monkeypatch.setattr(shutil, "which", lambda name: None)
83 assert not is_simulator_available("verilator")
84 assert "verilator" not in available_simulators()
85
86 def test_verilator_available_from_env_path(self, monkeypatch, tmp_path):
87 root = tmp_path / "verilator"
88 (root / "bin").mkdir(parents=True)
89 pkg_root = root / "share" / "verilator"
90 (pkg_root / "include").mkdir(parents=True)
91 (pkg_root / "include" / "verilated.h").touch()
92 fake_bin = root / "bin" / "verilator_bin"
93 fake_bin.touch()
94
95 monkeypatch.setenv("VERILATOR_PATH", str(fake_bin))
96 monkeypatch.delenv("VERILATOR_ROOT", raising=False)
97 monkeypatch.setattr(shutil, "which", lambda name: None)
98 assert is_simulator_available("verilator")
99 assert "verilator" in available_simulators()
100
101 def test_invalid_verilator_path_env_raises(self, monkeypatch, tmp_path):
102 monkeypatch.setenv("VERILATOR_PATH",
103 str(tmp_path / "missing" / "verilator_bin"))
104 monkeypatch.delenv("VERILATOR_ROOT", raising=False)
105 monkeypatch.setattr(shutil, "which", lambda name: None)
106 with pytest.raises(RuntimeError, match="VERILATOR_PATH"):
107 is_simulator_available("verilator")
108
109 def test_invalid_verilator_root_env_raises(self, monkeypatch, tmp_path):
110 root = tmp_path / "verilator"
111 (root / "bin").mkdir(parents=True)
112 pkg_root = root / "share" / "verilator"
113 pkg_root.mkdir(parents=True)
114 fake_bin = root / "bin" / "verilator_bin"
115 fake_bin.touch()
116
117 monkeypatch.setenv("VERILATOR_PATH", str(fake_bin))
118 monkeypatch.setenv("VERILATOR_ROOT", str(pkg_root))
119 monkeypatch.setattr(shutil, "which", lambda name: None)
120 with pytest.raises(RuntimeError, match="VERILATOR_ROOT"):
121 is_simulator_available("verilator")
122
124 monkeypatch.setattr(shutil, "which", lambda name: None)
125 assert not is_simulator_available("questa")
126
127 def test_questa_available_from_path(self, monkeypatch):
128 monkeypatch.delenv("VERILATOR_PATH", raising=False)
129 monkeypatch.delenv("VERILATOR_ROOT", raising=False)
130
131 def _which(name):
132 if name == "vsim":
133 return "C:/questa/vsim.exe"
134 return None
135
136 monkeypatch.setattr(shutil, "which", _which)
137 assert is_simulator_available("questa")
138 assert available_simulators() == ["questa"]
139
140
142
143 @requires_verilator_bin
144 def test_uses_verilator_bin(self, tmp_path):
145 v = _make_verilator(tmp_path)
146 cmds = v.compile_commands()
147 assert Path(cmds[0][0]).stem == "verilator_bin"
148 assert Path(cmds[0][0]) == v.verilator_bin
149
150 def test_cmake_and_ninja_commands(self, tmp_path, monkeypatch):
151 v = _make_cmake_verilator(tmp_path, monkeypatch)
152 build_dir = tmp_path / "obj_dir" / "cmake_build"
153 build_dir.mkdir(parents=True)
154 with mock.patch.object(v, "_run_compile_command", return_value=0) as run:
155 cmds = v.compile_commands()
156 assert len(cmds) == 4
157 assert callable(cmds[1])
158 assert callable(cmds[2])
159 assert cmds[2]() == 0
160 assert cmds[3][0] == "ninja"
161 cmake_cmd = run.call_args.args[0]
162 assert cmake_cmd[0] == "cmake"
163 assert "-G" in cmake_cmd and "Ninja" in cmake_cmd
164
165 def test_configure_skips_when_inputs_unchanged(self, tmp_path, monkeypatch):
166 v = _make_cmake_verilator(tmp_path, monkeypatch)
167 build_dir = tmp_path / "obj_dir" / "cmake_build"
168 build_dir.mkdir(parents=True)
169 (build_dir / "build.ninja").touch()
170 v._cmake_dirty = False
171
172 with mock.patch.object(v, "_run_compile_command", return_value=0) as run:
173 configure = v.compile_commands()[2]
174 assert configure() == 0
175 assert configure() == 0
176
177 assert run.call_count == 1
178 assert (build_dir / Verilator._CMakeSignatureFilename).exists()
179
181 monkeypatch):
182 v = _make_cmake_verilator(tmp_path, monkeypatch)
183 build_dir = tmp_path / "obj_dir" / "cmake_build"
184 build_dir.mkdir(parents=True)
185 (build_dir / "build.ninja").touch()
186
187 with mock.patch.object(v, "_run_compile_command", return_value=0) as run:
188 configure = v.compile_commands()[2]
189 assert configure() == 0
190 run.reset_mock()
191 v._cmake_dirty = True
192 assert configure() == 0
193
194 run.assert_not_called()
195
196 def test_configure_runs_when_environment_changes(self, tmp_path, monkeypatch):
197 v = _make_cmake_verilator(tmp_path, monkeypatch)
198 build_dir = tmp_path / "obj_dir" / "cmake_build"
199 build_dir.mkdir(parents=True)
200 (build_dir / "build.ninja").touch()
201 v._cmake_dirty = False
202
203 with mock.patch.object(v, "_run_compile_command", return_value=0) as run:
204 monkeypatch.setenv("CXX", "first-cxx")
205 assert v.compile_commands()[2]() == 0
206 monkeypatch.setenv("CXX", "second-cxx")
207 assert v.compile_commands()[2]() == 0
208
209 assert run.call_count == 2
210 assert run.call_args_list[0].args[0] == run.call_args_list[1].args[0]
211
212 def test_failed_configure_is_not_cached(self, tmp_path, monkeypatch):
213 v = _make_cmake_verilator(tmp_path, monkeypatch)
214 build_dir = tmp_path / "obj_dir" / "cmake_build"
215 build_dir.mkdir(parents=True)
216 (build_dir / "build.ninja").touch()
217 v._cmake_dirty = False
218 signature_file = build_dir / Verilator._CMakeSignatureFilename
219
220 with mock.patch.object(v, "_run_compile_command",
221 side_effect=(1, 0)) as run:
222 configure = v.compile_commands()[2]
223 assert configure() == 1
224 assert not signature_file.exists()
225 assert configure() == 0
226
227 assert run.call_count == 2
228 assert signature_file.exists()
229
230 @requires_verilator_bin
232 """When using cmake, --exe and --build should not appear."""
233 v = _make_verilator(tmp_path)
234 if not v._use_cmake:
235 pytest.skip("cmake+ninja not available")
236 cmd = v.compile_commands()[0]
237 assert "--exe" not in cmd
238 assert "--build" not in cmd
239
240 @requires_verilator_bin
242 """When using cmake, -CFLAGS and -LDFLAGS should not appear."""
243 v = _make_verilator(tmp_path)
244 if not v._use_cmake:
245 pytest.skip("cmake+ninja not available")
246 cmd = v.compile_commands()[0]
247 assert "-CFLAGS" not in cmd
248 assert "-LDFLAGS" not in cmd
249
250 @requires_verilator_bin
252 """When using cmake, driver.cpp should not be in the verilator command."""
253 v = _make_verilator(tmp_path)
254 if not v._use_cmake:
255 pytest.skip("cmake+ninja not available")
256 cmd = v.compile_commands()[0]
257 assert not any("driver.cpp" in str(c) for c in cmd)
258
259 @requires_verilator_bin
260 def test_trace_flags_in_debug(self, tmp_path):
261 v = _make_verilator(tmp_path, debug=True)
262 cmd = v.compile_commands()[0]
263 assert "--trace-fst" in cmd
264 assert "--trace-structs" in cmd
265 assert "--trace-underscore" in cmd
266
268 fake_bin = tmp_path / "custom" / "verilator_bin"
269 fake_bin.parent.mkdir()
270 fake_bin.touch()
271 with mock.patch.dict(os.environ, {"VERILATOR_PATH": str(fake_bin)}):
272 v = _make_verilator(tmp_path)
273 assert v.verilator_bin == fake_bin.resolve()
274
276 fake_wrapper = tmp_path / "usr" / "bin" / "verilator"
277 fake_bin = fake_wrapper.parent / "verilator_bin"
278 fake_wrapper.parent.mkdir(parents=True)
279 fake_wrapper.touch()
280 fake_bin.touch()
281 with mock.patch.dict(os.environ, {"VERILATOR_PATH": str(fake_wrapper)}):
282 v = _make_verilator(tmp_path)
283 assert v.verilator_bin == fake_bin.resolve()
284
286 env_root = tmp_path / "env-verilator"
287 path_root = tmp_path / "path-verilator"
288 (env_root / "bin").mkdir(parents=True)
289 (path_root / "bin").mkdir(parents=True)
290 env_bin = env_root / "bin" / "verilator_bin"
291 path_bin = path_root / "bin" / "verilator_bin"
292 env_bin.touch()
293 path_bin.touch()
294
295 with mock.patch.dict(os.environ, {"VERILATOR_PATH": str(env_bin)}):
296 with mock.patch("shutil.which", return_value=str(path_bin)):
297 assert Verilator._find_verilator_bin() == env_bin.resolve()
298
300 with mock.patch.dict(os.environ, {}, clear=False):
301 os.environ.pop("VERILATOR_ROOT", None)
302 os.environ.pop("VERILATOR_PATH", None)
303 with mock.patch("shutil.which", return_value=None):
304 v = _make_verilator(tmp_path)
305 with pytest.raises(RuntimeError, match="Cannot find verilator_bin"):
306 v.compile_commands()
307
308 @requires_verilator_bin
309 def test_macro_definitions(self, tmp_path):
310 v = _make_verilator(tmp_path, macros={"FOO": "BAR", "BAZ": None})
311 cmd = v.compile_commands()[0]
312 assert "+define+FOO=BAR" in cmd
313 assert "+define+BAZ" in cmd
314
315 @pytest.mark.parametrize("name", ("verilator", "questa"))
316 def test_get_simulator_macro_definitions(self, tmp_path, name):
317 sources = SourceFiles("TestTop")
318 simulator = get_simulator(name,
319 sources,
320 tmp_path,
321 False,
322 macro_definitions={
323 "FOO": "BAR",
324 "BAZ": None
325 })
326 assert simulator.macro_definitions == {"FOO": "BAR", "BAZ": None}
327
328
330 # Files named in `filelist.f` come first, in the listed order, then any
331 # other RTL files sorted by name. Nothing is added twice.
332 for name in ("A.sv", "zPkg.sv", "B.v", "notes.txt"):
333 (tmp_path / name).touch()
334 (tmp_path / "sub").mkdir()
335 (tmp_path / "sub" / "C.sv").touch()
336 (tmp_path / "filelist.f").write_text("zPkg.sv\n\nB.v\nmissing.sv\n")
337
338 sources = SourceFiles("TestTop")
339 sources.add_dir(tmp_path)
340 assert sources.user == [
341 tmp_path / "zPkg.sv", tmp_path / "B.v", tmp_path / "A.sv",
342 tmp_path / "sub" / "C.sv"
343 ]
344
345
347 for name in ("b.sv", "A.sv"):
348 (tmp_path / name).touch()
349 sources = SourceFiles("TestTop")
350 sources.add_dir(tmp_path)
351 assert sources.user == [tmp_path / "A.sv", tmp_path / "b.sv"]
352
353
355 script = (Path(__file__).parents[2] / "cosim_dpi_server" / "esi-cosim.py")
356 script_globals = runpy.run_path(str(script))
357 main = script_globals["__main__"]
358 simulator = MagicMock()
359 simulator.run.return_value = 0
360 sources = MagicMock()
361 source_files_factory = MagicMock(return_value=sources)
362 simulator_factory = MagicMock(return_value=simulator)
363
364 with mock.patch.dict(main.__globals__, {
365 "SourceFiles": source_files_factory,
366 "get_simulator": simulator_factory,
367 }):
368 assert main([
369 "esi-cosim", "-DFOO=BAR", "--define", "BAZ", "--source",
370 str(tmp_path), "--no-compile", "--server-only"
371 ]) == 0
372
373 simulator_factory.assert_called_once_with("verilator",
374 sources,
375 Path("run"),
376 False,
377 False,
378 macro_definitions={
379 "FOO": "BAR",
380 "BAZ": None
381 })
382
383
384@requires_verilator_bin
386 """Tests for the make fallback when cmake/ninja are not available."""
387
388 def _make_no_cmake(self, tmp_path, **kwargs):
389 """Create a Verilator instance that thinks cmake/ninja are missing."""
390 v = _make_verilator(tmp_path, **kwargs)
391 return v
392
393 @pytest.fixture(autouse=True)
394 def _hide_cmake(self):
395 """Patch shutil.which so cmake and ninja appear absent."""
396 original_which = shutil.which
397
398 def _which_no_cmake(name, *args, **kwargs):
399 if name in ("cmake", "ninja"):
400 return None
401 return original_which(name, *args, **kwargs)
402
403 with mock.patch("shutil.which", side_effect=_which_no_cmake):
404 yield
405
406 def test_fallback_uses_make(self, tmp_path):
407 v = self._make_no_cmake(tmp_path)
408 cmds = v.compile_commands()
409 assert len(cmds) == 2
410 assert cmds[1][0] == "make"
411
412 def test_fallback_has_exe_flag(self, tmp_path):
413 v = self._make_no_cmake(tmp_path)
414 cmd = v.compile_commands()[0]
415 assert "--exe" in cmd
416
417 def test_fallback_has_cflags(self, tmp_path):
418 v = self._make_no_cmake(tmp_path)
419 cmd = v.compile_commands()[0]
420 assert "-CFLAGS" in cmd
421 idx = cmd.index("-CFLAGS")
422 assert "-DTOP_MODULE=TestTop" in cmd[idx + 1]
423
424 def test_fallback_has_driver(self, tmp_path):
425 v = self._make_no_cmake(tmp_path)
426 cmd = v.compile_commands()[0]
427 assert any("driver.cpp" in str(c) for c in cmd)
428
430 v = self._make_no_cmake(tmp_path, dpi_so=["EsiCosimDpiServer"])
431 cmd = v.compile_commands()[0]
432 assert "-LDFLAGS" in cmd
433 idx = cmd.index("-LDFLAGS")
434 assert "-lEsiCosimDpiServer" in cmd[idx + 1]
435
437 v = self._make_no_cmake(tmp_path, dpi_so=[])
438 cmd = v.compile_commands()[0]
439 assert "-LDFLAGS" not in cmd
440
442 v = self._make_no_cmake(tmp_path, debug=True)
443 cmd = v.compile_commands()[0]
444 idx = cmd.index("-CFLAGS")
445 assert "-DTRACE" in cmd[idx + 1]
446
447 def test_fallback_make_command(self, tmp_path):
448 v = self._make_no_cmake(tmp_path, top="MyTop")
449 cmds = v.compile_commands()
450 make_cmd = cmds[1]
451 assert make_cmd[0] == "make"
452 assert "-C" in make_cmd
453 assert "obj_dir" in make_cmd
454 assert "-f" in make_cmd
455 assert "VMyTop.mk" in make_cmd
456
457 def test_fallback_exe_path(self, tmp_path):
458 v = self._make_no_cmake(tmp_path, top="MyTop")
459 exe_name = "VMyTop.exe" if os.name == "nt" else "VMyTop"
460 with mock.patch.object(Path, "cwd", return_value=tmp_path):
461 cmd = v.run_command(gui=False)
462 assert cmd == [str(tmp_path / "obj_dir" / exe_name)]
463
464
466
467 def test_from_env(self, tmp_path):
468 root = tmp_path / "verilator"
469 root.mkdir()
470 (root / "include").mkdir()
471 (root / "include" / "verilated.h").touch()
472 with mock.patch.dict(os.environ, {"VERILATOR_ROOT": str(root)}):
473 v = _make_verilator(tmp_path)
474 assert v._find_verilator_root() == root
475
476 def test_from_bin_in_path(self, tmp_path):
477 root = tmp_path / "verilator"
478 (root / "bin").mkdir(parents=True)
479 pkg_root = root / "share" / "verilator"
480 (pkg_root / "include").mkdir(parents=True)
481 (pkg_root / "include" / "verilated.h").touch()
482 fake_bin = root / "bin" / "verilator_bin"
483 fake_bin.touch()
484 fake_bin.chmod(0o755)
485 with mock.patch.dict(os.environ, {}, clear=False):
486 # Clear both root and path env vars so the real Verilator install
487 # doesn't shadow the fake bin created for this test.
488 os.environ.pop("VERILATOR_ROOT", None)
489 os.environ.pop("VERILATOR_PATH", None)
490 with mock.patch("shutil.which", return_value=str(fake_bin)):
491 v = _make_verilator(tmp_path)
492 found = v._find_verilator_root()
493 assert found == pkg_root
494
496 with mock.patch.dict(os.environ, {}, clear=False):
497 # Clear both env vars so the real Verilator install doesn't satisfy
498 # root detection before the RuntimeError can be raised.
499 os.environ.pop("VERILATOR_ROOT", None)
500 os.environ.pop("VERILATOR_PATH", None)
501 with mock.patch("shutil.which", return_value=None):
502 v = _make_verilator(tmp_path)
503 assert v._find_verilator_root() is None
504
505 def test_invalid_env_raises(self, tmp_path):
506 root = tmp_path / "verilator"
507 root.mkdir()
508 with mock.patch.dict(os.environ, {"VERILATOR_ROOT": str(root)}):
509 v = _make_verilator(tmp_path)
510 with pytest.raises(RuntimeError, match="VERILATOR_ROOT"):
511 v._find_verilator_root()
512
513
515
516 def test_generates_cmake(self, tmp_path):
517 obj_dir = tmp_path / "obj_dir"
518 obj_dir.mkdir()
519 generated_sources = [obj_dir / "VTestTop.cpp"]
520 root = tmp_path / "verilator"
521 (root / "include").mkdir(parents=True)
522 (root / "include" / "verilated.h").touch()
523 with mock.patch.dict(os.environ, {"VERILATOR_ROOT": str(root)}):
524 v = _make_verilator(tmp_path, dpi_so=[])
525 build_dir = v._write_cmake(obj_dir, generated_sources)
526 assert (build_dir / "CMakeLists.txt").exists()
527 content = (build_dir / "CMakeLists.txt").read_text()
528 assert "VTestTop" in content
529 assert generated_sources[0].as_posix() in content
530 assert "verilated.cpp" in content
531 assert "verilated_threads.cpp" in content
532 assert "driver.cpp" in content
533
534 def test_trace_sources_in_debug(self, tmp_path):
535 obj_dir = tmp_path / "obj_dir"
536 obj_dir.mkdir()
537 generated_sources = [obj_dir / "VTestTop.cpp"]
538 root = tmp_path / "verilator"
539 (root / "include").mkdir(parents=True)
540 (root / "include" / "verilated.h").touch()
541 with mock.patch.dict(os.environ, {"VERILATOR_ROOT": str(root)}):
542 v = _make_verilator(tmp_path, debug=True, dpi_so=[])
543 build_dir = v._write_cmake(obj_dir, generated_sources)
544 content = (build_dir / "CMakeLists.txt").read_text()
545 assert "verilated_fst_c.cpp" in content
546 assert "TRACE" in content
547
548 @pytest.mark.parametrize(
549 ("filename", "expected"),
550 [
551 ("VTestTop___024root__Slow.cpp", True),
552 ("VTestTop__Syms__Slow.cpp", True),
553 ("VTestTop__Syms__ctor__0__Slow.cpp", True),
554 ("VTestTop__ConstPool__0__Slow.cpp", True),
555 ("VTestTop.cpp", False),
556 ("VTestTop___024root.cpp", False),
557 ],
558 )
559 def test_classifies_slow_generated_sources(self, filename, expected):
560 assert Verilator._is_slow(Path(filename)) is expected
561
563 obj_dir = tmp_path / "obj_dir"
564 obj_dir.mkdir()
565 generated_sources = [
566 obj_dir / "VTestTop.cpp", obj_dir / "VTestTop__Slow.cpp"
567 ]
568 pch_header = obj_dir / "VTestTop__pch.h"
569 root = tmp_path / "verilator"
570 (root / "include").mkdir(parents=True)
571 (root / "include" / "verilated.h").touch()
572 with mock.patch.dict(os.environ, {"VERILATOR_ROOT": str(root)}):
573 v = _make_verilator(tmp_path, dpi_so=[])
574 build_dir = v._write_cmake(obj_dir, generated_sources, pch_header)
575 content = (build_dir / "CMakeLists.txt").read_text()
576 assert "target_precompile_headers(vl_fast PRIVATE" in content
577 assert "target_precompile_headers(vl_slow PRIVATE" in content
578 assert "target_precompile_headers(VTestTop PRIVATE" not in content
579 assert "VTestTop__pch.h" in content
580 assert "SKIP_PRECOMPILE_HEADERS ON" not in content
581 assert "verilated.cpp" in content
582 assert "driver.cpp" in content
583
584
586
587 def test_exe_path_cmake(self, tmp_path):
588 v = _make_verilator(tmp_path, top="MyTop")
589 if not v._use_cmake:
590 pytest.skip("cmake+ninja not available")
591 exe_name = "VMyTop.exe" if os.name == "nt" else "VMyTop"
592 with mock.patch.object(Path, "cwd", return_value=tmp_path):
593 cmd = v.run_command(gui=False)
594 assert cmd == [str(tmp_path / "obj_dir" / "cmake_build" / exe_name)]
test_respects_verilator_path_env(self, tmp_path)
test_verilator_path_overrides_path(self, tmp_path)
test_configure_runs_when_environment_changes(self, tmp_path, monkeypatch)
test_driver_not_in_verilator_cmd_cmake(self, tmp_path)
test_configure_skips_when_inputs_unchanged(self, tmp_path, monkeypatch)
test_get_simulator_macro_definitions(self, tmp_path, name)
test_no_cflags_or_ldflags_cmake(self, tmp_path)
test_compile_commands_requires_verilator_bin(self, tmp_path)
test_no_exe_or_build_flags_cmake(self, tmp_path)
test_cmake_and_ninja_commands(self, tmp_path, monkeypatch)
test_configure_leaves_cmakelists_changes_to_ninja(self, tmp_path, monkeypatch)
test_failed_configure_is_not_cached(self, tmp_path, monkeypatch)
test_verilator_path_redirects_perl_wrapper(self, tmp_path)
test_fallback_trace_cflags_in_debug(self, tmp_path)
_make_no_cmake(self, tmp_path, **kwargs)
test_fallback_no_ldflags_without_dpi(self, tmp_path)
test_fallback_has_exe_flag(self, tmp_path)
test_fallback_make_command(self, tmp_path)
test_fallback_has_ldflags_with_dpi(self, tmp_path)
test_verilator_unavailable_without_bin(self, monkeypatch)
test_questa_available_from_path(self, monkeypatch)
test_invalid_verilator_root_env_raises(self, monkeypatch, tmp_path)
test_verilator_available_from_env_path(self, monkeypatch, tmp_path)
test_questa_unavailable_without_vsim(self, monkeypatch)
test_invalid_verilator_path_env_raises(self, monkeypatch, tmp_path)
test_trace_sources_in_debug(self, tmp_path)
test_classifies_slow_generated_sources(self, filename, expected)
test_enables_pch_for_generated_source_groups(self, tmp_path)
int main()
test_esi_cosim_macro_definitions(tmp_path)
test_source_files_add_dir_without_filelist(tmp_path)
test_source_files_add_dir_uses_filelist_order(tmp_path)
_make_cmake_verilator(tmp_path, monkeypatch)
_make_verilator(run_dir, top="TestTop", debug=False, dpi_so=None, macros=None)