CIRCT 24.0.0git
Loading...
Searching...
No Matches
questa.py
Go to the documentation of this file.
1# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2# See https://llvm.org/LICENSE.txt for license information.
3# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5import os
6from pathlib import Path
7from typing import List, Optional, Callable, Dict
8
9from .simulator import CosimCollateralDir, Simulator, SourceFiles
10
11
13 """Run and compile funcs for Questasim."""
14
15 DefaultDriver = CosimCollateralDir / "driver.sv"
16
18 self,
19 sources: SourceFiles,
20 run_dir: Path,
21 debug: bool,
22 save_waveform: bool = False,
23 run_stdout_callback: Optional[Callable[[str], None]] = None,
24 run_stderr_callback: Optional[Callable[[str], None]] = None,
25 compile_stdout_callback: Optional[Callable[[str], None]] = None,
26 compile_stderr_callback: Optional[Callable[[str], None]] = None,
27 make_default_logs: bool = True,
28 macro_definitions: Optional[Dict[str, Optional[str]]] = None,
29 # An optional list of questa error codes to suppress
30 suppressed_questa_errors: Optional[List[int]] = None):
31 super().__init__(
32 sources=sources,
33 run_dir=run_dir,
34 debug=debug,
35 save_waveform=save_waveform,
36 run_stdout_callback=run_stdout_callback,
37 run_stderr_callback=run_stderr_callback,
38 compile_stdout_callback=compile_stdout_callback,
39 compile_stderr_callback=compile_stderr_callback,
40 make_default_logs=make_default_logs,
41 macro_definitions=macro_definitions,
42 )
43 self.suppressed_questa_errors = suppressed_questa_errors
44
45 # Questa doesn't use stderr for error messages. Everything goes to stdout.
46 UsesStderr = False
47
48 def internal_compile_commands(self) -> List[str]:
49 cmds = [
50 "onerror { quit -f -code 1 }",
51 ]
52 sources = self.sources.rtl_sources
53 sources.append(Questa.DefaultDriver)
54
55 # Format macro definition command
56 if self.macro_definitions:
57 macro_definitions_cmd = " ".join([
58 f"+define+{k}={v}" if v is not None else f"+define+{k}"
59 for k, v in self.macro_definitions.items()
60 ])
61 else:
62 macro_definitions_cmd = ""
63
64 # Format error suppression command
66 suppressed_questa_errors_cmd = " ".join(
67 [f"-suppress {ec}" for ec in self.suppressed_questa_errors])
68 else:
69 suppressed_questa_errors_cmd = ""
70
71 acc_flag = " +acc" if self.debug else ""
72 for src in sources:
73 cmds.append(
74 f"vlog -incr{acc_flag} -sv {macro_definitions_cmd} {suppressed_questa_errors_cmd} +define+TOP_MODULE={self.sources.top}"
75 f" +define+SIMULATION {src.as_posix()}")
76 cmds.append(f"vopt -incr driver -o driver_opt{acc_flag}")
77 return cmds
78
79 def compile_commands(self) -> List[Simulator.CompileStep]:
80 with open("compile.do", "w") as f:
81 for cmd in self.internal_compile_commands():
82 f.write(cmd)
83 f.write("\n")
84 f.write("quit\n")
85 return [
86 ["vsim", "-batch", "-do", "compile.do"],
87 ]
88
89 def run_command(self, gui: bool) -> List[str]:
90 vsim = "vsim"
91 # Note: vsim exit codes say nothing about the test run's pass/fail even
92 # if $fatal is encountered in the simulation.
93 if gui:
94 cmd = [
95 vsim,
96 "driver_opt",
97 ]
98 else:
99 cmd = [
100 vsim,
101 "driver_opt",
102 "-batch",
103 ]
104
105 if self.debug:
106 # Create waveform dump .do file
107 wave_file = Path("wave.do")
108 with wave_file.open("w") as f:
109 f.write("log -r /*\n")
110 cmd += [
111 "-do",
112 str(wave_file.resolve()),
113 ]
114 # Questa will by default log to a vsim.wlf file in the current
115 # directory.
116 print(
117 f"Debug mode enabled - waveform will be in {wave_file.resolve().parent / 'vsim.wlf'}"
118 )
119
120 cmd += [
121 "-do",
122 "run -all",
123 ]
124
125 for lib in self.sources.dpi_so_paths():
126 svLib = os.path.splitext(lib)[0]
127 cmd.append("-sv_lib")
128 cmd.append(svLib)
129 return cmd
130
131 def run(self,
132 inner_command: str,
133 gui: bool = False,
134 server_only: bool = False) -> int:
135 """Override the Simulator.run() to add a link in the run directory (to
136 the work directory) before running vsim the usual way."""
137
138 # Ensure the work library is accessible from run_dir. Compiles run in a
139 # different directory (e.g. a cached class compile) so we need a link/copy
140 # so vsim can find it.
141 workDir = self.run_dir / "work"
142 compiledWork = Path(os.getcwd()) / "work"
143 if not workDir.exists() and compiledWork.exists():
144 if os.name == "nt":
145 # os.symlink requires elevated privileges on Windows; use a junction
146 # (which doesn't need them) so compiled outputs remain shared.
147 import subprocess as _sp
148 _sp.run(
149 ["cmd", "/c", "mklink", "/J",
150 str(workDir),
151 str(compiledWork)],
152 check=True,
153 capture_output=True,
154 text=True,
155 )
156 else:
157 os.symlink(compiledWork, workDir, target_is_directory=True)
158
159 # Run the simulation.
160 return super().run(inner_command, gui, server_only=server_only)
static void print(TypedAttr val, llvm::raw_ostream &os)
__init__(self, SourceFiles sources, Path run_dir, bool debug, bool save_waveform=False, Optional[Callable[[str], None]] run_stdout_callback=None, Optional[Callable[[str], None]] run_stderr_callback=None, Optional[Callable[[str], None]] compile_stdout_callback=None, Optional[Callable[[str], None]] compile_stderr_callback=None, bool make_default_logs=True, Optional[Dict[str, Optional[str]]] macro_definitions=None, Optional[List[int]] suppressed_questa_errors=None)
Definition questa.py:30
List[str] internal_compile_commands(self)
Definition questa.py:48
suppressed_questa_errors
Definition questa.py:43
List[str] run_command(self, bool gui)
Definition questa.py:89
List[Simulator.CompileStep] compile_commands(self)
Definition questa.py:79