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.
- _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
switchboard/util.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# General utilities for working with switchboard
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2024 Zero ASIC Corporation
|
|
4
|
+
# This code is licensed under Apache License 2.0 (see LICENSE for details)
|
|
5
|
+
|
|
6
|
+
import atexit
|
|
7
|
+
import signal
|
|
8
|
+
import subprocess
|
|
9
|
+
import shlex
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def plusargs_to_args(plusargs):
|
|
13
|
+
args = []
|
|
14
|
+
if plusargs is not None:
|
|
15
|
+
if not isinstance(plusargs, list):
|
|
16
|
+
raise TypeError('plusargs must be a list')
|
|
17
|
+
for plusarg in plusargs:
|
|
18
|
+
if isinstance(plusarg, (list, tuple)):
|
|
19
|
+
if len(plusarg) != 2:
|
|
20
|
+
raise ValueError('Only lists/tuples of length 2 allowed')
|
|
21
|
+
args += [f'+{plusarg[0]}={plusarg[1]}']
|
|
22
|
+
else:
|
|
23
|
+
args += [f'+{plusarg}']
|
|
24
|
+
return args
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def binary_run(bin, args=None, stop_timeout=10, use_sigint=False,
|
|
28
|
+
quiet=False, print_command=False, cwd=None, env=None):
|
|
29
|
+
|
|
30
|
+
cmd = []
|
|
31
|
+
|
|
32
|
+
cmd += [bin]
|
|
33
|
+
|
|
34
|
+
if args is not None:
|
|
35
|
+
if not isinstance(args, list):
|
|
36
|
+
raise TypeError('args must be a list')
|
|
37
|
+
cmd += args
|
|
38
|
+
|
|
39
|
+
cmd = [str(elem) for elem in cmd]
|
|
40
|
+
if print_command:
|
|
41
|
+
print(' '.join([shlex.quote(elem) for elem in cmd]))
|
|
42
|
+
|
|
43
|
+
kwargs = {}
|
|
44
|
+
if quiet:
|
|
45
|
+
kwargs['stdout'] = subprocess.DEVNULL
|
|
46
|
+
kwargs['stderr'] = subprocess.DEVNULL
|
|
47
|
+
|
|
48
|
+
p = subprocess.Popen(cmd, cwd=cwd, env=env, **kwargs)
|
|
49
|
+
|
|
50
|
+
def stop_bin(p=p, stop_timeout=stop_timeout, use_sigint=use_sigint):
|
|
51
|
+
poll = p.poll()
|
|
52
|
+
if poll is not None:
|
|
53
|
+
# process has stopped
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
if use_sigint:
|
|
57
|
+
try:
|
|
58
|
+
p.send_signal(signal.SIGINT)
|
|
59
|
+
p.wait(stop_timeout)
|
|
60
|
+
return
|
|
61
|
+
except: # noqa: E722
|
|
62
|
+
# if there is an exception for any reason, including
|
|
63
|
+
# Ctrl-C during the wait() call, want to make sure
|
|
64
|
+
# that the process is actually terminated
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
# if we get to this point, the process is still running
|
|
68
|
+
# and sigint didn't work (or we didn't try it)
|
|
69
|
+
p.terminate()
|
|
70
|
+
|
|
71
|
+
# note: tried combining all process terminations into a single
|
|
72
|
+
# function registered with atexit, but it didn't appear to make
|
|
73
|
+
# a difference when running with a few hundred verilator sim
|
|
74
|
+
# processes - still took a few dozen milliseconds to stop each
|
|
75
|
+
# simulator.
|
|
76
|
+
|
|
77
|
+
atexit.register(stop_bin)
|
|
78
|
+
|
|
79
|
+
return p
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class ProcessCollection:
|
|
83
|
+
def __init__(self):
|
|
84
|
+
self.processes = []
|
|
85
|
+
|
|
86
|
+
def add(self, process):
|
|
87
|
+
self.processes.append(process)
|
|
88
|
+
|
|
89
|
+
def wait(self):
|
|
90
|
+
import subprocess
|
|
91
|
+
import multiprocessing
|
|
92
|
+
|
|
93
|
+
for process in self.processes:
|
|
94
|
+
if isinstance(process, subprocess.Popen):
|
|
95
|
+
process.wait()
|
|
96
|
+
elif isinstance(process, multiprocessing.Process):
|
|
97
|
+
process.join()
|
|
98
|
+
else:
|
|
99
|
+
raise Exception(f'Unknown process type: {type(process)}')
|
|
100
|
+
|
|
101
|
+
def terminate(
|
|
102
|
+
self,
|
|
103
|
+
stop_timeout=10,
|
|
104
|
+
use_sigint=False
|
|
105
|
+
):
|
|
106
|
+
if not self.processes:
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
for p in self.processes:
|
|
110
|
+
if isinstance(p, ProcessCollection):
|
|
111
|
+
p.terminate(stop_timeout=stop_timeout, use_sigint=use_sigint)
|
|
112
|
+
else:
|
|
113
|
+
poll = p.poll()
|
|
114
|
+
if poll is not None:
|
|
115
|
+
# process has stopped
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
if use_sigint:
|
|
119
|
+
try:
|
|
120
|
+
p.send_signal(signal.SIGINT)
|
|
121
|
+
p.wait(stop_timeout)
|
|
122
|
+
return
|
|
123
|
+
except: # noqa: E722
|
|
124
|
+
# if there is an exception for any reason, including
|
|
125
|
+
# Ctrl-C during the wait() call, want to make sure
|
|
126
|
+
# that the process is actually terminated
|
|
127
|
+
pass
|
|
128
|
+
|
|
129
|
+
# if we get to this point, the process is still running
|
|
130
|
+
# and sigint didn't work (or we didn't try it)
|
|
131
|
+
p.terminate()
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This file silences Verilator warnings in the verilog-axi third party library.
|
|
2
|
+
// Note: this file must be passed to Verilator *before* Verilog sources.
|
|
3
|
+
|
|
4
|
+
// Copyright (c) 2024 Zero ASIC Corporation
|
|
5
|
+
// This code is licensed under Apache License 2.0 (see LICENSE for details)
|
|
6
|
+
|
|
7
|
+
`verilator_config
|
|
8
|
+
|
|
9
|
+
lint_off -file "*/deps/verilog-axi/rtl/*"
|
|
10
|
+
|
|
11
|
+
// For some reason these are not caught by the blanket statement above
|
|
12
|
+
lint_off -rule UNOPTFLAT -file "*/deps/verilog-axi/rtl/*"
|
|
13
|
+
lint_off -rule INITIALDLY -file "*/deps/verilog-axi/rtl/*"
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// Copyright (c) 2024 Zero ASIC Corporation
|
|
2
|
+
// This code is licensed under Apache License 2.0 (see LICENSE for details)
|
|
3
|
+
|
|
4
|
+
// modified from examples/make_tracing_c/sim_main.cpp in https://github.com/verilator/verilator,
|
|
5
|
+
// by Wilson Snyder (2017), released as Creative Commons Public Domain
|
|
6
|
+
|
|
7
|
+
// For Ctrl-C handling
|
|
8
|
+
#include <signal.h>
|
|
9
|
+
|
|
10
|
+
// For std::unique_ptr
|
|
11
|
+
#include <memory>
|
|
12
|
+
|
|
13
|
+
// For changing the clock period
|
|
14
|
+
#include <cmath>
|
|
15
|
+
#include <iostream>
|
|
16
|
+
#include <sstream>
|
|
17
|
+
#include <string>
|
|
18
|
+
|
|
19
|
+
// Include common routines
|
|
20
|
+
#include <verilated.h>
|
|
21
|
+
|
|
22
|
+
// Include model header, generated from Verilating "top.v"
|
|
23
|
+
#include "Vtestbench.h"
|
|
24
|
+
|
|
25
|
+
// Include switchboard functions
|
|
26
|
+
#include "switchboard.hpp"
|
|
27
|
+
|
|
28
|
+
// Legacy function required only so linking works on Cygwin and MSVC++
|
|
29
|
+
double sc_time_stamp() {
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ref: https://stackoverflow.com/a/4217052
|
|
34
|
+
static volatile int got_sigint = 0;
|
|
35
|
+
|
|
36
|
+
void sigint_handler(int unused) {
|
|
37
|
+
got_sigint = 1;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
std::string extract_plusarg_value(const char* match, const char* name) {
|
|
41
|
+
if (match) {
|
|
42
|
+
std::string full = std::string(match);
|
|
43
|
+
std::string prefix = "+" + std::string(name) + "=";
|
|
44
|
+
size_t len = prefix.size();
|
|
45
|
+
// match requirements: there must be at least one character after
|
|
46
|
+
// the prefix, and the argument must start with the prefix,
|
|
47
|
+
// ignoring the last character of the prefix, which can be
|
|
48
|
+
// anything (typically "=" or "+")
|
|
49
|
+
if ((full.size() >= (len + 1)) && (full.substr(0, len - 1) == prefix.substr(0, len - 1))) {
|
|
50
|
+
return std::string(match).substr(len);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// if we get here, return an empty string
|
|
55
|
+
return "";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
template <typename T> void parse_plusarg(const char* match, const char* name, T& result) {
|
|
59
|
+
std::string value = extract_plusarg_value(match, name);
|
|
60
|
+
|
|
61
|
+
if (value != "") {
|
|
62
|
+
std::istringstream iss(value);
|
|
63
|
+
iss >> result;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
int main(int argc, char** argv, char** env) {
|
|
68
|
+
// Prevent unused variable warnings
|
|
69
|
+
if (false && argc && argv && env) {}
|
|
70
|
+
|
|
71
|
+
// Using unique_ptr is similar to
|
|
72
|
+
// "VerilatedContext* contextp = new VerilatedContext" then deleting at end.
|
|
73
|
+
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
|
|
74
|
+
// Do not instead make Vtop as a file-scope static variable, as the
|
|
75
|
+
// "C++ static initialization order fiasco" may cause a crash
|
|
76
|
+
|
|
77
|
+
// Verilator must compute traced signals
|
|
78
|
+
contextp->traceEverOn(true);
|
|
79
|
+
|
|
80
|
+
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
|
|
81
|
+
// This needs to be called before you create any model
|
|
82
|
+
contextp->commandArgs(argc, argv);
|
|
83
|
+
|
|
84
|
+
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v".
|
|
85
|
+
// Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end.
|
|
86
|
+
// "TOP" will be the hierarchical name of the module.
|
|
87
|
+
const std::unique_ptr<Vtestbench> top{new Vtestbench{contextp.get(), "TOP"}};
|
|
88
|
+
|
|
89
|
+
// parse the clock period, if provided
|
|
90
|
+
double period = 10e-9;
|
|
91
|
+
const char* period_match = contextp->commandArgsPlusMatch("period");
|
|
92
|
+
parse_plusarg<double>(period_match, "period", period);
|
|
93
|
+
|
|
94
|
+
// parse the maximum simulation rate, if provided. convert it to a target
|
|
95
|
+
// period in microseconds
|
|
96
|
+
|
|
97
|
+
double max_rate = -1;
|
|
98
|
+
const char* rate_match = contextp->commandArgsPlusMatch("max-rate");
|
|
99
|
+
parse_plusarg<double>(rate_match, "max-rate", max_rate);
|
|
100
|
+
|
|
101
|
+
// convert the clock period an integer, scaling by the time precision
|
|
102
|
+
uint64_t iperiod = std::round(period * std::pow(10.0, -1.0 * contextp->timeprecision()));
|
|
103
|
+
uint64_t duration0 = iperiod / 2;
|
|
104
|
+
uint64_t duration1 = iperiod - duration0;
|
|
105
|
+
|
|
106
|
+
// Set Vtestbench's input signals
|
|
107
|
+
top->clk = 0;
|
|
108
|
+
top->eval();
|
|
109
|
+
|
|
110
|
+
// Set up Ctrl-C handler
|
|
111
|
+
signal(SIGINT, sigint_handler);
|
|
112
|
+
|
|
113
|
+
// Optional delay before setting up main loop
|
|
114
|
+
|
|
115
|
+
double start_delay_value = -1;
|
|
116
|
+
const char* delay_match = contextp->commandArgsPlusMatch("start-delay");
|
|
117
|
+
parse_plusarg<double>(delay_match, "start-delay", start_delay_value);
|
|
118
|
+
|
|
119
|
+
start_delay(start_delay_value);
|
|
120
|
+
|
|
121
|
+
// Main loop
|
|
122
|
+
|
|
123
|
+
long t_us = -1;
|
|
124
|
+
long min_period_us = (1.0e6 / max_rate) + 0.5;
|
|
125
|
+
|
|
126
|
+
while (!(contextp->gotFinish() || got_sigint)) {
|
|
127
|
+
max_rate_tick(t_us, min_period_us);
|
|
128
|
+
|
|
129
|
+
contextp->timeInc(duration0);
|
|
130
|
+
top->clk = 1;
|
|
131
|
+
top->eval();
|
|
132
|
+
contextp->timeInc(duration1);
|
|
133
|
+
top->clk = 0;
|
|
134
|
+
top->eval();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Final model cleanup
|
|
138
|
+
top->final();
|
|
139
|
+
|
|
140
|
+
// Return good completion status
|
|
141
|
+
// Don't use exit() or destructor won't get called
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from siliconcompiler import Design
|
|
2
|
+
|
|
3
|
+
from switchboard import sb_path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Verilator(Design):
|
|
7
|
+
def __init__(self):
|
|
8
|
+
super().__init__("verilator")
|
|
9
|
+
|
|
10
|
+
self.set_dataroot('localroot', sb_path() / "verilator")
|
|
11
|
+
|
|
12
|
+
with self.active_fileset('verilator'):
|
|
13
|
+
self.add_file("testbench.cc")
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Utilities for working with Verilator
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2024 Zero ASIC Corporation
|
|
4
|
+
# This code is licensed under Apache License 2.0 (see LICENSE for details)
|
|
5
|
+
|
|
6
|
+
# TODO: replace with SiliconCompiler functionality
|
|
7
|
+
|
|
8
|
+
from .util import plusargs_to_args, binary_run
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def verilator_run(bin, plusargs=None, args=None, use_sigint=True, **kwargs):
|
|
12
|
+
if args is None:
|
|
13
|
+
extra_args = []
|
|
14
|
+
elif isinstance(args, (list, tuple)):
|
|
15
|
+
# even if args is already a list, make a copy to
|
|
16
|
+
# ensure that changes don't propagate back to the
|
|
17
|
+
# value that the user provided for args
|
|
18
|
+
extra_args = list(args)
|
|
19
|
+
else:
|
|
20
|
+
# if the user provided a single value for args,
|
|
21
|
+
# wrap it in a list rather than erroring out
|
|
22
|
+
extra_args = [args]
|
|
23
|
+
|
|
24
|
+
# build up the argument list
|
|
25
|
+
args = []
|
|
26
|
+
args += plusargs_to_args(plusargs)
|
|
27
|
+
|
|
28
|
+
# append any extra arguments user provided by the user
|
|
29
|
+
args += extra_args
|
|
30
|
+
|
|
31
|
+
return binary_run(bin=bin, args=args, use_sigint=use_sigint, **kwargs)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from siliconcompiler import Design
|
|
2
|
+
|
|
3
|
+
from umi.sumi import Unpack, Pack
|
|
4
|
+
|
|
5
|
+
from switchboard import sb_path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Common(Design):
|
|
9
|
+
def __init__(self):
|
|
10
|
+
|
|
11
|
+
super().__init__("common")
|
|
12
|
+
|
|
13
|
+
files = [
|
|
14
|
+
"uart_xactor.sv",
|
|
15
|
+
"umi_gpio.v"
|
|
16
|
+
]
|
|
17
|
+
deps = [Unpack(), Pack()]
|
|
18
|
+
|
|
19
|
+
self.set_dataroot('sb_verilog_common', sb_path() / "verilog" / "common")
|
|
20
|
+
|
|
21
|
+
with self.active_fileset('rtl'):
|
|
22
|
+
self.add_idir(".")
|
|
23
|
+
for item in files:
|
|
24
|
+
self.add_file(item)
|
|
25
|
+
for item in deps:
|
|
26
|
+
self.add_depfileset(item)
|