Skip to main content

A low-latency communication library for RTL simulation and emulation.

Project description

Switchboard

Actions Status Documentation Status PyPI version License

Switchboard (SB) is a framework for communication between distinct hardware models, such as RTL simulations, RTL implemented on FPGAs, and fast SW models. This makes it possible to simulate large hardware systems in a distributed fashion, using whatever models are available for the different components.

In such a simulation, each hardware model has one or more SB ports. Each is unidirectional: it may act as an input or an output, but not both. In addition, each SB connection is single-producer, single-consumer (SPSC): an output port may not drive more than one input port, and an input port may not be driven by more than one output port.

Here's an example of what a switchboard connection topology might look like:

image

The method for adding a switchboard port depends on the language that a HW model is implemented in. For RTL-based models, SB ports are instantiated as Verilog models, whereas for C++ and Python-based models, these ports are instantiated as objects. We provide both a low-level interface for moving data directly between SB ports, as well as a higher-level interface for running UMI transactions over SB connections.

Under the hood, communication happens through shared-memory queues, where an SB output port is driving packets into the queue, and an SB input port is reading from that queue. This standardization is what allows any two kinds of models to talk to each other. A shared-memory SPSC queue is an appealing common interface because it is one of the fastest interprocess communication techniques, with latencies on the order of hundreds of nanoseconds; no system calls are required to transmit and receive data. At the same time, this type of queue is straightforward to implement for FPGA platforms, with queue read and write operations only requiring a handful of memory transactions.

Switchboard also has mixed-signal features that make it easy to incorporate SPICE subcircuits into a system emulation; see the xyce example.

Installation

The fastest way to install this package is from PyPI:

pip install switchboard-hw

However, if you want to run the examples below (or if you're a switchboard developer), clone this repository and install the Python package in-place:

$ git clone https://github.com/zeroasiccorp/switchboard.git
$ cd switchboard
$ git submodule update --init
$ pip install --upgrade pip
$ pip install -e .

Examples

Various examples demonstrating the features of switchboard are in the examples folder. If you'd like to run them yourself, please run this command first:

$ pip install -r examples/requirements.txt

This clones some additional repositories that are needed by the examples.

A good starting point is the python example, where a Python script sends packets to and receives packets from a Verilator RTL simulation. The configuration is simple: there is a small RTL simulation that accepts an SB packet, increments the data payload, and transmits the result on its SB output port. On the other side, a Python script sends an SB packet to the simulation, and checks that the packet it gets back has been incremented.

image

To run this example, you'll need verilator (sudo apt install verilator for Ubuntu, brew install verilator for macOS). You can then run the example by changing directory to examples/python and then typing make. That should produce output similar to the following:

*** TX packet ***
dest: 123456789
last: 1
data: [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29 30 31]

*** RX packet ***
dest: 123456789
last: 1
data: [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 25 26 27 28 29 30 31 32]

- ../verilog/testbench.sv:72: Verilog $finish
PASS!

To get a sense of how this works, open the Python script examples/python/test.py. The core logic is essentially:

from switchboard import PySbPacket, PySbTx, PySbRx
...
tx = PySbTx("to_rtl.q")
rx = PySbRx("from_rtl.q")
...
txp = PySbPacket(...)
tx.send(txp)
...
rxp = rx.recv()

In other words, we create an SB output port (tx) and an SB input port (rx). An SB packet is then created (txp) and sent via the output port. Finally, a new SB packet is received from the input port.

To get a sense of how switchboard is used in RTL, have a look at the Verilog part of this example in examples/python/testbench.sv. The core logic is the instantiation of queue_to_sb_sim (SB input port) and sb_to_queue_sim (SB output port), along with the initialization step to define the name of each SB connection. Notice that the Python output port is matched to the Verilog input port (to_rtl.q) and similarly the Python input port is matched to the Verilog output port (from_rtl.q).

// ...

queue_to_sb_sim rx_i (
    .clk(clk),
    .data(sb_rx_data),
    .dest(sb_rx_dest),
    .last(sb_rx_last),
    .ready(sb_rx_ready),
    .valid(sb_rx_valid)
);

sb_to_queue_sim tx_i (
    .clk(clk),
    .data(sb_tx_data),
    .dest(sb_tx_dest),
    .last(sb_tx_last),
    .ready(sb_tx_ready),
    .valid(sb_tx_valid)
);

// ...

initial begin
    rx_i.init("to_rtl.q");
    tx_i.init("from_rtl.q");
end

// ...

Using the same name for two ports is what establishes a connection between them. You can use any name that you like for a SB connection, as long as it is a valid file name. The reason is that SB connections are visible as files on your file system. After this example runs, it will leave behind files called to_rtl.q and from_rtl.q. It's convenient to name SB connections in a way that is amenable to pattern matching, so that you can do things like rm *.q to clean up old connections.

We encourage you to explore the other examples, which demonstrate simulation with Icarus Verilog and switchboard's C++ library (minimal), bridging SB connections via TCP (tcp), and switchboard's UMI abstraction (umiram).

Build automation

We also provide build automation powered by SiliconCompiler that makes it easy to build RTL simulations with switchboard infrastructure (queue_to_sb_sim, sb_to_queue_sim, etc.). This is mainly important because Verilog DPI and VPI are used under the hood, requiring certain flags to be passed to the RTL simulator during the build. Using our build automation lets you focus on specifying RTL sources, without having to deal with these details.

As an example, we return to examples/python. The basic logic for a Verilator build is:

from switchboard import SbDut

dut = SbDut('name-of-top-level-module', default_main=True)

dut.input('path/to/file/1')
dut.input('path/to/file/2')
...

dut.build()

dut.simulate()

In other words, create an SbDut object, input() files, build() it to compile the Verilator simulator, and use simulate() to start the simulator. SbDut is a subclass of siliconcompiler.Chip, which allows you to invoke a range of features to control the simulator build, such as specifying include paths and `define macros. More information about siliconcompiler.Chip can be found here.

Packet format

An SB packet is a simple data structure with three parts, defined in switchboard/cpp/switchboard.hpp.

  1. A 32-bit destination.
  2. A 32-bit flags bit vector. Currently only bit "0" is used, providing the last flag.
  3. A 416-bit data payload. This width was chosen to accommodate a UMI packet with a 256 bit payload, 64-bit source and destination addresses, and a 32-bit command. In the future, we may support parameterizable data widths for switchboard connections.

destination and flags control how the packet is routed. destination indicates the intended recipient of the packet as a flat, unsigned 32-bit integer. This provides a mechanism where a packet can be routed through multiple hops before reaching its final destination.

For example, consider using switchboard to build a simple topology in which packets can be sent from one HW block to one of two other blocks. One could indicate which block should receive the packet using the destination field, with a router transmitting the packet to the right one.

image

The last indicator (part of the flags bit vector) indicates whether there is more to come as part of a transaction. The rule is that a transmission cannot be interrupted as long as as last is zero. As an example, consider the system below, where Block A and Block B are both sending SB packets to the same port on Block C, using a router to multiplex between the two. Following the rule of unbroken transmissions, if the router starts sending a sequence of packets from Block A to Block C, it cannot switch to sending packets from Block B to Block C until it gets a packet from Block A that has last set to one. It is legal to have last=1 set in all packets, meaning that packets can be interspersed at any time.

image

The purpose of last is two-fold. For one, it simplifies the process of transmitting "burstable" protocols such as UMI through switchboard. It also provides opportunities for performance optimization. For example, if a long sequence of SB packets is being sent over TCP, the TCP bridge knows it can wait to fill up its transmission buffer as long as last=0. Without the last bit, the bridge would have to send each packet one at a time (or speculatively wait for more packets), since any given packet may be the last one.

UMI interface

In addition to supporting data movement directly through SB packets, we provide a higher-level interface for running UMI transactions over switchboard connections. The mechanisms for this can be seen in the examples/umi* examples. Here's a sketch of what UMI transactions look like, adapted from the definition of python_intf() in examples/umiram/test.py:

from switchboard import UmiTxRx

umi = UmiTxRx(from_client, to_client, fresh=True)

wrbuf = np.array([elem1, elem2, ...], dtype)
umi.write(wraddr, wrbuf)

rdbuf = umi.read(rdaddr, num, dtype)  # also a numpy array

We are no longer creating PySbTx and PySbRx objects, but rather a single UmiTxRx object with two SB ports: from_client, and to_client. Transactions are sent by the Python script through the from_client port, and responses are received back through the to_client port.

UMI write transactions are generated with the umi.write() method, which accepts an address and numpy array or scalar as arguments. This sends out one or more SUMI packets to implement the write request, packing the data, source address, destination address, and command into SB packets. Since an SB packet is 416 bits, and the two addresses + command take up 160 bits, each SB packet contains up to 256b data. Switchboard automatically splits up larger transactions into multiple SUMI packets as needed, incrementing the source and destination addresses automatically. Optional arguments to write() control where a ack'd or non-ack'd (posted) write is used and the maximum amount of data to send in a single SUMI packet. If an ack'd write is used, write() blocks until the response is received.

In a similar fashion, umi.read() reads a certain number of words from a given address. For example, umi.read(0x1234, 4, np.uint16) will send out a UMI read request with dstaddr=0x1234, LEN=3, SIZE=1 from the SB port from_client. When it gets the response to that query on to_client, it will return an array of 4 np.uint16 words to the Python script. A umi.atomic() method is also provided to generate UMI atomic transactions.

Sometimes it is convenient to work directly with SUMI packets, for example when testing a UMI FIFO or UMI router. For that situation, we provide send() and recv() methods for UmiTxRx, highlighted in examples/umi_fifo/test.py. In that exampe, we are sending SUMI packets into a UMI FIFO, and want to make sure that the sequence of packets read out of the FIFO is the same as the sequence of packets written in.

The main while loop is essentially:

txq = []

while ...:
    txp = random_umi_packet()
    if umi.send(txp, blocking=False):
        txq.append(txp)

    rxp = umi.recv(blocking=False)
    if rxp is not None:
        assert rxp == txq[0]
        txq.pop(0)

In other words, first try to write a random packet into the FIFO. If successful, add it to the back of a list of outstanding packets. Then, try to read a packet from the FIFO. If successful, make sure that the packet is equal to the oldest outstanding packet (since this is a first-in, first-out queue) and remove that outstanding packet from our records. Continue in a loop until a sufficient number of transactions have been checked.

This code example demonstrates several features:

  1. send() and recv() for working with SUMI packets, represented using PyUmiPacket objects.
  2. blocking=False for non-blocking transactions. send() returns True if successful and False otherwise; recv() returns a PyUmiPacket if successful, and None otherwise. A transaction might be unsuccessful if the underlying UMI FIFO is full or empty. For example, if we don't call umi.recv(), eventually the FIFO will fill, and subsequent send() invocations will fail (returning False). Similarly, if we keep calling umi.recv() without calling umi.send(), eventually the FIFO will be empty, and umi.recv() will fail (returning None).
  3. The ability to generate random SUMI packets with random_umi_packet(). Various optional arguments can constrain the opcodes, addresses, and data.
  4. PyUmiPacket objects can be compared using Python == and != operators. This checks if two packets have equal commands, addresses, and data.

Queue format

Under the hood, SB ports are implemented using shared memory queues. The data structure used is made simple enough that RTL running on FPGAs can directly read and write to these queues, without the need for bridge programs. In fact, if two FPGAs have access to the same memory space, they can communicate through a shared memory queue without any involvement from the host operating system, after the initial setup.

The layout of the queue is:

  • Bytes 0-3: head (int32)
  • Bytes 64-67: tail (int32)
  • Bytes 128-179: SB packet
  • Bytes 256-307: SB packet
  • Bytes 320-371: SB packet
  • ...
  • Bytes 4,032-4,095: SB packet

To write an SB packet to the queue, compute next_head = head + 1. If next_head equals 62 (the end of the queue), then set next_head to 0. If next_head equals tail, then the write fails - the queue is full. Otherwise, write the SB packet to address 128 + (64 * head), and then set head to next_head.

Reading an SB packet works in a similar fashion. If tail equals head, the read fails - the queue is empty. Otherwise, read the SB packet from address 128 + (64 * tail), and then increment tail. If tail equals 62 (the end of the queue), then set tail to 0.

The queue implementation in C is in switchboard/cpp/spsc_queue.h, with care taken to avoid memory ordering hazards, and various cache-oriented optimizations. The queue implementation in Verilog (intended for FPGA-based emulation) can be found in switchboard/verilog/fpga/sb_rx_fpga.sv and switchboard/verilog/fpga/sb_tx_fpga.sv.

License

Apache 2.0

Contributing

switchboard is an open-source project and welcomes contributions. To find out how to contribute to the project, see our Contributing Guidelines.

Issues / Bugs

We use GitHub Issues for tracking requests and bugs.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

switchboard_hw-0.0.40-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (312.2 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.40-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (302.6 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.40-cp312-cp312-macosx_11_0_arm64.whl (273.2 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

switchboard_hw-0.0.40-cp312-cp312-macosx_10_13_x86_64.whl (279.5 kB view details)

Uploaded CPython 3.12 macOS 10.13+ x86-64

switchboard_hw-0.0.40-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (313.3 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.40-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (304.7 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.40-cp311-cp311-macosx_11_0_arm64.whl (274.7 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

switchboard_hw-0.0.40-cp311-cp311-macosx_10_13_x86_64.whl (278.8 kB view details)

Uploaded CPython 3.11 macOS 10.13+ x86-64

switchboard_hw-0.0.40-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (312.6 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.40-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (303.3 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.40-cp310-cp310-macosx_11_0_arm64.whl (273.4 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

switchboard_hw-0.0.40-cp310-cp310-macosx_10_13_x86_64.whl (277.5 kB view details)

Uploaded CPython 3.10 macOS 10.13+ x86-64

switchboard_hw-0.0.40-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (312.5 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.40-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (303.6 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.40-cp39-cp39-macosx_11_0_arm64.whl (273.6 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

switchboard_hw-0.0.40-cp39-cp39-macosx_10_13_x86_64.whl (277.6 kB view details)

Uploaded CPython 3.9 macOS 10.13+ x86-64

switchboard_hw-0.0.40-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (312.2 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.40-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (303.3 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.40-cp38-cp38-macosx_11_0_arm64.whl (273.3 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

switchboard_hw-0.0.40-cp38-cp38-macosx_10_13_x86_64.whl (277.4 kB view details)

Uploaded CPython 3.8 macOS 10.13+ x86-64

switchboard_hw-0.0.40-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (314.4 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.40-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (307.6 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.40-cp37-cp37m-macosx_10_13_x86_64.whl (273.9 kB view details)

Uploaded CPython 3.7m macOS 10.13+ x86-64

File details

Details for the file switchboard_hw-0.0.40-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5346683d2bada1286c54414ac7eb1fbc05f0b5dfbd55aee58b032a1ca483bd65
MD5 01b7920fae8bd6e6a8f0f0d34877cb5a
BLAKE2b-256 cc26d4de6860261e259ae20759aac707254e8d83f2d015d8f40d989f5a2a61b2

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 1ee1579b98cc2647279a3ce2ec5001f460e948eae2d9899a3e68f3b82a464448
MD5 307c3f3a9148b287a4570601a647f43a
BLAKE2b-256 a27c6c01567cba2b7083e7e1f5cef2e7efc2fda8ab3679a7e7987893e7222b26

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a77a1dc5d048c98403a1accbf65927b3ecb3af630084b7b5873e5fb1d3b29a3d
MD5 d9e42c3f63a40959745fa9e0685845a0
BLAKE2b-256 a32a67032b02143d827a680500d3846d6fda2efeedbdffaeb405acf3ca21f1b8

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 981406efbc12c865a43c7f34a18000e9d045a3ff7fe9043ebceebfbea06a5c53
MD5 635f595b88393ce5c813a5f71136dd72
BLAKE2b-256 9b72c6506731f2865f255d438532c275c0092b5aac043ac8a4395f6c706ff663

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b62e754e93aa6344c05a9fe2f728bfc9be9a0908d958a150ceb56d708ca98159
MD5 c6109a8b38dcefe73bec5136a1052287
BLAKE2b-256 877dc4bab3430da23bf8bb28e63be733d7f7be40b5dfa635fc749a25725f9550

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 6fe9aff0ab045a39ec92eaf74498b361395ab545cf181342bc6aefd11d1926c6
MD5 60a2b4c6b40c699e4e968fdce17fb041
BLAKE2b-256 1b7bf87a1625f2169c5834fd7a043ca66bd8b6acbe3989a8a6dc78187d922297

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7699fada18f443f4f4650e7fb15c1287c7998030d6eabe7cfc725530d13884f7
MD5 d2f5f5d487babef889f7919df2856949
BLAKE2b-256 be3b4e417c6a348fdecc03063db15ce9a69fc35d9826a63e29bac6683fc49c35

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp311-cp311-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp311-cp311-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 f495dd6a4040ac31386410fda00ba21f7bd0b225310c24630f81c5fdf36dd4f5
MD5 b3e619548a8d75432f1dfc809c9b5592
BLAKE2b-256 353481d169b8c7aefc388dd392d5cf898ff574b919127c15e3eac3f7900f56c5

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5c494dc3546449bce237652ecab5de9fdf9d9ca483210f2bdd06182ba5cde107
MD5 9ce0bc29d6fa31d5b48edbb5e3214b05
BLAKE2b-256 c3969b98ccd71290b79dd2d4af9c84a8bd14007c8cbd08a96ba724f1cddf8a28

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 06f767077fb9a6a94cc3967e7ea955132136ce11b3b638c96277e8bbcdfdce77
MD5 29733e1a11151dba22aa0dc988cb50dd
BLAKE2b-256 1ed8d732062d71c683c5c2238edb810cb5d518c9879b5d5875e7454c51a75e52

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 85c4566a7ba5feb569a829f2f2a32dccbbf1977438596536a47bfedd99534c3d
MD5 e15412fe83b5e525fb5ec5b8808bb0a6
BLAKE2b-256 7d34ccfc297d2ce150d473914720400b86dd35f11462d8c6f592808cb3b0a770

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp310-cp310-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp310-cp310-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 a60cf2011df6685e50c3e2a622b7c51c019d582ee74573e18117dbb3041abd0a
MD5 efd700edb527fc8a029a438d605e69bc
BLAKE2b-256 e6a8a4624d2e74561b45b8123cd2e242a996c171277300e12e3e7da3a7febc56

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c5d2774041b3d3b8b2c89a4299aa22be9ec01a7ee876cf6f4974b726eee21443
MD5 d353815d4e36c3d482787aeeca03333a
BLAKE2b-256 f831e095b5dbbee811df7705584204e91ca444cf72389a924a0043868edc6541

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 04d4a8e521403bf285735c9ebc17260b946dee62e11dd443f98b932ba7253044
MD5 b2df1a019ded807f00e2d89bd9d72bae
BLAKE2b-256 d1c61009f771338cb41641860e2ed47e899895d6268589ad0f11f98309d5ff9d

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cef783a76ed57cab0fde05cb272b79b47199a7ae0871ecb1a20eff3fd7daf5c6
MD5 70a6d1aaeec297f9aee841220941f841
BLAKE2b-256 05bb08571158a0003fa7ffb86c93df28c8c85fa5ef741a474b1ceabb3c077f00

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp39-cp39-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp39-cp39-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 622e38feaa5977296cd4dd629c46bb211de18d9e4abd7ed343384f2517b0de32
MD5 90c7635648dd74b65aea2c69496554b2
BLAKE2b-256 969ba0c8beaa86630061611b30c032f0c2ae2fb79485418cd8213d1ad1401201

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8fe342d09732aafd5f2d4fa3fcc89834ddeab4caadf0476a7cc6c734a0c0ebd2
MD5 554381640b997eb19507e157bbe0ba86
BLAKE2b-256 0394827852f4943a4f206a12f2c1193b3ce44ce3b8310c9a1da1647a574b96c3

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 b13d9bfa9175002c8b76b2a83956f02329d8aa00242fc26b4d4be521d771a4fe
MD5 8369f39e08fd783a9d433d1c9a939dc8
BLAKE2b-256 03a3c1b766b110cd90ed8aa29becd8e1031f73bcb19102ef1686a0a970cb915a

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 79a39c841f8c6549744ed85411de798320e3f318bb63a1cbf2cd2edada2d86bf
MD5 3207187f3d0d470c0f4ab594797b025c
BLAKE2b-256 60579685406281546f8fa8e704695413431a677f48eae76fdaaa644f88f8e9f1

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp38-cp38-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp38-cp38-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 b6098c9d973c340fbf94dfbf7ec0ee1894891adf5015b115fe3e711596c4b7b9
MD5 34a3c2d85caff938ad216d3e59789090
BLAKE2b-256 708b2935c8c7dd327a85f21b7495630c088f318788f4092b33eb490cbb499bb4

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 402f366f8e6dee669893816446af3a4354642b0087254fa45d1317fd5bd754ff
MD5 1b57ccf5424c09d5c59a16827eb5226d
BLAKE2b-256 1bbb9f0e7a82a29cfe0764dca6a7c4a6615c76f7be2c9c17131369632c1c3fea

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d4db6aff9ad274672eb4601ccccc44ce51a330bce56c363a9064775e1eb7cbee
MD5 4199f56f7591caf07c7773e8007356de
BLAKE2b-256 801fa95e80440a2561e1eaabd12fd6a2ca609a684de089fbd5441945c6c1319c

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.0.40-cp37-cp37m-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.0.40-cp37-cp37m-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 b1b902b1038d376d6a23dd2038b53773f7c3b3f8a149b2d21a6d3813d106138a
MD5 ed2ad262bc4f6dc8774d26f88a6e0628
BLAKE2b-256 aba17928aedda7ddef37cf547e24bd275474ea8bd7501fc8ad4c3c4a80cff50e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page