esiaccel 0.2.2__cp312-cp312-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.
Potentially problematic release.
This version of esiaccel might be problematic. Click here for more details.
- esiaccel/CosimBackend.dll +0 -0
- esiaccel/CosimBackend.lib +0 -0
- esiaccel/CosimRpc.dll +0 -0
- esiaccel/CosimRpc.lib +0 -0
- esiaccel/ESICppRuntime.dll +0 -0
- esiaccel/ESICppRuntime.lib +0 -0
- esiaccel/EsiCosimDpiServer.dll +0 -0
- esiaccel/EsiCosimDpiServer.lib +0 -0
- esiaccel/MtiPli.dll +0 -0
- esiaccel/MtiPli.lib +0 -0
- esiaccel/__init__.py +31 -0
- esiaccel/abseil_dll.dll +0 -0
- esiaccel/accelerator.py +134 -0
- esiaccel/cares.dll +0 -0
- esiaccel/cmake/esiaccelConfig.cmake +49 -0
- esiaccel/codegen.py +197 -0
- esiaccel/cosim/Cosim_DpiPkg.sv +85 -0
- esiaccel/cosim/Cosim_Endpoint.sv +218 -0
- esiaccel/cosim/Cosim_Manifest.sv +32 -0
- esiaccel/cosim/driver.cpp +131 -0
- esiaccel/cosim/driver.sv +74 -0
- esiaccel/cosim/questa.py +141 -0
- esiaccel/cosim/simulator.py +382 -0
- esiaccel/cosim/verilator.py +92 -0
- esiaccel/esi-cosim.py +104 -0
- esiaccel/esiCppAccel.cp312-win_amd64.pyd +0 -0
- esiaccel/esiquery.exe +0 -0
- esiaccel/include/esi/Accelerator.h +219 -0
- esiaccel/include/esi/CLI.h +77 -0
- esiaccel/include/esi/Common.h +182 -0
- esiaccel/include/esi/Context.h +82 -0
- esiaccel/include/esi/Design.h +132 -0
- esiaccel/include/esi/Engines.h +124 -0
- esiaccel/include/esi/Logging.h +231 -0
- esiaccel/include/esi/Manifest.h +70 -0
- esiaccel/include/esi/Ports.h +482 -0
- esiaccel/include/esi/Services.h +453 -0
- esiaccel/include/esi/Types.h +334 -0
- esiaccel/include/esi/Utils.h +102 -0
- esiaccel/include/esi/Values.h +313 -0
- esiaccel/include/esi/backends/Cosim.h +78 -0
- esiaccel/include/esi/backends/RpcClient.h +97 -0
- esiaccel/include/esi/backends/RpcServer.h +73 -0
- esiaccel/include/esi/backends/Trace.h +87 -0
- esiaccel/libcrypto-3-x64.dll +0 -0
- esiaccel/libprotobuf.dll +0 -0
- esiaccel/libssl-3-x64.dll +0 -0
- esiaccel/re2.dll +0 -0
- esiaccel/types.py +565 -0
- esiaccel/utils.py +54 -0
- esiaccel/zlib1.dll +0 -0
- esiaccel-0.2.2.dist-info/METADATA +254 -0
- esiaccel-0.2.2.dist-info/RECORD +57 -0
- esiaccel-0.2.2.dist-info/WHEEL +5 -0
- esiaccel-0.2.2.dist-info/entry_points.txt +4 -0
- esiaccel-0.2.2.dist-info/licenses/LICENSE +234 -0
- esiaccel-0.2.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
//===- Cosim_Endpoint.sv - ESI cosim primary RTL 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
|
+
// Package: Cosim_DpiPkg
|
|
10
|
+
//
|
|
11
|
+
// Main cosim <--> dpi bridge module.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
//
|
|
15
|
+
//===----------------------------------------------------------------------===//
|
|
16
|
+
|
|
17
|
+
import Cosim_DpiPkg::*;
|
|
18
|
+
|
|
19
|
+
module Cosim_Endpoint_ToHost
|
|
20
|
+
#(
|
|
21
|
+
parameter string ENDPOINT_ID = "",
|
|
22
|
+
parameter string TO_HOST_TYPE_ID = "",
|
|
23
|
+
parameter int TO_HOST_SIZE_BITS = -1
|
|
24
|
+
)
|
|
25
|
+
(
|
|
26
|
+
input logic clk,
|
|
27
|
+
input logic rst,
|
|
28
|
+
|
|
29
|
+
input logic DataInValid,
|
|
30
|
+
output logic DataInReady,
|
|
31
|
+
input logic [TO_HOST_SIZE_BITS-1:0] DataIn
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
initial begin
|
|
35
|
+
int rc;
|
|
36
|
+
rc = cosim_init();
|
|
37
|
+
if (rc != 0)
|
|
38
|
+
$error("Cosim init failed (%d)", rc);
|
|
39
|
+
rc = cosim_ep_register(ENDPOINT_ID, "", 0,
|
|
40
|
+
TO_HOST_TYPE_ID, TO_HOST_SIZE_BYTES);
|
|
41
|
+
if (rc != 0)
|
|
42
|
+
$error("Cosim endpoint (%s) register failed: %d", ENDPOINT_ID, rc);
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
/// **********************
|
|
46
|
+
/// Data in management.
|
|
47
|
+
///
|
|
48
|
+
|
|
49
|
+
localparam int TO_HOST_SIZE_BYTES = int'((TO_HOST_SIZE_BITS+7)/8);
|
|
50
|
+
// The number of bits over a byte.
|
|
51
|
+
localparam int TO_HOST_SIZE_BITS_DIFF = TO_HOST_SIZE_BITS % 8;
|
|
52
|
+
localparam int TO_HOST_SIZE_BYTES_FLOOR = int'(TO_HOST_SIZE_BITS/8);
|
|
53
|
+
localparam int TO_HOST_SIZE_BYTES_FLOOR_IN_BITS
|
|
54
|
+
= TO_HOST_SIZE_BYTES_FLOOR * 8;
|
|
55
|
+
|
|
56
|
+
assign DataInReady = 1'b1;
|
|
57
|
+
byte unsigned DataInBuffer[TO_HOST_SIZE_BYTES-1:0];
|
|
58
|
+
|
|
59
|
+
always@(posedge clk) begin
|
|
60
|
+
if (~rst) begin
|
|
61
|
+
if (DataInValid) begin
|
|
62
|
+
int rc;
|
|
63
|
+
rc = cosim_ep_tryput(ENDPOINT_ID, DataInBuffer, TO_HOST_SIZE_BYTES);
|
|
64
|
+
if (rc != 0)
|
|
65
|
+
$error("cosim_ep_tryput(%s, *, %d) = %d Error! (Data lost)",
|
|
66
|
+
ENDPOINT_ID, TO_HOST_SIZE_BYTES, rc);
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
// Assign packed input bit array to unpacked byte array.
|
|
72
|
+
genvar iIn;
|
|
73
|
+
generate
|
|
74
|
+
for (iIn=0; iIn<TO_HOST_SIZE_BYTES_FLOOR; iIn++)
|
|
75
|
+
assign DataInBuffer[iIn] = DataIn[((iIn+1)*8)-1:iIn*8];
|
|
76
|
+
if (TO_HOST_SIZE_BITS_DIFF != 0)
|
|
77
|
+
// If the type is not a multiple of 8, we've got to copy the extra bits.
|
|
78
|
+
assign DataInBuffer[TO_HOST_SIZE_BYTES - 1]
|
|
79
|
+
[TO_HOST_SIZE_BITS_DIFF - 1:0] =
|
|
80
|
+
DataIn[(TO_HOST_SIZE_BYTES_FLOOR_IN_BITS +
|
|
81
|
+
TO_HOST_SIZE_BITS_DIFF - 1) :
|
|
82
|
+
TO_HOST_SIZE_BYTES_FLOOR_IN_BITS];
|
|
83
|
+
endgenerate
|
|
84
|
+
|
|
85
|
+
endmodule
|
|
86
|
+
|
|
87
|
+
module Cosim_Endpoint_FromHost
|
|
88
|
+
#(
|
|
89
|
+
parameter string ENDPOINT_ID = "",
|
|
90
|
+
parameter string FROM_HOST_TYPE_ID = "",
|
|
91
|
+
parameter int FROM_HOST_SIZE_BITS = -1
|
|
92
|
+
)
|
|
93
|
+
(
|
|
94
|
+
input logic clk,
|
|
95
|
+
input logic rst,
|
|
96
|
+
|
|
97
|
+
output logic DataOutValid,
|
|
98
|
+
input logic DataOutReady,
|
|
99
|
+
output logic [FROM_HOST_SIZE_BITS-1:0] DataOut
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Handle initialization logic.
|
|
103
|
+
initial begin
|
|
104
|
+
int rc;
|
|
105
|
+
rc = cosim_init();
|
|
106
|
+
if (rc != 0)
|
|
107
|
+
$error("Cosim init failed (%d)", rc);
|
|
108
|
+
rc = cosim_ep_register(ENDPOINT_ID, FROM_HOST_TYPE_ID, FROM_HOST_SIZE_BYTES,
|
|
109
|
+
"", 0);
|
|
110
|
+
if (rc != 0)
|
|
111
|
+
$error("Cosim endpoint (%s) register failed: %d", ENDPOINT_ID, rc);
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
/// ***********************
|
|
115
|
+
/// Useful constants.
|
|
116
|
+
|
|
117
|
+
localparam int FROM_HOST_SIZE_BYTES = int'((FROM_HOST_SIZE_BITS+7)/8);
|
|
118
|
+
// The number of bits over a byte.
|
|
119
|
+
localparam int FROM_HOST_SIZE_BITS_DIFF = FROM_HOST_SIZE_BITS % 8;
|
|
120
|
+
localparam int FROM_HOST_SIZE_BYTES_FLOOR = int'(FROM_HOST_SIZE_BITS/8);
|
|
121
|
+
localparam int FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS
|
|
122
|
+
= FROM_HOST_SIZE_BYTES_FLOOR * 8;
|
|
123
|
+
|
|
124
|
+
// Buffer to hold incoming data directly from the DPI calls.
|
|
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
|
+
|
|
138
|
+
always @(posedge clk) begin
|
|
139
|
+
if (~rst) 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
|
|
148
|
+
int data_limit;
|
|
149
|
+
int rc;
|
|
150
|
+
|
|
151
|
+
data_limit = FROM_HOST_SIZE_BYTES;
|
|
152
|
+
rc = cosim_ep_tryget(ENDPOINT_ID, DataOutBuffer, data_limit);
|
|
153
|
+
if (rc < 0) begin
|
|
154
|
+
$error("cosim_ep_tryget(%s, *, %d -> %d) returned an error (%d)",
|
|
155
|
+
ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit, rc);
|
|
156
|
+
end else if (rc > 0) begin
|
|
157
|
+
$error("cosim_ep_tryget(%s, *, %d -> %d) had data left over! (%d)",
|
|
158
|
+
ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit, rc);
|
|
159
|
+
end else if (rc == 0) begin
|
|
160
|
+
if (data_limit == FROM_HOST_SIZE_BYTES)
|
|
161
|
+
DataOut_a_valid <= 1'b1;
|
|
162
|
+
else if (data_limit == 0)
|
|
163
|
+
begin end // No message.
|
|
164
|
+
else
|
|
165
|
+
$error(
|
|
166
|
+
"cosim_ep_tryget(%s, *, %d -> %d) did not load entire buffer!",
|
|
167
|
+
ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit);
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end else begin
|
|
171
|
+
DataOut_a_valid <= 1'b0;
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
// Pack the byte array into a single vector that will be handed to the
|
|
176
|
+
// skid buffer as its input payload.
|
|
177
|
+
genvar iOut;
|
|
178
|
+
generate
|
|
179
|
+
for (iOut=0; iOut<FROM_HOST_SIZE_BYTES_FLOOR; iOut++)
|
|
180
|
+
assign DataOut_a[((iOut+1)*8)-1:iOut*8] = DataOutBuffer[iOut];
|
|
181
|
+
if (FROM_HOST_SIZE_BITS_DIFF != 0)
|
|
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]
|
|
186
|
+
= DataOutBuffer[FROM_HOST_SIZE_BYTES - 1]
|
|
187
|
+
[FROM_HOST_SIZE_BITS_DIFF - 1 : 0];
|
|
188
|
+
endgenerate
|
|
189
|
+
|
|
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;
|
|
217
|
+
|
|
218
|
+
endmodule
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//===- Cosim_Manifest.sv - ESI manifest 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 needs to instantiate this ONCE with the zlib-compressed
|
|
10
|
+
// JSON manifest as the parameter.
|
|
11
|
+
//
|
|
12
|
+
//===----------------------------------------------------------------------===//
|
|
13
|
+
|
|
14
|
+
import Cosim_DpiPkg::*;
|
|
15
|
+
|
|
16
|
+
module Cosim_Manifest
|
|
17
|
+
#(
|
|
18
|
+
parameter int COMPRESSED_MANIFEST_SIZE = 0,
|
|
19
|
+
parameter int unsigned ESI_VERSION = 0
|
|
20
|
+
)(
|
|
21
|
+
input logic [COMPRESSED_MANIFEST_SIZE-1:0][7:0] compressed_manifest
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
byte unsigned compressed_manifest_bytes[COMPRESSED_MANIFEST_SIZE-1:0];
|
|
25
|
+
always_comb
|
|
26
|
+
for (int i=0; i<COMPRESSED_MANIFEST_SIZE; i++)
|
|
27
|
+
compressed_manifest_bytes[i] = compressed_manifest[i];
|
|
28
|
+
|
|
29
|
+
always@(compressed_manifest)
|
|
30
|
+
cosim_set_manifest(ESI_VERSION, compressed_manifest_bytes);
|
|
31
|
+
|
|
32
|
+
endmodule
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
//===- driver.cpp - ESI Verilator software driver -------------------------===//
|
|
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 fairly standard, boilerplate Verilator C++ simulation driver. Assumes the
|
|
10
|
+
// top level exposes just two signals: 'clk' and 'rst'.
|
|
11
|
+
//
|
|
12
|
+
//===----------------------------------------------------------------------===//
|
|
13
|
+
|
|
14
|
+
#ifndef TOP_MODULE
|
|
15
|
+
#define TOP_MODULE ESI_Cosim_Top
|
|
16
|
+
#endif // TOP_MODULE
|
|
17
|
+
|
|
18
|
+
// Macro black magic to get the header file name and class name from the
|
|
19
|
+
// TOP_MODULE macro. Need to disable formatting for this section, as
|
|
20
|
+
// clang-format messes it up by inserting spaces.
|
|
21
|
+
|
|
22
|
+
// clang-format off
|
|
23
|
+
#define STRINGIFY_MACRO(x) STR(x)
|
|
24
|
+
#define STR(x) #x
|
|
25
|
+
#define EXPAND(x)x
|
|
26
|
+
#define CONCAT3(n1, n2, n3) STRINGIFY_MACRO(EXPAND(n1)EXPAND(n2)EXPAND(n3))
|
|
27
|
+
#define TOKENPASTE(x, y) x ## y
|
|
28
|
+
#define CLASSNAME(x, y) TOKENPASTE(x, y)
|
|
29
|
+
|
|
30
|
+
#include CONCAT3(V,TOP_MODULE,.h)
|
|
31
|
+
// clang-format on
|
|
32
|
+
|
|
33
|
+
#include "verilated_fst_c.h"
|
|
34
|
+
|
|
35
|
+
#include "signal.h"
|
|
36
|
+
#include <iostream>
|
|
37
|
+
#include <thread>
|
|
38
|
+
|
|
39
|
+
vluint64_t timeStamp;
|
|
40
|
+
|
|
41
|
+
// Stop the simulation gracefully on ctrl-c.
|
|
42
|
+
volatile bool stopSimulation = false;
|
|
43
|
+
void handle_sigint(int) { stopSimulation = true; }
|
|
44
|
+
|
|
45
|
+
// Called by $time in Verilog.
|
|
46
|
+
double sc_time_stamp() { return timeStamp; }
|
|
47
|
+
|
|
48
|
+
int main(int argc, char **argv) {
|
|
49
|
+
// Register graceful exit handler.
|
|
50
|
+
signal(SIGINT, handle_sigint);
|
|
51
|
+
|
|
52
|
+
Verilated::commandArgs(argc, argv);
|
|
53
|
+
|
|
54
|
+
// Construct the simulated module's C++ model.
|
|
55
|
+
auto &dut = *new CLASSNAME(V, TOP_MODULE)();
|
|
56
|
+
char *waveformFile = getenv("SAVE_WAVE");
|
|
57
|
+
|
|
58
|
+
char *periodStr = getenv("DEBUG_PERIOD");
|
|
59
|
+
unsigned debugPeriod = 0;
|
|
60
|
+
if (periodStr) {
|
|
61
|
+
debugPeriod = std::stoi(periodStr);
|
|
62
|
+
std::cout << "[driver] Setting debug period to " << debugPeriod
|
|
63
|
+
<< std::endl;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#ifdef TRACE
|
|
67
|
+
VerilatedFstC *tfp = nullptr;
|
|
68
|
+
#endif
|
|
69
|
+
|
|
70
|
+
if (waveformFile) {
|
|
71
|
+
#ifdef TRACE
|
|
72
|
+
tfp = new VerilatedFstC();
|
|
73
|
+
Verilated::traceEverOn(true);
|
|
74
|
+
dut.trace(tfp, 99); // Trace 99 levels of hierarchy
|
|
75
|
+
tfp->open(waveformFile);
|
|
76
|
+
std::cout << "[driver] Writing trace to " << waveformFile << std::endl;
|
|
77
|
+
#else
|
|
78
|
+
std::cout
|
|
79
|
+
<< "[driver] Warning: waveform file specified, but not a debug build"
|
|
80
|
+
<< std::endl;
|
|
81
|
+
#endif
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
std::cout << "[driver] Starting simulation" << std::endl;
|
|
85
|
+
|
|
86
|
+
// TODO: Add max speed (cycles per second) option for small, interactive
|
|
87
|
+
// simulations to reduce waveform for debugging. Should this be a command line
|
|
88
|
+
// option or configurable over the cosim interface?
|
|
89
|
+
|
|
90
|
+
// Reset.
|
|
91
|
+
dut.rst = 1;
|
|
92
|
+
dut.clk = 0;
|
|
93
|
+
|
|
94
|
+
// TODO: Support ESI reset handshake in the future.
|
|
95
|
+
// Run for a few cycles with reset held.
|
|
96
|
+
for (timeStamp = 0; timeStamp < 8 && !Verilated::gotFinish(); timeStamp++) {
|
|
97
|
+
dut.eval();
|
|
98
|
+
#ifdef TRACE
|
|
99
|
+
if (tfp)
|
|
100
|
+
tfp->dump(timeStamp);
|
|
101
|
+
#endif
|
|
102
|
+
dut.clk = !dut.clk;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Take simulation out of reset.
|
|
106
|
+
dut.rst = 0;
|
|
107
|
+
|
|
108
|
+
// Run for the specified number of cycles out of reset.
|
|
109
|
+
for (; !Verilated::gotFinish() && !stopSimulation; timeStamp++) {
|
|
110
|
+
dut.eval();
|
|
111
|
+
#ifdef TRACE
|
|
112
|
+
if (tfp)
|
|
113
|
+
tfp->dump(timeStamp);
|
|
114
|
+
#endif
|
|
115
|
+
dut.clk = !dut.clk;
|
|
116
|
+
|
|
117
|
+
if (debugPeriod)
|
|
118
|
+
std::this_thread::sleep_for(std::chrono::milliseconds(debugPeriod));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Tell the simulator that we're going to exit. This flushes the output(s) and
|
|
122
|
+
// frees whatever memory may have been allocated.
|
|
123
|
+
dut.final();
|
|
124
|
+
#ifdef TRACE
|
|
125
|
+
if (tfp)
|
|
126
|
+
tfp->close();
|
|
127
|
+
#endif
|
|
128
|
+
|
|
129
|
+
std::cout << "[driver] Ending simulation at tick #" << timeStamp << std::endl;
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
esiaccel/cosim/driver.sv
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
//===- driver.sv - ESI cosim testbench driver -----------------------------===//
|
|
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
|
+
// Contains the top module driver for an ESI cosimulation. It simply provides a
|
|
10
|
+
// clock and reset signal. In the future, the reset signal will become a reset
|
|
11
|
+
// handshake.
|
|
12
|
+
//
|
|
13
|
+
//===----------------------------------------------------------------------===//
|
|
14
|
+
|
|
15
|
+
`timescale 1ns / 100ps
|
|
16
|
+
|
|
17
|
+
`ifndef TOP_MODULE
|
|
18
|
+
`define TOP_MODULE ESI_Cosim_Top
|
|
19
|
+
`endif
|
|
20
|
+
|
|
21
|
+
// Allow reading environment variables to control waveform dumping.
|
|
22
|
+
import "DPI-C" function string getenv(input string env_name);
|
|
23
|
+
|
|
24
|
+
module driver();
|
|
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
|
+
|
|
37
|
+
logic clk = 0;
|
|
38
|
+
logic rst = 0;
|
|
39
|
+
|
|
40
|
+
`TOP_MODULE top (
|
|
41
|
+
.clk(clk),
|
|
42
|
+
.rst(rst)
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
always begin
|
|
46
|
+
// A clock period is #4.
|
|
47
|
+
clk = ~clk;
|
|
48
|
+
#2;
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
initial begin
|
|
52
|
+
int cycles;
|
|
53
|
+
|
|
54
|
+
$display("[driver] Starting simulation");
|
|
55
|
+
|
|
56
|
+
rst = 1;
|
|
57
|
+
// Hold in reset for 4 cycles.
|
|
58
|
+
@(posedge clk);
|
|
59
|
+
@(posedge clk);
|
|
60
|
+
@(posedge clk);
|
|
61
|
+
@(posedge clk);
|
|
62
|
+
rst = 0;
|
|
63
|
+
|
|
64
|
+
if ($value$plusargs ("cycles=%d", cycles)) begin
|
|
65
|
+
int i;
|
|
66
|
+
for (i = 0; i < cycles; i++) begin
|
|
67
|
+
@(posedge clk);
|
|
68
|
+
end
|
|
69
|
+
$display("[driver] Ending simulation at tick #%0d", $time);
|
|
70
|
+
$finish();
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
endmodule
|
esiaccel/cosim/questa.py
ADDED
|
@@ -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)
|