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.
- 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/{lib/MtiPli.dll → MtiPli.dll} +0 -0
- esiaccel/{lib/MtiPli.lib → MtiPli.lib} +0 -0
- esiaccel/__init__.py +22 -4
- esiaccel/abseil_dll.dll +0 -0
- esiaccel/accelerator.py +37 -5
- esiaccel/cares.dll +0 -0
- esiaccel/cmake/esiaccelConfig.cmake +34 -0
- esiaccel/codegen.py +3 -3
- esiaccel/cosim/Cosim_CycleCount.sv +84 -0
- esiaccel/cosim/Cosim_Endpoint.sv +61 -32
- esiaccel/cosim/driver.cpp +6 -6
- esiaccel/cosim/driver.sv +14 -0
- esiaccel/cosim/questa.py +141 -0
- esiaccel/cosim/simulator.py +383 -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 +14 -17
- esiaccel/include/esi/CLI.h +5 -5
- esiaccel/include/esi/Common.h +19 -2
- esiaccel/include/esi/Context.h +17 -9
- esiaccel/include/esi/Design.h +9 -4
- esiaccel/include/esi/Manifest.h +0 -2
- esiaccel/include/esi/Ports.h +230 -23
- esiaccel/include/esi/Services.h +92 -31
- esiaccel/include/esi/Types.h +162 -10
- esiaccel/include/esi/Values.h +313 -0
- esiaccel/include/esi/backends/Cosim.h +5 -12
- esiaccel/include/esi/backends/RpcClient.h +97 -0
- esiaccel/include/esi/backends/RpcServer.h +21 -3
- 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 +66 -26
- esiaccel/utils.py +21 -3
- esiaccel/zlib1.dll +0 -0
- {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/METADATA +1 -1
- esiaccel-0.2.3.dev80.dist-info/RECORD +58 -0
- esiaccel/bin/esi-cosim.py +0 -423
- esiaccel/bin/esiquery.exe +0 -0
- esiaccel/esiCppAccel.cp310-win_amd64.pyd +0 -0
- esiaccel/lib/EsiCosimDpiServer.dll +0 -0
- esiaccel/lib/EsiCosimDpiServer.lib +0 -0
- esiaccel-0.1.4.dev31.dist-info/RECORD +0 -43
- {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/WHEEL +0 -0
- {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/entry_points.txt +0 -0
- {esiaccel-0.1.4.dev31.dist-info → esiaccel-0.2.3.dev80.dist-info}/licenses/LICENSE +0 -0
- {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
|
esiaccel/ESICppRuntime.dll
CHANGED
|
Binary file
|
esiaccel/ESICppRuntime.lib
CHANGED
|
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
|
-
|
|
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", "
|
|
12
|
-
"
|
|
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))
|
esiaccel/abseil_dll.dll
ADDED
|
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
|
-
|
|
19
|
-
|
|
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,
|
|
26
|
-
|
|
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(
|
|
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 =
|
|
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 =
|
|
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
|
esiaccel/cosim/Cosim_Endpoint.sv
CHANGED
|
@@ -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
|
-
///
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
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
|
-
|
|
171
|
+
DataOut_a_valid <= 1'b0;
|
|
163
172
|
end
|
|
164
173
|
end
|
|
165
174
|
|
|
166
|
-
//
|
|
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
|
|
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,
|
|
173
|
-
assign
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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 "
|
|
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
|
-
|
|
67
|
+
VerilatedFstC *tfp = nullptr;
|
|
68
68
|
#endif
|
|
69
69
|
|
|
70
70
|
if (waveformFile) {
|
|
71
71
|
#ifdef TRACE
|
|
72
|
-
tfp = new
|
|
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
|
|
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)
|