esiaccel 0.1.4.dev31__cp310-cp310-win_amd64.whl → 0.2.3.dev80__cp310-cp310-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. esiaccel/CosimBackend.dll +0 -0
  2. esiaccel/CosimBackend.lib +0 -0
  3. esiaccel/CosimRpc.dll +0 -0
  4. esiaccel/CosimRpc.lib +0 -0
  5. esiaccel/ESICppRuntime.dll +0 -0
  6. esiaccel/ESICppRuntime.lib +0 -0
  7. esiaccel/EsiCosimDpiServer.dll +0 -0
  8. esiaccel/EsiCosimDpiServer.lib +0 -0
  9. esiaccel/{lib/MtiPli.dll → MtiPli.dll} +0 -0
  10. esiaccel/{lib/MtiPli.lib → MtiPli.lib} +0 -0
  11. esiaccel/__init__.py +22 -4
  12. esiaccel/abseil_dll.dll +0 -0
  13. esiaccel/accelerator.py +37 -5
  14. esiaccel/cares.dll +0 -0
  15. esiaccel/cmake/esiaccelConfig.cmake +34 -0
  16. esiaccel/codegen.py +3 -3
  17. esiaccel/cosim/Cosim_CycleCount.sv +84 -0
  18. esiaccel/cosim/Cosim_Endpoint.sv +61 -32
  19. esiaccel/cosim/driver.cpp +6 -6
  20. esiaccel/cosim/driver.sv +14 -0
  21. esiaccel/cosim/questa.py +141 -0
  22. esiaccel/cosim/simulator.py +383 -0
  23. esiaccel/cosim/verilator.py +92 -0
  24. esiaccel/esi-cosim.py +104 -0
  25. esiaccel/esiCppAccel.cp312-win_amd64.pyd +0 -0
  26. esiaccel/esiquery.exe +0 -0
  27. esiaccel/include/esi/Accelerator.h +14 -17
  28. esiaccel/include/esi/CLI.h +5 -5
  29. esiaccel/include/esi/Common.h +19 -2
  30. esiaccel/include/esi/Context.h +17 -9
  31. esiaccel/include/esi/Design.h +9 -4
  32. esiaccel/include/esi/Manifest.h +0 -2
  33. esiaccel/include/esi/Ports.h +230 -23
  34. esiaccel/include/esi/Services.h +92 -31
  35. esiaccel/include/esi/Types.h +162 -10
  36. esiaccel/include/esi/Values.h +313 -0
  37. esiaccel/include/esi/backends/Cosim.h +5 -12
  38. esiaccel/include/esi/backends/RpcClient.h +97 -0
  39. esiaccel/include/esi/backends/RpcServer.h +21 -3
  40. esiaccel/libcrypto-3-x64.dll +0 -0
  41. esiaccel/libprotobuf.dll +0 -0
  42. esiaccel/libssl-3-x64.dll +0 -0
  43. esiaccel/re2.dll +0 -0
  44. esiaccel/types.py +66 -26
  45. esiaccel/utils.py +21 -3
  46. esiaccel/zlib1.dll +0 -0
  47. {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/METADATA +1 -1
  48. esiaccel-0.2.3.dev80.dist-info/RECORD +58 -0
  49. esiaccel/bin/esi-cosim.py +0 -423
  50. esiaccel/bin/esiquery.exe +0 -0
  51. esiaccel/esiCppAccel.cp310-win_amd64.pyd +0 -0
  52. esiaccel/lib/EsiCosimDpiServer.dll +0 -0
  53. esiaccel/lib/EsiCosimDpiServer.lib +0 -0
  54. esiaccel-0.1.4.dev31.dist-info/RECORD +0 -43
  55. {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/WHEEL +0 -0
  56. {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/entry_points.txt +0 -0
  57. {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/licenses/LICENSE +0 -0
  58. {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/top_level.txt +0 -0
esiaccel/CosimBackend.dll CHANGED
Binary file
esiaccel/CosimBackend.lib CHANGED
Binary file
esiaccel/CosimRpc.dll ADDED
Binary file
esiaccel/CosimRpc.lib ADDED
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
esiaccel/__init__.py CHANGED
@@ -1,13 +1,31 @@
1
1
  # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2
2
  # See https://llvm.org/LICENSE.txt for license information.
3
3
  # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
-
5
- from .accelerator import AcceleratorConnection
4
+ import sys
5
+ import os
6
+ from .accelerator import AcceleratorConnection, Context, LogLevel
6
7
 
7
8
  from .esiCppAccel import (AppID, Type, BundleType, ChannelType, ArrayType,
8
9
  StructType, BitsType, UIntType, SIntType)
9
10
 
10
11
  __all__ = [
11
- "AcceleratorConnection", "AppID", "Type", "BundleType", "ChannelType",
12
- "ArrayType", "StructType", "BitsType", "UIntType", "SIntType"
12
+ "AcceleratorConnection", "AppID", "Context", "LogLevel", "Type",
13
+ "BundleType", "ChannelType", "ArrayType", "StructType", "BitsType",
14
+ "UIntType", "SIntType"
13
15
  ]
16
+
17
+ if sys.platform == "win32":
18
+ """Ensure that ESI libraries are in the dll path on Windows. Necessary to
19
+ call when users build against the esiaccel-provided prebuilt CMake/prebuilt
20
+ libraries, before they are loaded via. python.
21
+ """
22
+ from .utils import get_dll_dir
23
+ os.add_dll_directory(str(get_dll_dir()))
24
+
25
+
26
+ def connect(platform: str, connection_str: str) -> "AcceleratorConnection":
27
+ """Connect to an accelerator using the specified platform and connection
28
+ string."""
29
+ ctxt = Context.default()
30
+ return AcceleratorConnection(ctxt,
31
+ ctxt.cpp_ctxt.connect(platform, connection_str))
Binary file
esiaccel/accelerator.py CHANGED
@@ -15,19 +15,51 @@ from typing import Dict, List, Optional
15
15
  from .types import BundlePort
16
16
  from . import esiCppAccel as cpp
17
17
 
18
- # Global context for the C++ side.
19
- ctxt = cpp.Context()
18
+ LogLevel = cpp.LogLevel
19
+
20
+
21
+ class Context:
22
+ """A context for ESI accelerator connections. The underlying C++ context owns
23
+ everything assocated with it including types, accelerator connections, and
24
+ the accelerator facade/interface (aka Accelerator) itself. It must not be
25
+ garbage collected while any accelerators or connections that it owns are still
26
+ in use as they will be disconnected and destroyed when the context is
27
+ destroyed."""
28
+
29
+ _default: Optional["Context"] = None
30
+
31
+ def __init__(self, log_level: cpp.LogLevel = cpp.LogLevel.Warning):
32
+ self.cpp_ctxt = cpp.Context()
33
+ self.set_stdio_logger(log_level)
34
+
35
+ @staticmethod
36
+ def default() -> "Context":
37
+ if Context._default is None:
38
+ Context._default = Context()
39
+ return Context._default
40
+
41
+ def set_stdio_logger(self, level: cpp.LogLevel):
42
+ self.cpp_ctxt.set_stdio_logger(level)
43
+
44
+ def connect(self, platform: str,
45
+ connection_str: str) -> "AcceleratorConnection":
46
+ return AcceleratorConnection(
47
+ self, self.cpp_ctxt.connect(platform, connection_str))
20
48
 
21
49
 
22
50
  class AcceleratorConnection:
23
51
  """A connection to an ESI accelerator."""
24
52
 
25
- def __init__(self, platform: str, connection_str: str):
26
- self.cpp_accel = cpp.AcceleratorConnection(ctxt, platform, connection_str)
53
+ def __init__(self, ctxt: Context, cpp_accel: cpp.AcceleratorConnection):
54
+ if not isinstance(ctxt, Context):
55
+ raise TypeError("ctxt must be a Context")
56
+ self.ctxt = ctxt
57
+ self.cpp_accel = cpp_accel
27
58
 
28
59
  def manifest(self) -> cpp.Manifest:
29
60
  """Get and parse the accelerator manifest."""
30
- return cpp.Manifest(ctxt, self.cpp_accel.sysinfo().json_manifest())
61
+ return cpp.Manifest(self.ctxt.cpp_ctxt,
62
+ self.cpp_accel.sysinfo().json_manifest())
31
63
 
32
64
  def sysinfo(self) -> cpp.SysInfo:
33
65
  return self.cpp_accel.sysinfo()
esiaccel/cares.dll ADDED
Binary file
@@ -13,3 +13,37 @@ else()
13
13
  IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/.././libESICppRuntime.so"
14
14
  )
15
15
  endif()
16
+
17
+ add_library(esiaccel::CosimRpc SHARED IMPORTED)
18
+ set_target_properties(esiaccel::CosimRpc PROPERTIES
19
+ INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/../include"
20
+ INTERFACE_LINK_LIBRARIES esiaccel::ESICppRuntime
21
+ )
22
+
23
+ if(WIN32)
24
+ set_target_properties(esiaccel::CosimRpc PROPERTIES
25
+ IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../CosimRpc.dll"
26
+ IMPORTED_IMPLIB "${CMAKE_CURRENT_LIST_DIR}/../CosimRpc.lib"
27
+ )
28
+ else()
29
+ set_target_properties(esiaccel::CosimRpc PROPERTIES
30
+ IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/.././libCosimRpc.so"
31
+ )
32
+ endif()
33
+
34
+ add_library(esiaccel::CosimBackend SHARED IMPORTED)
35
+ set_target_properties(esiaccel::CosimBackend PROPERTIES
36
+ INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/../include"
37
+ INTERFACE_LINK_LIBRARIES "esiaccel::ESICppRuntime;esiaccel::CosimRpc"
38
+ )
39
+
40
+ if(WIN32)
41
+ set_target_properties(esiaccel::CosimBackend PROPERTIES
42
+ IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../CosimBackend.dll"
43
+ IMPORTED_IMPLIB "${CMAKE_CURRENT_LIST_DIR}/../CosimBackend.lib"
44
+ )
45
+ else()
46
+ set_target_properties(esiaccel::CosimBackend PROPERTIES
47
+ IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/.././libCosimBackend.so"
48
+ )
49
+ endif()
esiaccel/codegen.py CHANGED
@@ -6,7 +6,7 @@
6
6
  # with the runtime, though it is intended to be extensible for other languages.
7
7
 
8
8
  from typing import List, TextIO, Type, Optional
9
- from .accelerator import AcceleratorConnection
9
+ from .accelerator import AcceleratorConnection, Context
10
10
  from .esiCppAccel import ModuleInfo
11
11
  from . import types
12
12
 
@@ -171,12 +171,12 @@ def run(generator: Type[Generator] = CppGenerator,
171
171
 
172
172
  conn: AcceleratorConnection
173
173
  if args.file is not None:
174
- conn = AcceleratorConnection("trace", f"-:{args.file}")
174
+ conn = Context.default().connect("trace", f"-:{args.file}")
175
175
  elif args.platform is not None:
176
176
  if args.connection is None:
177
177
  print("Must specify --connection with --platform")
178
178
  return 1
179
- conn = AcceleratorConnection(args.platform, args.connection)
179
+ conn = Context.default().connect(args.platform, args.connection)
180
180
  else:
181
181
  print("Must specify either --file or --platform")
182
182
  return 1
@@ -0,0 +1,84 @@
1
+ //===- Cosim_CycleCount.sv - ESI cycle counter module -------*- verilog -*-===//
2
+ //
3
+ // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
+ // See https://llvm.org/LICENSE.txt for license information.
5
+ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
+ //
7
+ //===----------------------------------------------------------------------===//
8
+ //
9
+ // A cosimulated design should instantiate this ONCE to provide cycle count
10
+ // information to the ESI runtime. The module maintains a 64-bit cycle counter
11
+ // and uses request/response channels to provide the count to the runtime.
12
+ //
13
+ //===----------------------------------------------------------------------===//
14
+
15
+ import Cosim_DpiPkg::*;
16
+
17
+ module Cosim_CycleCount
18
+ #(
19
+ // Core clock frequency in Hz. Used by the runtime to convert cycles to time.
20
+ parameter longint unsigned CORE_CLOCK_FREQUENCY_HZ = 0
21
+ )(
22
+ input logic clk,
23
+ input logic rst
24
+ );
25
+
26
+ // 64-bit cycle counter.
27
+ longint unsigned cycle_count;
28
+
29
+ always_ff @(posedge clk) begin
30
+ if (rst)
31
+ cycle_count <= 0;
32
+ else
33
+ cycle_count <= cycle_count + 1;
34
+ end
35
+
36
+ // Request channel (From Host)
37
+ // 0-bit message used as a trigger.
38
+ wire req_valid;
39
+ wire req_ready;
40
+
41
+ Cosim_Endpoint_FromHost #(
42
+ .ENDPOINT_ID("__cosim_cycle_count.arg"),
43
+ .FROM_HOST_TYPE_ID("!esi.channel<i1>"),
44
+ .FROM_HOST_SIZE_BITS(1)
45
+ ) req_ep (
46
+ .clk(clk),
47
+ .rst(rst),
48
+ .DataOutValid(req_valid),
49
+ .DataOutReady(req_ready),
50
+ .DataOut()
51
+ );
52
+
53
+ // Response channel (To Host)
54
+ typedef struct packed {
55
+ longint unsigned cycle;
56
+ longint unsigned freq;
57
+ } RespStruct;
58
+
59
+ wire resp_ready;
60
+ wire resp_valid;
61
+ RespStruct resp_data;
62
+
63
+ assign resp_data.cycle = cycle_count;
64
+ assign resp_data.freq = CORE_CLOCK_FREQUENCY_HZ;
65
+
66
+ // Handshake logic:
67
+ // When request arrives (req_valid), we are ready to send response (resp_valid).
68
+ // We consume request only when response is accepted.
69
+ assign resp_valid = req_valid;
70
+ assign req_ready = resp_ready;
71
+
72
+ Cosim_Endpoint_ToHost #(
73
+ .ENDPOINT_ID("__cosim_cycle_count.result"),
74
+ .TO_HOST_TYPE_ID("struct{cycle:int<64>,freq:int<64>}"),
75
+ .TO_HOST_SIZE_BITS(128)
76
+ ) resp_ep (
77
+ .clk(clk),
78
+ .rst(rst),
79
+ .DataInValid(resp_valid),
80
+ .DataInReady(resp_ready),
81
+ .DataIn(resp_data)
82
+ );
83
+
84
+ endmodule
@@ -9,6 +9,8 @@
9
9
  // Package: Cosim_DpiPkg
10
10
  //
11
11
  // Main cosim <--> dpi bridge module.
12
+
13
+
12
14
  //
13
15
  //===----------------------------------------------------------------------===//
14
16
 
@@ -80,15 +82,6 @@ module Cosim_Endpoint_ToHost
80
82
  TO_HOST_SIZE_BYTES_FLOOR_IN_BITS];
81
83
  endgenerate
82
84
 
83
- initial begin
84
- $display("TO_HOST_SIZE_BITS: %d", TO_HOST_SIZE_BITS);
85
- $display("TO_HOST_SIZE_BYTES: %d", TO_HOST_SIZE_BYTES);
86
- $display("TO_HOST_SIZE_BITS_DIFF: %d", TO_HOST_SIZE_BITS_DIFF);
87
- $display("TO_HOST_SIZE_BYTES_FLOOR: %d", TO_HOST_SIZE_BYTES_FLOOR);
88
- $display("TO_HOST_SIZE_BYTES_FLOOR_IN_BITS: %d",
89
- TO_HOST_SIZE_BYTES_FLOOR_IN_BITS);
90
- end
91
-
92
85
  endmodule
93
86
 
94
87
  module Cosim_Endpoint_FromHost
@@ -118,9 +111,8 @@ module Cosim_Endpoint_FromHost
118
111
  $error("Cosim endpoint (%s) register failed: %d", ENDPOINT_ID, rc);
119
112
  end
120
113
 
121
- /// *******************
122
- /// Data out management.
123
- ///
114
+ /// ***********************
115
+ /// Useful constants.
124
116
 
125
117
  localparam int FROM_HOST_SIZE_BYTES = int'((FROM_HOST_SIZE_BITS+7)/8);
126
118
  // The number of bits over a byte.
@@ -129,13 +121,30 @@ module Cosim_Endpoint_FromHost
129
121
  localparam int FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS
130
122
  = FROM_HOST_SIZE_BYTES_FLOOR * 8;
131
123
 
124
+ // Buffer to hold incoming data directly from the DPI calls.
132
125
  byte unsigned DataOutBuffer[FROM_HOST_SIZE_BYTES-1:0];
126
+
127
+ // Pipeline interface signals for buffering DataOut.
128
+ // DataOut_a_valid is asserted when a complete message is available in
129
+ // DataOut_a buffer and waiting to be accepted by the skid buffer.
130
+ logic DataOut_a_valid;
131
+ // Packed representation of the byte buffer to feed the skid input.
132
+ logic [FROM_HOST_SIZE_BITS-1:0] DataOut_a;
133
+ // Ready/valid wires between this module and the skid buffer.
134
+ wire DataOut_a_ready;
135
+ wire DataOut_x_valid;
136
+ wire [FROM_HOST_SIZE_BITS-1:0] DataOut_x;
137
+
133
138
  always @(posedge clk) begin
134
139
  if (~rst) begin
135
- if (DataOutValid && DataOutReady) // A transfer occurred.
136
- DataOutValid <= 1'b0;
137
-
138
- if (!DataOutValid || DataOutReady) begin
140
+ // If the skid buffer accepted the input token this cycle, clear the
141
+ // internal valid that indicates we have buffered data.
142
+ if (DataOut_a_valid && DataOut_a_ready)
143
+ DataOut_a_valid <= 1'b0;
144
+
145
+ // Only attempt to fetch data from the host when the skid buffer can
146
+ // accept it (DataOut_a_ready).
147
+ if (!DataOut_a_valid && DataOut_a_ready) begin
139
148
  int data_limit;
140
149
  int rc;
141
150
 
@@ -149,7 +158,7 @@ module Cosim_Endpoint_FromHost
149
158
  ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit, rc);
150
159
  end else if (rc == 0) begin
151
160
  if (data_limit == FROM_HOST_SIZE_BYTES)
152
- DataOutValid <= 1'b1;
161
+ DataOut_a_valid <= 1'b1;
153
162
  else if (data_limit == 0)
154
163
  begin end // No message.
155
164
  else
@@ -159,31 +168,51 @@ module Cosim_Endpoint_FromHost
159
168
  end
160
169
  end
161
170
  end else begin
162
- DataOutValid <= 1'b0;
171
+ DataOut_a_valid <= 1'b0;
163
172
  end
164
173
  end
165
174
 
166
- // Assign packed output bit array from unpacked byte array.
175
+ // Pack the byte array into a single vector that will be handed to the
176
+ // skid buffer as its input payload.
167
177
  genvar iOut;
168
178
  generate
169
179
  for (iOut=0; iOut<FROM_HOST_SIZE_BYTES_FLOOR; iOut++)
170
- assign DataOut[((iOut+1)*8)-1:iOut*8] = DataOutBuffer[iOut];
180
+ assign DataOut_a[((iOut+1)*8)-1:iOut*8] = DataOutBuffer[iOut];
171
181
  if (FROM_HOST_SIZE_BITS_DIFF != 0)
172
- // If the type is not a multiple of 8, we've got to copy the extra bits.
173
- assign DataOut[(FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS +
174
- FROM_HOST_SIZE_BITS_DIFF - 1) :
175
- FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS]
182
+ // If the type is not a multiple of 8, copy the extra bits.
183
+ assign DataOut_a[(FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS +
184
+ FROM_HOST_SIZE_BITS_DIFF - 1) :
185
+ FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS]
176
186
  = DataOutBuffer[FROM_HOST_SIZE_BYTES - 1]
177
187
  [FROM_HOST_SIZE_BITS_DIFF - 1 : 0];
178
188
  endgenerate
179
189
 
180
- initial begin
181
- $display("FROM_HOST_SIZE_BITS: %d", FROM_HOST_SIZE_BITS);
182
- $display("FROM_HOST_SIZE_BYTES: %d", FROM_HOST_SIZE_BYTES);
183
- $display("FROM_HOST_SIZE_BITS_DIFF: %d", FROM_HOST_SIZE_BITS_DIFF);
184
- $display("FROM_HOST_SIZE_BYTES_FLOOR: %d", FROM_HOST_SIZE_BYTES_FLOOR);
185
- $display("FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS: %d",
186
- FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS);
187
- end
190
+ /// *******************
191
+ /// Data out management.
192
+ ///
193
+ /// It has been observed that some simulators (verilator) does not handle
194
+ /// combinational driving from DPI well (resulting in non-determinism wrt
195
+ /// some of the combinational outputs being dropped/replicated). Questa does
196
+ /// not show this behavior.
197
+ /// A mitigation is to add a skid buffer to decouple the DPI interface
198
+ /// from the output interface.
199
+
200
+ // Instantiate a single-stage pipeline to buffer tokens that arrive from
201
+ // the host and present them to the module's output with proper
202
+ // ready/valid handshaking.
203
+ ESI_PipelineStage #(.WIDTH(FROM_HOST_SIZE_BITS)) out_pipe (
204
+ .clk(clk),
205
+ .rst(rst),
206
+ .a_valid(DataOut_a_valid),
207
+ .a(DataOut_a),
208
+ .a_ready(DataOut_a_ready),
209
+ .x_valid(DataOut_x_valid),
210
+ .x(DataOut_x),
211
+ .x_ready(DataOutReady)
212
+ );
213
+
214
+ // Drive the module's outward-facing signals from the pipeline output.
215
+ assign DataOutValid = DataOut_x_valid;
216
+ assign DataOut = DataOut_x;
188
217
 
189
218
  endmodule
esiaccel/cosim/driver.cpp CHANGED
@@ -30,7 +30,7 @@
30
30
  #include CONCAT3(V,TOP_MODULE,.h)
31
31
  // clang-format on
32
32
 
33
- #include "verilated_vcd_c.h"
33
+ #include "verilated_fst_c.h"
34
34
 
35
35
  #include "signal.h"
36
36
  #include <iostream>
@@ -64,12 +64,12 @@ int main(int argc, char **argv) {
64
64
  }
65
65
 
66
66
  #ifdef TRACE
67
- VerilatedVcdC *tfp = nullptr;
67
+ VerilatedFstC *tfp = nullptr;
68
68
  #endif
69
69
 
70
70
  if (waveformFile) {
71
71
  #ifdef TRACE
72
- tfp = new VerilatedVcdC();
72
+ tfp = new VerilatedFstC();
73
73
  Verilated::traceEverOn(true);
74
74
  dut.trace(tfp, 99); // Trace 99 levels of hierarchy
75
75
  tfp->open(waveformFile);
@@ -95,11 +95,11 @@ int main(int argc, char **argv) {
95
95
  // Run for a few cycles with reset held.
96
96
  for (timeStamp = 0; timeStamp < 8 && !Verilated::gotFinish(); timeStamp++) {
97
97
  dut.eval();
98
- dut.clk = !dut.clk;
99
98
  #ifdef TRACE
100
99
  if (tfp)
101
100
  tfp->dump(timeStamp);
102
101
  #endif
102
+ dut.clk = !dut.clk;
103
103
  }
104
104
 
105
105
  // Take simulation out of reset.
@@ -108,12 +108,12 @@ int main(int argc, char **argv) {
108
108
  // Run for the specified number of cycles out of reset.
109
109
  for (; !Verilated::gotFinish() && !stopSimulation; timeStamp++) {
110
110
  dut.eval();
111
- dut.clk = !dut.clk;
112
-
113
111
  #ifdef TRACE
114
112
  if (tfp)
115
113
  tfp->dump(timeStamp);
116
114
  #endif
115
+ dut.clk = !dut.clk;
116
+
117
117
  if (debugPeriod)
118
118
  std::this_thread::sleep_for(std::chrono::milliseconds(debugPeriod));
119
119
  }
esiaccel/cosim/driver.sv CHANGED
@@ -18,8 +18,22 @@
18
18
  `define TOP_MODULE ESI_Cosim_Top
19
19
  `endif
20
20
 
21
+ // Allow reading environment variables to control waveform dumping.
22
+ import "DPI-C" function string getenv(input string env_name);
23
+
21
24
  module driver();
22
25
 
26
+ // If the SAVE_WAVE environment variable is set, dump a VCD waveform to that
27
+ // filename.
28
+ initial begin
29
+ string save_wave = getenv("SAVE_WAVE");
30
+ if (save_wave != "") begin
31
+ $display("[driver] Saving waveform to %s", save_wave);
32
+ $dumpfile(save_wave);
33
+ $dumpvars(0, driver);
34
+ end
35
+ end
36
+
23
37
  logic clk = 0;
24
38
  logic rst = 0;
25
39
 
@@ -0,0 +1,141 @@
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
+
5
+ import os
6
+ from pathlib import Path
7
+ from typing import List, Optional, Callable, Dict
8
+
9
+ from .simulator import CosimCollateralDir, Simulator, SourceFiles
10
+
11
+
12
+ class Questa(Simulator):
13
+ """Run and compile funcs for Questasim."""
14
+
15
+ DefaultDriver = CosimCollateralDir / "driver.sv"
16
+
17
+ def __init__(
18
+ self,
19
+ sources: SourceFiles,
20
+ run_dir: Path,
21
+ debug: bool,
22
+ run_stdout_callback: Optional[Callable[[str], None]] = None,
23
+ run_stderr_callback: Optional[Callable[[str], None]] = None,
24
+ compile_stdout_callback: Optional[Callable[[str], None]] = None,
25
+ compile_stderr_callback: Optional[Callable[[str], None]] = None,
26
+ make_default_logs: bool = True,
27
+ macro_definitions: Optional[Dict[str, str]] = None,
28
+ # An optional list of questa error codes to suppress
29
+ suppressed_questa_errors: Optional[List[int]] = None):
30
+ super().__init__(
31
+ sources=sources,
32
+ run_dir=run_dir,
33
+ debug=debug,
34
+ run_stdout_callback=run_stdout_callback,
35
+ run_stderr_callback=run_stderr_callback,
36
+ compile_stdout_callback=compile_stdout_callback,
37
+ compile_stderr_callback=compile_stderr_callback,
38
+ make_default_logs=make_default_logs,
39
+ macro_definitions=macro_definitions,
40
+ )
41
+ self.suppressed_questa_errors = suppressed_questa_errors
42
+
43
+ # Questa doesn't use stderr for error messages. Everything goes to stdout.
44
+ UsesStderr = False
45
+
46
+ def internal_compile_commands(self) -> List[str]:
47
+ cmds = [
48
+ "onerror { quit -f -code 1 }",
49
+ ]
50
+ sources = self.sources.rtl_sources
51
+ sources.append(Questa.DefaultDriver)
52
+
53
+ # Format macro definition command
54
+ if self.macro_definitions:
55
+ macro_definitions_cmd = " ".join([
56
+ f"+define+{k}={v}" if v is not None else f"+define+{k}"
57
+ for k, v in self.macro_definitions.items()
58
+ ])
59
+ else:
60
+ macro_definitions_cmd = ""
61
+
62
+ # Format error suppression command
63
+ if self.suppressed_questa_errors:
64
+ suppressed_questa_errors_cmd = " ".join(
65
+ [f"-suppress {ec}" for ec in self.suppressed_questa_errors])
66
+ else:
67
+ suppressed_questa_errors_cmd = ""
68
+
69
+ for src in sources:
70
+ cmds.append(
71
+ f"vlog -incr +acc -sv {macro_definitions_cmd} {suppressed_questa_errors_cmd} +define+TOP_MODULE={self.sources.top}"
72
+ f" +define+SIMULATION {src.as_posix()}")
73
+ cmds.append(f"vopt -incr driver -o driver_opt +acc")
74
+ return cmds
75
+
76
+ def compile_commands(self) -> List[List[str]]:
77
+ with open("compile.do", "w") as f:
78
+ for cmd in self.internal_compile_commands():
79
+ f.write(cmd)
80
+ f.write("\n")
81
+ f.write("quit\n")
82
+ return [
83
+ ["vsim", "-batch", "-do", "compile.do"],
84
+ ]
85
+
86
+ def run_command(self, gui: bool) -> List[str]:
87
+ vsim = "vsim"
88
+ # Note: vsim exit codes say nothing about the test run's pass/fail even
89
+ # if $fatal is encountered in the simulation.
90
+ if gui:
91
+ cmd = [
92
+ vsim,
93
+ "driver_opt",
94
+ ]
95
+ else:
96
+ cmd = [
97
+ vsim,
98
+ "driver_opt",
99
+ "-batch",
100
+ ]
101
+
102
+ if self.debug:
103
+ # Create waveform dump .do file
104
+ wave_file = Path("wave.do")
105
+ with wave_file.open("w") as f:
106
+ f.write("log -r /*\n")
107
+ cmd += [
108
+ "-do",
109
+ str(wave_file.resolve()),
110
+ ]
111
+ # Questa will by default log to a vsim.wlf file in the current
112
+ # directory.
113
+ print(
114
+ f"Debug mode enabled - waveform will be in {wave_file.resolve().parent / 'vsim.wlf'}"
115
+ )
116
+
117
+ cmd += [
118
+ "-do",
119
+ "run -all",
120
+ ]
121
+
122
+ for lib in self.sources.dpi_so_paths():
123
+ svLib = os.path.splitext(lib)[0]
124
+ cmd.append("-sv_lib")
125
+ cmd.append(svLib)
126
+ return cmd
127
+
128
+ def run(self,
129
+ inner_command: str,
130
+ gui: bool = False,
131
+ server_only: bool = False) -> int:
132
+ """Override the Simulator.run() to add a soft link in the run directory (to
133
+ the work directory) before running vsim the usual way."""
134
+
135
+ # Create a soft link to the work directory.
136
+ workDir = self.run_dir / "work"
137
+ if not workDir.exists():
138
+ os.symlink(Path(os.getcwd()) / "work", workDir)
139
+
140
+ # Run the simulation.
141
+ return super().run(inner_command, gui, server_only=server_only)