switchboard-hw 0.3.0__cp314-cp314-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. _switchboard.cpython-314-darwin.so +0 -0
  2. switchboard/__init__.py +24 -0
  3. switchboard/ams.py +668 -0
  4. switchboard/apb.py +278 -0
  5. switchboard/autowrap.py +1000 -0
  6. switchboard/axi.py +571 -0
  7. switchboard/axil.py +348 -0
  8. switchboard/bitvector.py +112 -0
  9. switchboard/cmdline.py +142 -0
  10. switchboard/cpp/Makefile +13 -0
  11. switchboard/cpp/bitutil.h +39 -0
  12. switchboard/cpp/pagemap.h +91 -0
  13. switchboard/cpp/pciedev.h +86 -0
  14. switchboard/cpp/router.cc +89 -0
  15. switchboard/cpp/spsc_queue.h +267 -0
  16. switchboard/cpp/switchboard.hpp +257 -0
  17. switchboard/cpp/switchboard_pcie.hpp +234 -0
  18. switchboard/cpp/switchboard_tlm.hpp +98 -0
  19. switchboard/cpp/umilib.h +144 -0
  20. switchboard/cpp/umilib.hpp +113 -0
  21. switchboard/cpp/umisb.hpp +364 -0
  22. switchboard/cpp/xyce.hpp +90 -0
  23. switchboard/deps/__init__.py +0 -0
  24. switchboard/deps/verilog_axi.py +23 -0
  25. switchboard/dpi/__init__.py +0 -0
  26. switchboard/dpi/switchboard_dpi.cc +119 -0
  27. switchboard/dpi/switchboard_dpi.py +13 -0
  28. switchboard/dpi/xyce_dpi.cc +43 -0
  29. switchboard/gpio.py +108 -0
  30. switchboard/icarus.py +85 -0
  31. switchboard/loopback.py +157 -0
  32. switchboard/network.py +714 -0
  33. switchboard/pytest_plugin.py +11 -0
  34. switchboard/sbdesign.py +55 -0
  35. switchboard/sbdut.py +744 -0
  36. switchboard/sbtcp.py +345 -0
  37. switchboard/sc/__init__.py +0 -0
  38. switchboard/sc/morty/__init__.py +0 -0
  39. switchboard/sc/morty/uniquify.py +67 -0
  40. switchboard/sc/sed/__init__.py +0 -0
  41. switchboard/sc/sed/sed_remove.py +47 -0
  42. switchboard/sc/standalone_netlist_flow.py +25 -0
  43. switchboard/switchboard.py +53 -0
  44. switchboard/test_util.py +46 -0
  45. switchboard/uart_xactor.py +66 -0
  46. switchboard/umi.py +793 -0
  47. switchboard/util.py +131 -0
  48. switchboard/verilator/__init__.py +0 -0
  49. switchboard/verilator/config.vlt +13 -0
  50. switchboard/verilator/testbench.cc +143 -0
  51. switchboard/verilator/verilator.py +13 -0
  52. switchboard/verilator_run.py +31 -0
  53. switchboard/verilog/__init__.py +0 -0
  54. switchboard/verilog/common/__init__.py +0 -0
  55. switchboard/verilog/common/common.py +26 -0
  56. switchboard/verilog/common/switchboard.vh +429 -0
  57. switchboard/verilog/common/uart_xactor.sv +247 -0
  58. switchboard/verilog/common/umi_gpio.v +236 -0
  59. switchboard/verilog/fpga/__init__.py +0 -0
  60. switchboard/verilog/fpga/axi_reader.sv +82 -0
  61. switchboard/verilog/fpga/axi_writer.sv +111 -0
  62. switchboard/verilog/fpga/config_registers.sv +249 -0
  63. switchboard/verilog/fpga/fpga.py +21 -0
  64. switchboard/verilog/fpga/include/sb_queue_regmap.vh +21 -0
  65. switchboard/verilog/fpga/include/spsc_queue.vh +7 -0
  66. switchboard/verilog/fpga/memory_fault.sv +40 -0
  67. switchboard/verilog/fpga/sb_fpga_queues.sv +416 -0
  68. switchboard/verilog/fpga/sb_rx_fpga.sv +303 -0
  69. switchboard/verilog/fpga/sb_tx_fpga.sv +294 -0
  70. switchboard/verilog/fpga/umi_fpga_queues.sv +146 -0
  71. switchboard/verilog/sim/__init__.py +0 -0
  72. switchboard/verilog/sim/auto_stop_sim.sv +25 -0
  73. switchboard/verilog/sim/perf_meas_sim.sv +97 -0
  74. switchboard/verilog/sim/queue_to_sb_sim.sv +176 -0
  75. switchboard/verilog/sim/queue_to_umi_sim.sv +66 -0
  76. switchboard/verilog/sim/sb_apb_m.sv +146 -0
  77. switchboard/verilog/sim/sb_axi_m.sv +199 -0
  78. switchboard/verilog/sim/sb_axil_m.sv +180 -0
  79. switchboard/verilog/sim/sb_axil_s.sv +180 -0
  80. switchboard/verilog/sim/sb_clk_gen.sv +89 -0
  81. switchboard/verilog/sim/sb_jtag_rbb_sim.sv +148 -0
  82. switchboard/verilog/sim/sb_rx_sim.sv +55 -0
  83. switchboard/verilog/sim/sb_to_queue_sim.sv +196 -0
  84. switchboard/verilog/sim/sb_tx_sim.sv +55 -0
  85. switchboard/verilog/sim/switchboard_sim.py +49 -0
  86. switchboard/verilog/sim/umi_rx_sim.sv +61 -0
  87. switchboard/verilog/sim/umi_to_queue_sim.sv +66 -0
  88. switchboard/verilog/sim/umi_tx_sim.sv +61 -0
  89. switchboard/verilog/sim/xyce_intf.sv +67 -0
  90. switchboard/vpi/switchboard_vpi.cc +431 -0
  91. switchboard/vpi/xyce_vpi.cc +200 -0
  92. switchboard/warn.py +14 -0
  93. switchboard/xyce.py +27 -0
  94. switchboard_hw-0.3.0.dist-info/METADATA +303 -0
  95. switchboard_hw-0.3.0.dist-info/RECORD +99 -0
  96. switchboard_hw-0.3.0.dist-info/WHEEL +6 -0
  97. switchboard_hw-0.3.0.dist-info/entry_points.txt +6 -0
  98. switchboard_hw-0.3.0.dist-info/licenses/LICENSE +190 -0
  99. 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