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", fresh=True)
rx = PySbRx("from_rtl.q", fresh=True)

...

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).

`include "switchboard.vh"

...

`SB_WIRES(to_rtl, DW);
`QUEUE_TO_SB_SIM(to_rtl, DW, "to_rtl.q");

...

`SB_WIRES(from_rtl, DW);
`SB_TO_QUEUE_SIM(from_rtl, DW, "from_rtl.q");

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')

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.2.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (338.4 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.2.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (329.5 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.11-cp312-cp312-macosx_11_0_arm64.whl (295.5 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

switchboard_hw-0.2.11-cp312-cp312-macosx_10_13_x86_64.whl (300.9 kB view details)

Uploaded CPython 3.12 macOS 10.13+ x86-64

switchboard_hw-0.2.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (340.0 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.2.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (332.3 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.11-cp311-cp311-macosx_11_0_arm64.whl (295.3 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

switchboard_hw-0.2.11-cp311-cp311-macosx_10_13_x86_64.whl (299.3 kB view details)

Uploaded CPython 3.11 macOS 10.13+ x86-64

switchboard_hw-0.2.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (338.6 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.2.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (331.1 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.11-cp310-cp310-macosx_11_0_arm64.whl (293.7 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

switchboard_hw-0.2.11-cp310-cp310-macosx_10_13_x86_64.whl (298.2 kB view details)

Uploaded CPython 3.10 macOS 10.13+ x86-64

switchboard_hw-0.2.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (338.9 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.2.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (331.1 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.11-cp39-cp39-macosx_11_0_arm64.whl (293.9 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

switchboard_hw-0.2.11-cp39-cp39-macosx_10_13_x86_64.whl (298.3 kB view details)

Uploaded CPython 3.9 macOS 10.13+ x86-64

switchboard_hw-0.2.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (338.1 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.2.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (331.1 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.11-cp38-cp38-macosx_11_0_arm64.whl (293.7 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

switchboard_hw-0.2.11-cp38-cp38-macosx_10_13_x86_64.whl (298.1 kB view details)

Uploaded CPython 3.8 macOS 10.13+ x86-64

switchboard_hw-0.2.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (341.0 kB view details)

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

switchboard_hw-0.2.11-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (335.4 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.11-cp37-cp37m-macosx_10_13_x86_64.whl (294.8 kB view details)

Uploaded CPython 3.7m macOS 10.13+ x86-64

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 eb5df2f8ff0d0259c302358e8761657fc0c0ed56e1c3543a558a035fff6e48e1
MD5 0fd5cf0825c47d957e257b14d534aff7
BLAKE2b-256 dc9c9f3b4bc25cd34d6a8a0af17408da985a3e7cd7ba48f9545432d14b7b6c50

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a9cc787498935ff3cad880482e32d2dcda6d8fd30192ad58584499026ff6fbfd
MD5 d956ee7497f6a295b90a2252b8519089
BLAKE2b-256 4093cc4430d482d621285893d4bee8a709d3db3a267fee755d134b804e6bed5f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a396af74d5219b4b6b7eb42511335b228c7f0efb7830f43b94bfefdbdbd7f368
MD5 825f87a7cd519bc9f2d91138b1891c84
BLAKE2b-256 ee0ac96edd304cb0a83df814fa2be81e0e142f50f31a9731a31db52a2f89de23

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 524ea5b6d94586e2377169904400f2acf50e53eae2bba8b3fbc9513a4c3f60dd
MD5 e433e546fee3a92f0b30eaae7da200de
BLAKE2b-256 1762a3f18edd436039afc784facde6aa058292e3879754285cb3f819a8c6c238

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 be7c0bf6d2e0ea03f1e552a8cb88eb11da1cfde4f6fc4848f8ee907d8616e29d
MD5 c4fa10b5fc67158c1eaaa93ecaa8297e
BLAKE2b-256 f357395decf3d0a7b68a6d208b92abcdce2b49f68e1fd082da322b75dfa78885

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 5928ba8de1b67616b3156e7b7e1d87c05cf74b1e529f6ec6a9f2bccd72e136fe
MD5 92fd0630e914b9ee24002d2c2a21d611
BLAKE2b-256 130cbb6bbdbd62e44e6a8f0c22f578ac9d817f40149c7d76a0765d0262e5febc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 78f5adf4e159253727dcaf8fadd84488d044055db1520a621dbef9d2ffb7ed42
MD5 24b42719172855f630bf7fe8246d270a
BLAKE2b-256 2768e626f2ab89e3afed984db6a389e6bc6813e69118faefd028f7787765921b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp311-cp311-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 92ea83c777ba66ffa54a78bab756979ccaf16bc63d971bb4fa0481d9bb7b6fdb
MD5 02cf3db4d544714b2ee2030cc540ef78
BLAKE2b-256 f8864016d9e0b9ed3a0e5fdcca9334d478866f1993df782d32dd4cdfdbeed6da

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c75a0b9f893a3411129ab7b4e9a5552b0afc8061c52da8894ffe75113b460694
MD5 bf48d1d49cdae731e1ab57e62aeb4c84
BLAKE2b-256 e129923dfacd5680f2c5c1fe548ee778aef610d9c2507915d5d9f7390f26da76

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 7bbff22321fe8ee84b6234c4e16d0460daa8965752f7749df38dc0e9105c41d1
MD5 a8db9ac9199603a2cb58127fe2c5fa47
BLAKE2b-256 3902a09117d157ea31f36313a4a1c5ea12fdc0e5391f9cac593a30bd6490eac9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8e84183c3e6b64ad590a70a6a94563adaedfb08a90e9334ebc341e3ef011b28d
MD5 8cf291572fb49f342deafd6573333da0
BLAKE2b-256 d3feb584dec1ec9ae13d8f9764fae5cf34a2c4769f49605bc7d11b4749a5ea87

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp310-cp310-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 4571220e274d018a451114aa67afc9451b2c8c11fa046ec26658cd383547bc0c
MD5 d3cc5285a1ee6a1043beb8d3bf7614d9
BLAKE2b-256 31bf570dc96b3aebb401ef2d4ec059422dfc6fd7aea354753a8913c2f383b6d7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 39af67e38a6623230fc71dbca4c92a81e9535979d995b491684340d9b6a6d0fd
MD5 55b2a8252f8ca424de25dddf78d654ea
BLAKE2b-256 1f49c84967dcc896bfffd5794ee816879086da0ba82cd61e7ce9ba3113f04ca9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 9dd915f6b4863561bf90dd07bf90fbc4409efa2266bf7b49b9c209dce9835bec
MD5 61cf7650b1213e8f6475cad0fb4daf7c
BLAKE2b-256 a32cdd74c22d9ee83c189168b3ff64724f9bc90ddc60ddf14db69457391a0d8d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 db669b6d15ebfe73745d691cfa43babafc55b0333c3322ceff4850bc94768b75
MD5 9e83c52cb51a5e8f9f1183c88d58f5e7
BLAKE2b-256 d8fc05a54c6b3a3f98168c143e16d67ef96d439465d14d8202eafe64ee247765

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp39-cp39-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 03c6eb049b04ec6cf5c9dd2343cf024993963413841c37d0740df8338160dc10
MD5 5949b43b96bb34eda94c948f618ff394
BLAKE2b-256 beb46d5c0b63826a4580535c82601f47cc40be77cfd65256fe9f31cc2236ecc4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 cffed55907857ca4bfbc3820d16e86fa8649f44a6e34c1a5cea0c38889c44bf3
MD5 ec439ebce00aa9366e6240acd93d4c18
BLAKE2b-256 8f47505a44c19d190aa6f9db920a37f7d9b27c386520410483db9db1936a78be

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 8e5336e01cecef4185394319290abd126d5b0d8665b9ac5aefac4a8598675266
MD5 8d3a3ff325961030d7d5854c82e437ab
BLAKE2b-256 5cc1dfa518cf49806ef15b847369f306db9d48af08582c63054043282bfba335

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 77d012332d91828ad426303e667e713af916d7b6d4a2aa61f4d4445e0d6201c2
MD5 ca0e7c7a19b944209e8864f073ba64ae
BLAKE2b-256 266dd5dc1179d75d39fde50b2efdcb0a7ff23a40d3db0a6ef274ed95c1c73b6c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp38-cp38-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 3241e01da30e8fcad4351650f9f5e598e0500c6d49658e9e90e288aabe790915
MD5 0047a483c4cd3701f5f760c27f43f9c7
BLAKE2b-256 acab868fc0ec893d817c31e07a3cb36a1ad68d79052643ceb7309de86480f1e5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 03c873ceb9e7fb56e1d5a921f02178fcf004d0bd9ce50f8f49e641cfc1bf94eb
MD5 4b0cb9b31c213458a6f397768001f12b
BLAKE2b-256 f2f4fac5819cd62bb1773110fcdf992918fd8da4611def3ba9b4c010126a6c85

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ee716bba995c74e0492169d52de473a61110d68d8c33381cfb5737d995857642
MD5 c4ddc07b12906acc48d255f2173af4a1
BLAKE2b-256 9751c6287399b21c7b4acabcad513b9018bf5de1a510b5b634f4137dea38b6b7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.11-cp37-cp37m-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 39a7375005648dc72400321bc8e2800bc5f2dd49f57d2e89d96d513fcd68fb19
MD5 38f7541c95685c78e2612a8d0a64d757
BLAKE2b-256 37d52a2b2300ca03c32f88a008c09c591cecdf17ade111f3d7ff65a9e870a4ba

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