esiaccel 0.0.10__cp310-cp310-win_amd64.whl → 0.1.5.dev406__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.
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/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 +10 -1
- esiaccel/abseil_dll.dll +0 -0
- esiaccel/accelerator.py +15 -1
- esiaccel/cares.dll +0 -0
- esiaccel/cmake/esiaccelConfig.cmake +1 -1
- 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.cp310-win_amd64.pyd +0 -0
- esiaccel/esiquery.exe +0 -0
- esiaccel/include/esi/Accelerator.h +33 -9
- esiaccel/include/esi/CLI.h +77 -0
- esiaccel/include/esi/Common.h +59 -10
- esiaccel/include/esi/Context.h +21 -1
- esiaccel/include/esi/Design.h +14 -3
- esiaccel/include/esi/Engines.h +124 -0
- esiaccel/include/esi/Logging.h +231 -0
- esiaccel/include/esi/Manifest.h +0 -2
- esiaccel/include/esi/Ports.h +54 -7
- esiaccel/include/esi/Services.h +225 -22
- esiaccel/include/esi/Types.h +103 -5
- esiaccel/include/esi/Utils.h +5 -0
- esiaccel/include/esi/Values.h +313 -0
- esiaccel/include/esi/backends/Cosim.h +85 -0
- esiaccel/include/esi/backends/RpcServer.h +55 -0
- esiaccel/include/esi/backends/Trace.h +8 -5
- 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 +174 -33
- esiaccel/utils.py +27 -3
- esiaccel/zlib1.dll +0 -0
- {esiaccel-0.0.10.dist-info → esiaccel-0.1.5.dev406.dist-info}/METADATA +3 -3
- esiaccel-0.1.5.dev406.dist-info/RECORD +54 -0
- {esiaccel-0.0.10.dist-info → esiaccel-0.1.5.dev406.dist-info}/WHEEL +1 -1
- {esiaccel-0.0.10.dist-info → esiaccel-0.1.5.dev406.dist-info}/entry_points.txt +1 -0
- esiaccel/bin/ESICppRuntime.dll +0 -0
- esiaccel/bin/esiquery.exe +0 -0
- esiaccel/bin/zlib1.dll +0 -0
- esiaccel-0.0.10.dist-info/RECORD +0 -28
- {esiaccel-0.0.10.dist-info → esiaccel-0.1.5.dev406.dist-info/licenses}/LICENSE +0 -0
- {esiaccel-0.0.10.dist-info → esiaccel-0.1.5.dev406.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
esiaccel/ESICppRuntime.dll
CHANGED
|
Binary file
|
esiaccel/ESICppRuntime.lib
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
esiaccel/MtiPli.dll
ADDED
|
Binary file
|
esiaccel/MtiPli.lib
ADDED
|
Binary file
|
esiaccel/__init__.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
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
|
-
|
|
4
|
+
import sys
|
|
5
|
+
import os
|
|
5
6
|
from .accelerator import AcceleratorConnection
|
|
6
7
|
|
|
7
8
|
from .esiCppAccel import (AppID, Type, BundleType, ChannelType, ArrayType,
|
|
@@ -11,3 +12,11 @@ __all__ = [
|
|
|
11
12
|
"AcceleratorConnection", "AppID", "Type", "BundleType", "ChannelType",
|
|
12
13
|
"ArrayType", "StructType", "BitsType", "UIntType", "SIntType"
|
|
13
14
|
]
|
|
15
|
+
|
|
16
|
+
if sys.platform == "win32":
|
|
17
|
+
"""Ensure that ESI libraries are in the dll path on Windows. Necessary to
|
|
18
|
+
call when users build against the esiaccel-provided prebuilt CMake/prebuilt
|
|
19
|
+
libraries, before they are loaded via. python.
|
|
20
|
+
"""
|
|
21
|
+
from .utils import get_dll_dir
|
|
22
|
+
os.add_dll_directory(str(get_dll_dir()))
|
esiaccel/abseil_dll.dll
ADDED
|
Binary file
|
esiaccel/accelerator.py
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
#
|
|
11
11
|
# ===-----------------------------------------------------------------------===#
|
|
12
12
|
|
|
13
|
-
from typing import Dict, Optional
|
|
13
|
+
from typing import Dict, List, Optional
|
|
14
14
|
|
|
15
15
|
from .types import BundlePort
|
|
16
16
|
from . import esiCppAccel as cpp
|
|
@@ -41,6 +41,13 @@ class AcceleratorConnection:
|
|
|
41
41
|
def get_service_hostmem(self) -> cpp.HostMem:
|
|
42
42
|
return self.cpp_accel.get_service_hostmem()
|
|
43
43
|
|
|
44
|
+
def get_accelerator(self) -> "Accelerator":
|
|
45
|
+
"""
|
|
46
|
+
Return an accelerator that may be owned by this accelerator connection.
|
|
47
|
+
If no accelerator is owned, will throw.
|
|
48
|
+
"""
|
|
49
|
+
return Accelerator(self.cpp_accel.get_accelerator())
|
|
50
|
+
|
|
44
51
|
|
|
45
52
|
from .esiCppAccel import HostMemOptions
|
|
46
53
|
|
|
@@ -66,6 +73,13 @@ class HWModule:
|
|
|
66
73
|
for name, port in self.cpp_hwmodule.ports.items()
|
|
67
74
|
}
|
|
68
75
|
|
|
76
|
+
@property
|
|
77
|
+
def services(self) -> List[cpp.AppID]:
|
|
78
|
+
return self.cpp_hwmodule.services
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
MMIO = cpp.MMIO
|
|
82
|
+
|
|
69
83
|
|
|
70
84
|
class Instance(HWModule):
|
|
71
85
|
"""Subclass of `HWModule` which represents a submodule instance. Adds an
|
esiaccel/cares.dll
ADDED
|
Binary file
|
esiaccel/codegen.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
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
|
+
# Code generation from ESI manifests to source code. C++ header support included
|
|
6
|
+
# with the runtime, though it is intended to be extensible for other languages.
|
|
7
|
+
|
|
8
|
+
from typing import List, TextIO, Type, Optional
|
|
9
|
+
from .accelerator import AcceleratorConnection
|
|
10
|
+
from .esiCppAccel import ModuleInfo
|
|
11
|
+
from . import types
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
import textwrap
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
_thisdir = Path(__file__).absolute().resolve().parent
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Generator:
|
|
22
|
+
"""Base class for all generators."""
|
|
23
|
+
|
|
24
|
+
language: Optional[str] = None
|
|
25
|
+
|
|
26
|
+
def __init__(self, conn: AcceleratorConnection):
|
|
27
|
+
self.manifest = conn.manifest()
|
|
28
|
+
|
|
29
|
+
def generate(self, output_dir: Path, system_name: str):
|
|
30
|
+
raise NotImplementedError("Generator.generate() must be overridden")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class CppGenerator(Generator):
|
|
34
|
+
"""Generate C++ headers from an ESI manifest."""
|
|
35
|
+
|
|
36
|
+
language = "C++"
|
|
37
|
+
|
|
38
|
+
# Supported bit widths for lone integer types.
|
|
39
|
+
int_width_support = set([8, 16, 32, 64])
|
|
40
|
+
|
|
41
|
+
def get_type_str(self, type: types.ESIType) -> str:
|
|
42
|
+
"""Get the textual code for the storage class of a type.
|
|
43
|
+
|
|
44
|
+
Examples: uint32_t, int64_t, CustomStruct."""
|
|
45
|
+
|
|
46
|
+
if isinstance(type, (types.BitsType, types.IntType)):
|
|
47
|
+
if type.bit_width not in self.int_width_support:
|
|
48
|
+
raise ValueError(f"Unsupported integer width: {type.bit_width}")
|
|
49
|
+
if isinstance(type, (types.BitsType, types.UIntType)):
|
|
50
|
+
return f"uint{type.bit_width}_t"
|
|
51
|
+
return f"int{type.bit_width}_t"
|
|
52
|
+
raise NotImplementedError(f"Type '{type}' not supported for C++ generation")
|
|
53
|
+
|
|
54
|
+
def get_consts_str(self, module_info: ModuleInfo) -> str:
|
|
55
|
+
"""Get the C++ code for a constant in a module."""
|
|
56
|
+
const_strs: List[str] = [
|
|
57
|
+
f"static constexpr {self.get_type_str(const.type)} "
|
|
58
|
+
f"{name} = 0x{const.value:x};"
|
|
59
|
+
for name, const in module_info.constants.items()
|
|
60
|
+
]
|
|
61
|
+
return "\n".join(const_strs)
|
|
62
|
+
|
|
63
|
+
def write_modules(self, output_dir: Path, system_name: str):
|
|
64
|
+
"""Write the C++ header. One for each module in the manifest."""
|
|
65
|
+
|
|
66
|
+
for module_info in self.manifest.module_infos:
|
|
67
|
+
s = f"""
|
|
68
|
+
/// Generated header for {system_name} module {module_info.name}.
|
|
69
|
+
#pragma once
|
|
70
|
+
#include "types.h"
|
|
71
|
+
|
|
72
|
+
namespace {system_name} {{
|
|
73
|
+
class {module_info.name} {{
|
|
74
|
+
public:
|
|
75
|
+
{self.get_consts_str(module_info)}
|
|
76
|
+
}};
|
|
77
|
+
}} // namespace {system_name}
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
hdr_file = output_dir / f"{module_info.name}.h"
|
|
81
|
+
with open(hdr_file, "w") as hdr:
|
|
82
|
+
hdr.write(textwrap.dedent(s))
|
|
83
|
+
|
|
84
|
+
def write_type(self, hdr: TextIO, type: types.ESIType):
|
|
85
|
+
if isinstance(type, (types.BitsType, types.IntType)):
|
|
86
|
+
# Bit vector types use standard C++ types.
|
|
87
|
+
return
|
|
88
|
+
raise NotImplementedError(f"Type '{type}' not supported for C++ generation")
|
|
89
|
+
|
|
90
|
+
def write_types(self, output_dir: Path, system_name: str):
|
|
91
|
+
hdr_file = output_dir / "types.h"
|
|
92
|
+
with open(hdr_file, "w") as hdr:
|
|
93
|
+
hdr.write(
|
|
94
|
+
textwrap.dedent(f"""
|
|
95
|
+
// Generated header for {system_name} types.
|
|
96
|
+
#pragma once
|
|
97
|
+
|
|
98
|
+
#include <cstdint>
|
|
99
|
+
|
|
100
|
+
namespace {system_name} {{
|
|
101
|
+
"""))
|
|
102
|
+
|
|
103
|
+
for type in self.manifest.type_table:
|
|
104
|
+
try:
|
|
105
|
+
self.write_type(hdr, type)
|
|
106
|
+
except NotImplementedError:
|
|
107
|
+
sys.stderr.write(
|
|
108
|
+
f"Warning: type '{type}' not supported for C++ generation\n")
|
|
109
|
+
|
|
110
|
+
hdr.write(
|
|
111
|
+
textwrap.dedent(f"""
|
|
112
|
+
}} // namespace {system_name}
|
|
113
|
+
"""))
|
|
114
|
+
|
|
115
|
+
def generate(self, output_dir: Path, system_name: str):
|
|
116
|
+
self.write_types(output_dir, system_name)
|
|
117
|
+
self.write_modules(output_dir, system_name)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def run(generator: Type[Generator] = CppGenerator,
|
|
121
|
+
cmdline_args=sys.argv) -> int:
|
|
122
|
+
"""Create and run a generator reading options from the command line."""
|
|
123
|
+
|
|
124
|
+
argparser = argparse.ArgumentParser(
|
|
125
|
+
description=f"Generate {generator.language} headers from an ESI manifest",
|
|
126
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
127
|
+
epilog=textwrap.dedent("""
|
|
128
|
+
Can read the manifest from either a file OR a running accelerator.
|
|
129
|
+
|
|
130
|
+
Usage examples:
|
|
131
|
+
# To read the manifest from a file:
|
|
132
|
+
esi-cppgen --file /path/to/manifest.json
|
|
133
|
+
|
|
134
|
+
# To read the manifest from a running accelerator:
|
|
135
|
+
esi-cppgen --platform cosim --connection localhost:1234
|
|
136
|
+
"""))
|
|
137
|
+
|
|
138
|
+
argparser.add_argument("--file",
|
|
139
|
+
type=str,
|
|
140
|
+
default=None,
|
|
141
|
+
help="Path to the manifest file.")
|
|
142
|
+
argparser.add_argument(
|
|
143
|
+
"--platform",
|
|
144
|
+
type=str,
|
|
145
|
+
help="Name of platform for live accelerator connection.")
|
|
146
|
+
argparser.add_argument(
|
|
147
|
+
"--connection",
|
|
148
|
+
type=str,
|
|
149
|
+
help="Connection string for live accelerator connection.")
|
|
150
|
+
argparser.add_argument(
|
|
151
|
+
"--output-dir",
|
|
152
|
+
type=str,
|
|
153
|
+
default="esi",
|
|
154
|
+
help="Output directory for generated files. Recommend adding either `esi`"
|
|
155
|
+
" or the system name to the end of the path so as to avoid header name"
|
|
156
|
+
"conflicts. Defaults to `esi`")
|
|
157
|
+
argparser.add_argument(
|
|
158
|
+
"--system-name",
|
|
159
|
+
type=str,
|
|
160
|
+
default="esi_system",
|
|
161
|
+
help="Name of the ESI system. For C++, this will be the namespace.")
|
|
162
|
+
|
|
163
|
+
if (len(cmdline_args) <= 1):
|
|
164
|
+
argparser.print_help()
|
|
165
|
+
return 1
|
|
166
|
+
args = argparser.parse_args(cmdline_args[1:])
|
|
167
|
+
|
|
168
|
+
if args.file is not None and args.platform is not None:
|
|
169
|
+
print("Cannot specify both --file and --platform")
|
|
170
|
+
return 1
|
|
171
|
+
|
|
172
|
+
conn: AcceleratorConnection
|
|
173
|
+
if args.file is not None:
|
|
174
|
+
conn = AcceleratorConnection("trace", f"-:{args.file}")
|
|
175
|
+
elif args.platform is not None:
|
|
176
|
+
if args.connection is None:
|
|
177
|
+
print("Must specify --connection with --platform")
|
|
178
|
+
return 1
|
|
179
|
+
conn = AcceleratorConnection(args.platform, args.connection)
|
|
180
|
+
else:
|
|
181
|
+
print("Must specify either --file or --platform")
|
|
182
|
+
return 1
|
|
183
|
+
|
|
184
|
+
output_dir = Path(args.output_dir)
|
|
185
|
+
if output_dir.exists() and not output_dir.is_dir():
|
|
186
|
+
print(f"Output directory {output_dir} is not a directory")
|
|
187
|
+
return 1
|
|
188
|
+
if not output_dir.exists():
|
|
189
|
+
output_dir.mkdir(parents=True)
|
|
190
|
+
|
|
191
|
+
gen = generator(conn)
|
|
192
|
+
gen.generate(output_dir, args.system_name)
|
|
193
|
+
return 0
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
if __name__ == '__main__':
|
|
197
|
+
sys.exit(run())
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
//===- Cosim_DpiPkg.sv - ESI cosim DPI declarations ---------*- 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
|
+
// DPI-exposed funcs for cosimserver cosimulation unit-test.
|
|
12
|
+
//
|
|
13
|
+
//===----------------------------------------------------------------------===//
|
|
14
|
+
|
|
15
|
+
package Cosim_DpiPkg;
|
|
16
|
+
|
|
17
|
+
// --------------------- Cosim RPC Server --------------------------------------
|
|
18
|
+
|
|
19
|
+
// Start cosimserver (spawns server for HW-initiated work, listens for
|
|
20
|
+
// connections from new SW-clients).
|
|
21
|
+
import "DPI-C" sv2cCosimserverInit = function int cosim_init();
|
|
22
|
+
|
|
23
|
+
// Teardown cosimserver (disconnects from primary server port, stops connections
|
|
24
|
+
// from active clients).
|
|
25
|
+
import "DPI-C" sv2cCosimserverFinish = function void cosim_finish();
|
|
26
|
+
|
|
27
|
+
// --------------------- Endpoint Management -----------------------------------
|
|
28
|
+
|
|
29
|
+
// Register simulated device endpoints.
|
|
30
|
+
// - return 0 on success, non-zero on failure (duplicate EP registered).
|
|
31
|
+
import "DPI-C" sv2cCosimserverEpRegister =
|
|
32
|
+
function int cosim_ep_register(
|
|
33
|
+
// The endpoint ID.
|
|
34
|
+
input string endpoint_id,
|
|
35
|
+
// The ESI type id which the _RPC client_ is sending us.
|
|
36
|
+
input string from_host_type_id,
|
|
37
|
+
// The send types max size, in bytes.
|
|
38
|
+
input int from_host_type_size,
|
|
39
|
+
// The ESI type id which we are sending to the _RPC client_.
|
|
40
|
+
input string to_host_type_id,
|
|
41
|
+
// The recv types max size, in bytes.
|
|
42
|
+
input int to_host_type_size);
|
|
43
|
+
|
|
44
|
+
// --------------------- Endpoint Accessors ------------------------------------
|
|
45
|
+
|
|
46
|
+
// Attempt to send data to a client.
|
|
47
|
+
// - return 0 on success, negative on failure (unregistered EP).
|
|
48
|
+
import "DPI-C" sv2cCosimserverEpTryPut =
|
|
49
|
+
function int cosim_ep_tryput(
|
|
50
|
+
// The ID of the endpoint to which the data should be sent.
|
|
51
|
+
input string endpoint_id,
|
|
52
|
+
// A data buffer.
|
|
53
|
+
input byte unsigned data[],
|
|
54
|
+
// (Optional) Size of the buffer. If negative, will be dynamically detected.
|
|
55
|
+
input int data_size = -1
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// Attempt to recieve data from a client.
|
|
59
|
+
// - Returns negative when call failed (e.g. EP not registered).
|
|
60
|
+
// - If no message, return 0 with size_bytes == 0.
|
|
61
|
+
// - Assumes buffer is large enough to contain entire message. Fails if not
|
|
62
|
+
// large enough. (In the future, will add support for getting the message into
|
|
63
|
+
// a fixed-size buffer over multiple calls.)
|
|
64
|
+
import "DPI-C" sv2cCosimserverEpTryGet =
|
|
65
|
+
function int cosim_ep_tryget(
|
|
66
|
+
// The ID of the endpoint from which data should be recieved.
|
|
67
|
+
input string endpoint_id,
|
|
68
|
+
// The buffer in which to put the data. This should be 'output', but the
|
|
69
|
+
// open source simulator Verilator doesn't seem to have a way to do this.
|
|
70
|
+
inout byte unsigned data[],
|
|
71
|
+
// Input: indicates the size of the data[] buffer. If -1, dynamically detect
|
|
72
|
+
// size.
|
|
73
|
+
// Output: the size of the message.
|
|
74
|
+
inout int unsigned data_size
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// --------------------- Manifest ----------------------------------------------
|
|
78
|
+
|
|
79
|
+
import "DPI-C" sv2cCosimserverSetManifest =
|
|
80
|
+
function void cosim_set_manifest(
|
|
81
|
+
input int signed esi_version,
|
|
82
|
+
input byte unsigned compressed_manifest[]
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
endpackage // Cosim_DpiPkg
|
|
@@ -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
|