switchboard-hw 0.3.0__cp314-cp314-macosx_10_15_x86_64.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.
- _switchboard.cpython-314-darwin.so +0 -0
- switchboard/__init__.py +24 -0
- switchboard/ams.py +668 -0
- switchboard/apb.py +278 -0
- switchboard/autowrap.py +1000 -0
- switchboard/axi.py +571 -0
- switchboard/axil.py +348 -0
- switchboard/bitvector.py +112 -0
- switchboard/cmdline.py +142 -0
- switchboard/cpp/Makefile +13 -0
- switchboard/cpp/bitutil.h +39 -0
- switchboard/cpp/pagemap.h +91 -0
- switchboard/cpp/pciedev.h +86 -0
- switchboard/cpp/router.cc +89 -0
- switchboard/cpp/spsc_queue.h +267 -0
- switchboard/cpp/switchboard.hpp +257 -0
- switchboard/cpp/switchboard_pcie.hpp +234 -0
- switchboard/cpp/switchboard_tlm.hpp +98 -0
- switchboard/cpp/umilib.h +144 -0
- switchboard/cpp/umilib.hpp +113 -0
- switchboard/cpp/umisb.hpp +364 -0
- switchboard/cpp/xyce.hpp +90 -0
- switchboard/deps/__init__.py +0 -0
- switchboard/deps/verilog_axi.py +23 -0
- switchboard/dpi/__init__.py +0 -0
- switchboard/dpi/switchboard_dpi.cc +119 -0
- switchboard/dpi/switchboard_dpi.py +13 -0
- switchboard/dpi/xyce_dpi.cc +43 -0
- switchboard/gpio.py +108 -0
- switchboard/icarus.py +85 -0
- switchboard/loopback.py +157 -0
- switchboard/network.py +714 -0
- switchboard/pytest_plugin.py +11 -0
- switchboard/sbdesign.py +55 -0
- switchboard/sbdut.py +744 -0
- switchboard/sbtcp.py +345 -0
- switchboard/sc/__init__.py +0 -0
- switchboard/sc/morty/__init__.py +0 -0
- switchboard/sc/morty/uniquify.py +67 -0
- switchboard/sc/sed/__init__.py +0 -0
- switchboard/sc/sed/sed_remove.py +47 -0
- switchboard/sc/standalone_netlist_flow.py +25 -0
- switchboard/switchboard.py +53 -0
- switchboard/test_util.py +46 -0
- switchboard/uart_xactor.py +66 -0
- switchboard/umi.py +793 -0
- switchboard/util.py +131 -0
- switchboard/verilator/__init__.py +0 -0
- switchboard/verilator/config.vlt +13 -0
- switchboard/verilator/testbench.cc +143 -0
- switchboard/verilator/verilator.py +13 -0
- switchboard/verilator_run.py +31 -0
- switchboard/verilog/__init__.py +0 -0
- switchboard/verilog/common/__init__.py +0 -0
- switchboard/verilog/common/common.py +26 -0
- switchboard/verilog/common/switchboard.vh +429 -0
- switchboard/verilog/common/uart_xactor.sv +247 -0
- switchboard/verilog/common/umi_gpio.v +236 -0
- switchboard/verilog/fpga/__init__.py +0 -0
- switchboard/verilog/fpga/axi_reader.sv +82 -0
- switchboard/verilog/fpga/axi_writer.sv +111 -0
- switchboard/verilog/fpga/config_registers.sv +249 -0
- switchboard/verilog/fpga/fpga.py +21 -0
- switchboard/verilog/fpga/include/sb_queue_regmap.vh +21 -0
- switchboard/verilog/fpga/include/spsc_queue.vh +7 -0
- switchboard/verilog/fpga/memory_fault.sv +40 -0
- switchboard/verilog/fpga/sb_fpga_queues.sv +416 -0
- switchboard/verilog/fpga/sb_rx_fpga.sv +303 -0
- switchboard/verilog/fpga/sb_tx_fpga.sv +294 -0
- switchboard/verilog/fpga/umi_fpga_queues.sv +146 -0
- switchboard/verilog/sim/__init__.py +0 -0
- switchboard/verilog/sim/auto_stop_sim.sv +25 -0
- switchboard/verilog/sim/perf_meas_sim.sv +97 -0
- switchboard/verilog/sim/queue_to_sb_sim.sv +176 -0
- switchboard/verilog/sim/queue_to_umi_sim.sv +66 -0
- switchboard/verilog/sim/sb_apb_m.sv +146 -0
- switchboard/verilog/sim/sb_axi_m.sv +199 -0
- switchboard/verilog/sim/sb_axil_m.sv +180 -0
- switchboard/verilog/sim/sb_axil_s.sv +180 -0
- switchboard/verilog/sim/sb_clk_gen.sv +89 -0
- switchboard/verilog/sim/sb_jtag_rbb_sim.sv +148 -0
- switchboard/verilog/sim/sb_rx_sim.sv +55 -0
- switchboard/verilog/sim/sb_to_queue_sim.sv +196 -0
- switchboard/verilog/sim/sb_tx_sim.sv +55 -0
- switchboard/verilog/sim/switchboard_sim.py +49 -0
- switchboard/verilog/sim/umi_rx_sim.sv +61 -0
- switchboard/verilog/sim/umi_to_queue_sim.sv +66 -0
- switchboard/verilog/sim/umi_tx_sim.sv +61 -0
- switchboard/verilog/sim/xyce_intf.sv +67 -0
- switchboard/vpi/switchboard_vpi.cc +431 -0
- switchboard/vpi/xyce_vpi.cc +200 -0
- switchboard/warn.py +14 -0
- switchboard/xyce.py +27 -0
- switchboard_hw-0.3.0.dist-info/METADATA +303 -0
- switchboard_hw-0.3.0.dist-info/RECORD +99 -0
- switchboard_hw-0.3.0.dist-info/WHEEL +6 -0
- switchboard_hw-0.3.0.dist-info/entry_points.txt +6 -0
- switchboard_hw-0.3.0.dist-info/licenses/LICENSE +190 -0
- switchboard_hw-0.3.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
// Copyright (c) 2024 Zero ASIC Corporation
|
|
2
|
+
// This code is licensed under Apache License 2.0 (see LICENSE for details)
|
|
3
|
+
|
|
4
|
+
#include <chrono>
|
|
5
|
+
#include <memory>
|
|
6
|
+
#include <vector>
|
|
7
|
+
|
|
8
|
+
#include "switchboard.hpp"
|
|
9
|
+
|
|
10
|
+
#include <vpi_user.h>
|
|
11
|
+
|
|
12
|
+
static std::vector<std::unique_ptr<SBRX>> rxconn;
|
|
13
|
+
static std::vector<std::unique_ptr<SBTX>> txconn;
|
|
14
|
+
static std::vector<int> rxwidth;
|
|
15
|
+
static std::vector<int> txwidth;
|
|
16
|
+
static std::chrono::steady_clock::time_point start_time;
|
|
17
|
+
|
|
18
|
+
PLI_INT32 pi_sb_rx_init(PLI_BYTE8* userdata) {
|
|
19
|
+
(void)userdata; // unused
|
|
20
|
+
|
|
21
|
+
// get arguments
|
|
22
|
+
vpiHandle args_iter;
|
|
23
|
+
std::vector<vpiHandle> argh;
|
|
24
|
+
{
|
|
25
|
+
vpiHandle systfref;
|
|
26
|
+
systfref = vpi_handle(vpiSysTfCall, NULL);
|
|
27
|
+
args_iter = vpi_iterate(vpiArgument, systfref);
|
|
28
|
+
for (size_t i = 0; i < 3; i++) {
|
|
29
|
+
argh.push_back(vpi_scan(args_iter));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// get uri
|
|
34
|
+
std::string uri;
|
|
35
|
+
{
|
|
36
|
+
t_vpi_value argval;
|
|
37
|
+
argval.format = vpiStringVal;
|
|
38
|
+
vpi_get_value(argh[1], &argval);
|
|
39
|
+
uri = std::string(argval.value.str);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// initialize the connection
|
|
43
|
+
rxconn.push_back(std::unique_ptr<SBRX>(new SBRX()));
|
|
44
|
+
rxconn.back()->init(uri);
|
|
45
|
+
|
|
46
|
+
// get width
|
|
47
|
+
int width;
|
|
48
|
+
{
|
|
49
|
+
t_vpi_value argval;
|
|
50
|
+
argval.format = vpiIntVal;
|
|
51
|
+
vpi_get_value(argh[2], &argval);
|
|
52
|
+
width = argval.value.integer;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// remember width
|
|
56
|
+
rxwidth.push_back(width);
|
|
57
|
+
|
|
58
|
+
// assign the ID of this connection
|
|
59
|
+
{
|
|
60
|
+
t_vpi_value argval;
|
|
61
|
+
argval.format = vpiIntVal;
|
|
62
|
+
argval.value.integer = rxconn.size() - 1;
|
|
63
|
+
vpi_put_value(argh[0], &argval, NULL, vpiNoDelay);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// clean up
|
|
67
|
+
vpi_free_object(args_iter);
|
|
68
|
+
|
|
69
|
+
// return value unused?
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
PLI_INT32 pi_sb_tx_init(PLI_BYTE8* userdata) {
|
|
74
|
+
(void)userdata; // unused
|
|
75
|
+
|
|
76
|
+
// get arguments
|
|
77
|
+
vpiHandle args_iter;
|
|
78
|
+
std::vector<vpiHandle> argh;
|
|
79
|
+
{
|
|
80
|
+
vpiHandle systfref;
|
|
81
|
+
systfref = vpi_handle(vpiSysTfCall, NULL);
|
|
82
|
+
args_iter = vpi_iterate(vpiArgument, systfref);
|
|
83
|
+
for (size_t i = 0; i < 3; i++) {
|
|
84
|
+
argh.push_back(vpi_scan(args_iter));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// get uri
|
|
89
|
+
std::string uri;
|
|
90
|
+
{
|
|
91
|
+
t_vpi_value argval;
|
|
92
|
+
argval.format = vpiStringVal;
|
|
93
|
+
vpi_get_value(argh[1], &argval);
|
|
94
|
+
uri = std::string(argval.value.str);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// initialize the connection
|
|
98
|
+
txconn.push_back(std::unique_ptr<SBTX>(new SBTX()));
|
|
99
|
+
txconn.back()->init(uri);
|
|
100
|
+
|
|
101
|
+
// get width
|
|
102
|
+
int width;
|
|
103
|
+
{
|
|
104
|
+
t_vpi_value argval;
|
|
105
|
+
argval.format = vpiIntVal;
|
|
106
|
+
vpi_get_value(argh[2], &argval);
|
|
107
|
+
width = argval.value.integer;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// remember width
|
|
111
|
+
txwidth.push_back(width);
|
|
112
|
+
|
|
113
|
+
// assign the ID of this connection
|
|
114
|
+
{
|
|
115
|
+
t_vpi_value argval;
|
|
116
|
+
argval.format = vpiIntVal;
|
|
117
|
+
argval.value.integer = txconn.size() - 1;
|
|
118
|
+
vpi_put_value(argh[0], &argval, NULL, vpiNoDelay);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// clean up
|
|
122
|
+
vpi_free_object(args_iter);
|
|
123
|
+
|
|
124
|
+
// return value unused?
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
PLI_INT32 pi_sb_recv(PLI_BYTE8* userdata) {
|
|
129
|
+
(void)userdata; // unused
|
|
130
|
+
|
|
131
|
+
// get arguments
|
|
132
|
+
vpiHandle args_iter;
|
|
133
|
+
std::vector<vpiHandle> argh;
|
|
134
|
+
{
|
|
135
|
+
vpiHandle systfref;
|
|
136
|
+
systfref = vpi_handle(vpiSysTfCall, NULL);
|
|
137
|
+
args_iter = vpi_iterate(vpiArgument, systfref);
|
|
138
|
+
for (size_t i = 0; i < 5; i++) {
|
|
139
|
+
argh.push_back(vpi_scan(args_iter));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// get id
|
|
144
|
+
int id;
|
|
145
|
+
{
|
|
146
|
+
t_vpi_value argval;
|
|
147
|
+
argval.format = vpiIntVal;
|
|
148
|
+
vpi_get_value(argh[0], &argval);
|
|
149
|
+
id = argval.value.integer;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// read incoming packet
|
|
153
|
+
|
|
154
|
+
sb_packet p;
|
|
155
|
+
int success;
|
|
156
|
+
if (rxconn[id]->recv(p)) {
|
|
157
|
+
success = 1;
|
|
158
|
+
|
|
159
|
+
t_vpi_value argval;
|
|
160
|
+
|
|
161
|
+
// store data
|
|
162
|
+
argval.format = vpiVectorVal;
|
|
163
|
+
s_vpi_vecval vecval[SB_DATA_SIZE / 4];
|
|
164
|
+
argval.value.vector = vecval;
|
|
165
|
+
|
|
166
|
+
// determine the number of 32-bit words (rounding up)
|
|
167
|
+
int num_words = (rxwidth[id] + 3) / 4;
|
|
168
|
+
|
|
169
|
+
for (int i = 0; i < num_words; i++) {
|
|
170
|
+
argval.value.vector[i].aval = *((uint32_t*)(&p.data[i * 4]));
|
|
171
|
+
argval.value.vector[i].bval = 0;
|
|
172
|
+
}
|
|
173
|
+
vpi_put_value(argh[1], &argval, NULL, vpiNoDelay);
|
|
174
|
+
|
|
175
|
+
// store destination
|
|
176
|
+
argval.format = vpiIntVal;
|
|
177
|
+
argval.value.integer = p.destination;
|
|
178
|
+
vpi_put_value(argh[2], &argval, NULL, vpiNoDelay);
|
|
179
|
+
|
|
180
|
+
// store last
|
|
181
|
+
argval.format = vpiIntVal;
|
|
182
|
+
argval.value.integer = p.last ? 1 : 0;
|
|
183
|
+
vpi_put_value(argh[3], &argval, NULL, vpiNoDelay);
|
|
184
|
+
} else {
|
|
185
|
+
success = 0;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// indicate success
|
|
189
|
+
{
|
|
190
|
+
t_vpi_value argval;
|
|
191
|
+
argval.format = vpiIntVal;
|
|
192
|
+
argval.value.integer = success;
|
|
193
|
+
vpi_put_value(argh[4], &argval, NULL, vpiNoDelay);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// clean up
|
|
197
|
+
vpi_free_object(args_iter);
|
|
198
|
+
|
|
199
|
+
// return value unused?
|
|
200
|
+
return 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
PLI_INT32 pi_sb_send(PLI_BYTE8* userdata) {
|
|
204
|
+
(void)userdata; // unused
|
|
205
|
+
|
|
206
|
+
// get arguments
|
|
207
|
+
vpiHandle args_iter;
|
|
208
|
+
std::vector<vpiHandle> argh;
|
|
209
|
+
{
|
|
210
|
+
vpiHandle systfref;
|
|
211
|
+
systfref = vpi_handle(vpiSysTfCall, NULL);
|
|
212
|
+
args_iter = vpi_iterate(vpiArgument, systfref);
|
|
213
|
+
for (size_t i = 0; i < 5; i++) {
|
|
214
|
+
argh.push_back(vpi_scan(args_iter));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// get id
|
|
219
|
+
int id;
|
|
220
|
+
{
|
|
221
|
+
t_vpi_value argval;
|
|
222
|
+
argval.format = vpiIntVal;
|
|
223
|
+
vpi_get_value(argh[0], &argval);
|
|
224
|
+
id = argval.value.integer;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// get outgoing packet
|
|
228
|
+
sb_packet p;
|
|
229
|
+
{
|
|
230
|
+
t_vpi_value argval;
|
|
231
|
+
|
|
232
|
+
// store data
|
|
233
|
+
argval.format = vpiVectorVal;
|
|
234
|
+
vpi_get_value(argh[1], &argval);
|
|
235
|
+
|
|
236
|
+
// determine the number of 32-bit words (rounding up)
|
|
237
|
+
int num_words = (txwidth[id] + 3) / 4;
|
|
238
|
+
|
|
239
|
+
for (int i = 0; i < num_words; i++) {
|
|
240
|
+
*((uint32_t*)(&p.data[i * 4])) = argval.value.vector[i].aval;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// store destination
|
|
244
|
+
argval.format = vpiIntVal;
|
|
245
|
+
vpi_get_value(argh[2], &argval);
|
|
246
|
+
p.destination = argval.value.integer;
|
|
247
|
+
|
|
248
|
+
// store last
|
|
249
|
+
argval.format = vpiIntVal;
|
|
250
|
+
vpi_get_value(argh[3], &argval);
|
|
251
|
+
p.last = argval.value.integer;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// try to send packet
|
|
255
|
+
int success;
|
|
256
|
+
if (txconn[id]->send(p)) {
|
|
257
|
+
success = 1;
|
|
258
|
+
} else {
|
|
259
|
+
success = 0;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// indicate success
|
|
263
|
+
{
|
|
264
|
+
t_vpi_value argval;
|
|
265
|
+
argval.format = vpiIntVal;
|
|
266
|
+
argval.value.integer = success;
|
|
267
|
+
vpi_put_value(argh[4], &argval, NULL, vpiNoDelay);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// clean up
|
|
271
|
+
vpi_free_object(args_iter);
|
|
272
|
+
|
|
273
|
+
// return value unused?
|
|
274
|
+
return 0;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
PLI_INT32 pi_time_taken(PLI_BYTE8* userdata) {
|
|
278
|
+
(void)userdata; // unused
|
|
279
|
+
|
|
280
|
+
// get argument
|
|
281
|
+
|
|
282
|
+
vpiHandle systfref, args_iter;
|
|
283
|
+
vpiHandle argh;
|
|
284
|
+
t_vpi_value argval;
|
|
285
|
+
|
|
286
|
+
systfref = vpi_handle(vpiSysTfCall, NULL);
|
|
287
|
+
args_iter = vpi_iterate(vpiArgument, systfref);
|
|
288
|
+
argh = vpi_scan(args_iter);
|
|
289
|
+
|
|
290
|
+
// calculate the time taken
|
|
291
|
+
std::chrono::steady_clock::time_point stop_time = std::chrono::steady_clock::now();
|
|
292
|
+
double t =
|
|
293
|
+
1.0e-6 *
|
|
294
|
+
(std::chrono::duration_cast<std::chrono::microseconds>(stop_time - start_time).count());
|
|
295
|
+
start_time = stop_time;
|
|
296
|
+
|
|
297
|
+
// store the time taken
|
|
298
|
+
argval.format = vpiRealVal;
|
|
299
|
+
argval.value.real = t;
|
|
300
|
+
vpi_put_value(argh, &argval, NULL, vpiNoDelay);
|
|
301
|
+
|
|
302
|
+
// clean up
|
|
303
|
+
vpi_free_object(args_iter);
|
|
304
|
+
|
|
305
|
+
// return value unused?
|
|
306
|
+
return 0;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
PLI_INT32 pi_start_delay(PLI_BYTE8* userdata) {
|
|
310
|
+
(void)userdata; // unused
|
|
311
|
+
|
|
312
|
+
// get arguments
|
|
313
|
+
vpiHandle args_iter;
|
|
314
|
+
std::vector<vpiHandle> argh;
|
|
315
|
+
{
|
|
316
|
+
vpiHandle systfref;
|
|
317
|
+
systfref = vpi_handle(vpiSysTfCall, NULL);
|
|
318
|
+
args_iter = vpi_iterate(vpiArgument, systfref);
|
|
319
|
+
for (size_t i = 0; i < 1; i++) {
|
|
320
|
+
argh.push_back(vpi_scan(args_iter));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// get value
|
|
325
|
+
double value;
|
|
326
|
+
{
|
|
327
|
+
t_vpi_value argval;
|
|
328
|
+
argval.format = vpiRealVal;
|
|
329
|
+
vpi_get_value(argh[0], &argval);
|
|
330
|
+
value = argval.value.real;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// call the underlying switchboard function
|
|
334
|
+
start_delay(value);
|
|
335
|
+
|
|
336
|
+
// clean up
|
|
337
|
+
vpi_free_object(args_iter);
|
|
338
|
+
|
|
339
|
+
// return value unused?
|
|
340
|
+
return 0;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
PLI_INT32 pi_max_rate_tick(PLI_BYTE8* userdata) {
|
|
344
|
+
(void)userdata; // unused
|
|
345
|
+
|
|
346
|
+
// get arguments
|
|
347
|
+
vpiHandle args_iter;
|
|
348
|
+
std::vector<vpiHandle> argh;
|
|
349
|
+
{
|
|
350
|
+
vpiHandle systfref;
|
|
351
|
+
systfref = vpi_handle(vpiSysTfCall, NULL);
|
|
352
|
+
args_iter = vpi_iterate(vpiArgument, systfref);
|
|
353
|
+
for (size_t i = 0; i < 2; i++) {
|
|
354
|
+
argh.push_back(vpi_scan(args_iter));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// get the timestamp
|
|
359
|
+
long t_us = 0;
|
|
360
|
+
{
|
|
361
|
+
t_vpi_value argval;
|
|
362
|
+
argval.format = vpiVectorVal;
|
|
363
|
+
vpi_get_value(argh[0], &argval);
|
|
364
|
+
|
|
365
|
+
t_us |= argval.value.vector[1].aval & 0xffffffff;
|
|
366
|
+
t_us <<= 32;
|
|
367
|
+
t_us |= argval.value.vector[0].aval & 0xffffffff;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// get max rate
|
|
371
|
+
double max_rate;
|
|
372
|
+
{
|
|
373
|
+
t_vpi_value argval;
|
|
374
|
+
argval.format = vpiRealVal;
|
|
375
|
+
vpi_get_value(argh[1], &argval);
|
|
376
|
+
max_rate = argval.value.real;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// call the underlying switchboard function
|
|
380
|
+
max_rate_tick(t_us, max_rate);
|
|
381
|
+
|
|
382
|
+
// set the timestamp
|
|
383
|
+
{
|
|
384
|
+
t_vpi_value argval;
|
|
385
|
+
argval.format = vpiVectorVal;
|
|
386
|
+
s_vpi_vecval vecval[2]; // two 32-bit words
|
|
387
|
+
argval.value.vector = vecval;
|
|
388
|
+
|
|
389
|
+
argval.value.vector[0].aval = t_us & 0xffffffff;
|
|
390
|
+
argval.value.vector[0].bval = 0;
|
|
391
|
+
|
|
392
|
+
argval.value.vector[1].aval = (t_us >> 32) & 0xffffffff;
|
|
393
|
+
argval.value.vector[1].bval = 0;
|
|
394
|
+
|
|
395
|
+
vpi_put_value(argh[0], &argval, NULL, vpiNoDelay);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// clean up
|
|
399
|
+
vpi_free_object(args_iter);
|
|
400
|
+
|
|
401
|
+
// return value unused?
|
|
402
|
+
return 0;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// macro that creates a function to register PLI functions
|
|
406
|
+
|
|
407
|
+
#define VPI_REGISTER_FUNC_NAME(name) register_##name
|
|
408
|
+
#define VPI_REGISTER_FUNC(name) \
|
|
409
|
+
void VPI_REGISTER_FUNC_NAME(name)(void) { \
|
|
410
|
+
s_vpi_systf_data data = {vpiSysTask, 0, (char*)("$" #name), name, 0, 0, 0}; \
|
|
411
|
+
\
|
|
412
|
+
vpi_register_systf(&data); \
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// create the PLI registration functions using this macro
|
|
416
|
+
|
|
417
|
+
VPI_REGISTER_FUNC(pi_sb_rx_init)
|
|
418
|
+
VPI_REGISTER_FUNC(pi_sb_tx_init)
|
|
419
|
+
VPI_REGISTER_FUNC(pi_sb_recv)
|
|
420
|
+
VPI_REGISTER_FUNC(pi_sb_send)
|
|
421
|
+
VPI_REGISTER_FUNC(pi_time_taken)
|
|
422
|
+
VPI_REGISTER_FUNC(pi_start_delay)
|
|
423
|
+
VPI_REGISTER_FUNC(pi_max_rate_tick)
|
|
424
|
+
|
|
425
|
+
void (*vlog_startup_routines[])(void) = {
|
|
426
|
+
VPI_REGISTER_FUNC_NAME(pi_sb_rx_init), VPI_REGISTER_FUNC_NAME(pi_sb_tx_init),
|
|
427
|
+
VPI_REGISTER_FUNC_NAME(pi_sb_recv), VPI_REGISTER_FUNC_NAME(pi_sb_send),
|
|
428
|
+
VPI_REGISTER_FUNC_NAME(pi_time_taken), VPI_REGISTER_FUNC_NAME(pi_start_delay),
|
|
429
|
+
VPI_REGISTER_FUNC_NAME(pi_max_rate_tick),
|
|
430
|
+
0 // last entry must be 0
|
|
431
|
+
};
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// Copyright (c) 2024 Zero ASIC Corporation
|
|
2
|
+
// This code is licensed under Apache License 2.0 (see LICENSE for details)
|
|
3
|
+
|
|
4
|
+
#include <vpi_user.h>
|
|
5
|
+
|
|
6
|
+
#include <memory>
|
|
7
|
+
#include <string>
|
|
8
|
+
#include <vector>
|
|
9
|
+
|
|
10
|
+
#include <stdio.h>
|
|
11
|
+
#include <stdlib.h>
|
|
12
|
+
|
|
13
|
+
#include "xyce.hpp"
|
|
14
|
+
|
|
15
|
+
static std::vector<std::unique_ptr<XyceIntf>> xyceIntfs;
|
|
16
|
+
|
|
17
|
+
PLI_INT32 pi_sb_xyce_init(PLI_BYTE8* userdata) {
|
|
18
|
+
(void)userdata; // unused
|
|
19
|
+
|
|
20
|
+
// get arguments
|
|
21
|
+
vpiHandle args_iter;
|
|
22
|
+
std::vector<vpiHandle> argh;
|
|
23
|
+
{
|
|
24
|
+
vpiHandle systfref;
|
|
25
|
+
systfref = vpi_handle(vpiSysTfCall, NULL);
|
|
26
|
+
args_iter = vpi_iterate(vpiArgument, systfref);
|
|
27
|
+
for (size_t i = 0; i < 2; i++) {
|
|
28
|
+
argh.push_back(vpi_scan(args_iter));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// get file
|
|
33
|
+
std::string file;
|
|
34
|
+
{
|
|
35
|
+
t_vpi_value argval;
|
|
36
|
+
argval.format = vpiStringVal;
|
|
37
|
+
vpi_get_value(argh[1], &argval);
|
|
38
|
+
file = std::string(argval.value.str);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
xyceIntfs.push_back(std::unique_ptr<XyceIntf>(new XyceIntf()));
|
|
42
|
+
xyceIntfs.back()->init(file);
|
|
43
|
+
|
|
44
|
+
// put ID
|
|
45
|
+
{
|
|
46
|
+
t_vpi_value argval;
|
|
47
|
+
argval.format = vpiIntVal;
|
|
48
|
+
argval.value.integer = xyceIntfs.size() - 1;
|
|
49
|
+
vpi_put_value(argh[0], &argval, NULL, vpiNoDelay);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// clean up
|
|
53
|
+
vpi_free_object(args_iter);
|
|
54
|
+
|
|
55
|
+
// return value unused?
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
PLI_INT32 pi_sb_xyce_put(PLI_BYTE8* userdata) {
|
|
60
|
+
(void)userdata; // unused
|
|
61
|
+
|
|
62
|
+
// get arguments
|
|
63
|
+
vpiHandle args_iter;
|
|
64
|
+
std::vector<vpiHandle> argh;
|
|
65
|
+
{
|
|
66
|
+
vpiHandle systfref;
|
|
67
|
+
systfref = vpi_handle(vpiSysTfCall, NULL);
|
|
68
|
+
args_iter = vpi_iterate(vpiArgument, systfref);
|
|
69
|
+
for (size_t i = 0; i < 4; i++) {
|
|
70
|
+
argh.push_back(vpi_scan(args_iter));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// get ID
|
|
75
|
+
int id;
|
|
76
|
+
{
|
|
77
|
+
t_vpi_value argval;
|
|
78
|
+
argval.format = vpiIntVal;
|
|
79
|
+
vpi_get_value(argh[0], &argval);
|
|
80
|
+
id = argval.value.integer;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// get name
|
|
84
|
+
std::string name;
|
|
85
|
+
{
|
|
86
|
+
t_vpi_value argval;
|
|
87
|
+
argval.format = vpiStringVal;
|
|
88
|
+
vpi_get_value(argh[1], &argval);
|
|
89
|
+
name = std::string(argval.value.str);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// get time
|
|
93
|
+
double time;
|
|
94
|
+
{
|
|
95
|
+
t_vpi_value argval;
|
|
96
|
+
argval.format = vpiRealVal;
|
|
97
|
+
vpi_get_value(argh[2], &argval);
|
|
98
|
+
time = argval.value.real;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// get value
|
|
102
|
+
double value;
|
|
103
|
+
{
|
|
104
|
+
t_vpi_value argval;
|
|
105
|
+
argval.format = vpiRealVal;
|
|
106
|
+
vpi_get_value(argh[3], &argval);
|
|
107
|
+
value = argval.value.real;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
xyceIntfs[id]->put(name, time, value);
|
|
111
|
+
|
|
112
|
+
// clean up
|
|
113
|
+
vpi_free_object(args_iter);
|
|
114
|
+
|
|
115
|
+
// return value unused?
|
|
116
|
+
return 0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
PLI_INT32 pi_sb_xyce_get(PLI_BYTE8* userdata) {
|
|
120
|
+
(void)userdata; // unused
|
|
121
|
+
|
|
122
|
+
// get arguments
|
|
123
|
+
vpiHandle args_iter;
|
|
124
|
+
std::vector<vpiHandle> argh;
|
|
125
|
+
{
|
|
126
|
+
vpiHandle systfref;
|
|
127
|
+
systfref = vpi_handle(vpiSysTfCall, NULL);
|
|
128
|
+
args_iter = vpi_iterate(vpiArgument, systfref);
|
|
129
|
+
for (size_t i = 0; i < 4; i++) {
|
|
130
|
+
argh.push_back(vpi_scan(args_iter));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// get ID
|
|
135
|
+
int id;
|
|
136
|
+
{
|
|
137
|
+
t_vpi_value argval;
|
|
138
|
+
argval.format = vpiIntVal;
|
|
139
|
+
vpi_get_value(argh[0], &argval);
|
|
140
|
+
id = argval.value.integer;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// get name
|
|
144
|
+
std::string name;
|
|
145
|
+
{
|
|
146
|
+
t_vpi_value argval;
|
|
147
|
+
argval.format = vpiStringVal;
|
|
148
|
+
vpi_get_value(argh[1], &argval);
|
|
149
|
+
name = std::string(argval.value.str);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// get time
|
|
153
|
+
double time;
|
|
154
|
+
{
|
|
155
|
+
t_vpi_value argval;
|
|
156
|
+
argval.format = vpiRealVal;
|
|
157
|
+
vpi_get_value(argh[2], &argval);
|
|
158
|
+
time = argval.value.real;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// get value
|
|
162
|
+
double value;
|
|
163
|
+
xyceIntfs[id]->get(name, time, &value);
|
|
164
|
+
|
|
165
|
+
// put value
|
|
166
|
+
{
|
|
167
|
+
t_vpi_value argval;
|
|
168
|
+
argval.format = vpiRealVal;
|
|
169
|
+
argval.value.real = value;
|
|
170
|
+
vpi_put_value(argh[3], &argval, NULL, vpiNoDelay);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// clean up
|
|
174
|
+
vpi_free_object(args_iter);
|
|
175
|
+
|
|
176
|
+
// return value unused?
|
|
177
|
+
return 0;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// macro that creates a function to register PLI functions
|
|
181
|
+
|
|
182
|
+
#define VPI_REGISTER_FUNC_NAME(name) register_##name
|
|
183
|
+
#define VPI_REGISTER_FUNC(name) \
|
|
184
|
+
void VPI_REGISTER_FUNC_NAME(name)(void) { \
|
|
185
|
+
s_vpi_systf_data data = {vpiSysTask, 0, (char*)("$" #name), name, 0, 0, 0}; \
|
|
186
|
+
\
|
|
187
|
+
vpi_register_systf(&data); \
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// create the PLI registration functions using this macro
|
|
191
|
+
|
|
192
|
+
VPI_REGISTER_FUNC(pi_sb_xyce_init)
|
|
193
|
+
VPI_REGISTER_FUNC(pi_sb_xyce_put)
|
|
194
|
+
VPI_REGISTER_FUNC(pi_sb_xyce_get)
|
|
195
|
+
|
|
196
|
+
void (*vlog_startup_routines[])(void) = {
|
|
197
|
+
VPI_REGISTER_FUNC_NAME(pi_sb_xyce_init), VPI_REGISTER_FUNC_NAME(pi_sb_xyce_put),
|
|
198
|
+
VPI_REGISTER_FUNC_NAME(pi_sb_xyce_get),
|
|
199
|
+
0 // last entry must be 0
|
|
200
|
+
};
|
switchboard/warn.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Infrastructure for printing deprecation warnings
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2024 Zero ASIC Corporation
|
|
4
|
+
# This code is licensed under Apache License 2.0 (see LICENSE for details)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import warnings
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
warnings.simplefilter('once', FutureWarning)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def warn_future(msg: str):
|
|
14
|
+
warnings.warn(msg, category=FutureWarning)
|
switchboard/xyce.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Utilities for working with Xyce
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2024 Zero ASIC Corporation
|
|
4
|
+
# This code is licensed under Apache License 2.0 (see LICENSE for details)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def xyce_flags():
|
|
8
|
+
import shutil
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
xyce = shutil.which('Xyce')
|
|
12
|
+
|
|
13
|
+
if not xyce:
|
|
14
|
+
raise RuntimeError('Xyce install not found')
|
|
15
|
+
|
|
16
|
+
xyce_prefix = Path(xyce).parent.parent
|
|
17
|
+
|
|
18
|
+
ldflags = [
|
|
19
|
+
f'-L{xyce_prefix / "lib"}',
|
|
20
|
+
'-lxycecinterface'
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
cincludes = [
|
|
24
|
+
f'{xyce_prefix / "include"}'
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
return cincludes, ldflags
|