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

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (304.1 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.1.0-cp312-cp312-macosx_11_0_arm64.whl (274.7 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

switchboard_hw-0.1.0-cp312-cp312-macosx_10_13_x86_64.whl (280.9 kB view details)

Uploaded CPython 3.12 macOS 10.13+ x86-64

switchboard_hw-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (314.8 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (306.2 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.1.0-cp311-cp311-macosx_11_0_arm64.whl (276.1 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

switchboard_hw-0.1.0-cp311-cp311-macosx_10_13_x86_64.whl (280.3 kB view details)

Uploaded CPython 3.11 macOS 10.13+ x86-64

switchboard_hw-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (314.0 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (304.7 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.1.0-cp310-cp310-macosx_11_0_arm64.whl (274.8 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

switchboard_hw-0.1.0-cp310-cp310-macosx_10_13_x86_64.whl (278.9 kB view details)

Uploaded CPython 3.10 macOS 10.13+ x86-64

switchboard_hw-0.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (313.9 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (305.1 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.1.0-cp39-cp39-macosx_11_0_arm64.whl (275.0 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

switchboard_hw-0.1.0-cp39-cp39-macosx_10_13_x86_64.whl (279.1 kB view details)

Uploaded CPython 3.9 macOS 10.13+ x86-64

switchboard_hw-0.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (313.6 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (304.8 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.1.0-cp38-cp38-macosx_11_0_arm64.whl (274.8 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

switchboard_hw-0.1.0-cp38-cp38-macosx_10_13_x86_64.whl (278.8 kB view details)

Uploaded CPython 3.8 macOS 10.13+ x86-64

switchboard_hw-0.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (315.9 kB view details)

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

switchboard_hw-0.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (309.0 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64

switchboard_hw-0.1.0-cp37-cp37m-macosx_10_13_x86_64.whl (275.3 kB view details)

Uploaded CPython 3.7m macOS 10.13+ x86-64

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1f238c8a0c6488e26355ae1c22e3519cf0a9522fe4be7d57f1dede26a2911596
MD5 ad3745038bacf1750cd2a736aa2c9b7a
BLAKE2b-256 6a39cc04424e17bbead2538d7976556727134c626eaccf6d4ba0d5e485d20190

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a29db814f3874558d13d0019dc4b265cbbde6c4e7b3023f6ff015451f9cad878
MD5 e31ef9baa9298b1b0511a59e1d9500aa
BLAKE2b-256 822c68657df112b77c5e46fd0212fec698823bd49770071b5d65b559a1c73581

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4ed83d5e78565dc11598a8301f0916440e83dc92efec483ec88555f645e5fd9d
MD5 1abe07f5a9e558442ceb6ece58b6612b
BLAKE2b-256 82a402b1122230b676e8a2f1c8dc8bed4e2a6303e5327b1129f9410a1e382720

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 3bbf42031b76bdcf08f7ce0043b15c8a5909729b4a13a16ff4da2128a6d70bc8
MD5 03c886aa78d90ddbf9735ba633ec8873
BLAKE2b-256 8fffcd3029b22629aebf2b6a2f77ab3fe9b45a999ae1f0570c2e5bd8d63b7958

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3a34359cb9bd8b2a35ce2e01ba2f8d228e5e403a0277de5eb0dc0d306218c4a9
MD5 83128d9575b8e2c2eefc5d823757ff97
BLAKE2b-256 96680f248cbd520d6a3eb3d35d6c29589c39ce3da97019732fd79fe6bdc225a5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 80e0c81dfd179185343a291ebf0ce9c281326c285adae03ecea6148a9cd0b956
MD5 4d1f66192bef5bd533aaf1eea34df380
BLAKE2b-256 40f7c07790de3fd9c8146f9d0b4c70c9e7f5af772680388c6ee472124f51e7fd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3d7d1b5d82850b40fe44f87a685908d3ba465bc3f2ab3150ef47b0628d573921
MD5 a1b32f6d79ff95712f270bb3be8f8ef1
BLAKE2b-256 58f1b90712a3ea00a6fa5c0ccbd3f91ebc24ca79701a87add800df67951d8416

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp311-cp311-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 fef781ce87adc65d30cb69b9abd3e528cfe04ebc640f110113da9ba95d6f0894
MD5 dbed203a91481b9154f35059585230e1
BLAKE2b-256 4ad857aa96d5e9ac67528185390e8b7452f2ca8a1f50cb68091a5cc18297f33f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d6ef341a7a7ae9b9f1a890bd16893401deadd48d69ed5e1c3751959dd89aacae
MD5 615d27093e506f868f4f6e754ef08b6a
BLAKE2b-256 baa5b00d3f365a43e4cb452152fd892af0a5e35ca27e4d86f25674b7d7925834

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 aa52699390d23fa719628f8c2b6e423d9f8f43d968d1c91e656153f56588f77f
MD5 6b16db6f231442fa2bd7750f2881a615
BLAKE2b-256 43afa6b920696ddf281ac37d41ef6f1a53d9c7ca38f94fb01ba930869cd7b02d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c71189b52b8b34eef43233553e05af6cce163748ab49abf7a0c3d431e66d4ca9
MD5 9d121c55741cfa1b0dd39f81331a82de
BLAKE2b-256 b2bc4ed399e57dc2873e54e4fda73312b4b0d46584084f58c8d44ffa0a38e7bb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp310-cp310-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 1368b44260e9b733f4b8678d1ab6215cce34fb9e4b4e0a5e2bfe32b64056c497
MD5 e0e6306226e2cac6b86012b99ed8c4ce
BLAKE2b-256 50061aaa583d6cb1cadc4dd5df692875ac728383402e8b9ddc2c8cf24b8a5728

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7659c00dc4ab93de971d80c155c44f18ea109654053c35e6aa23958473f028ab
MD5 0736ee9f38acafad780267af102156a3
BLAKE2b-256 019dacffb57d6b60e09541bc5786ab3d95bec935aed6194bac6ed27dcc0bfdb7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 084763f79c7a31b42d3bf4d59d696345306b9163b14e5abffe861028d3330226
MD5 05bf99e79320fbcd8a6671ef5a3a176c
BLAKE2b-256 2da7030ae3db92cad553d0af30277f5f50dbdfa638cf497c7da555c001255d3e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 38d35b4882fca526a2a183d1159207b4237fade18b42a917e4221a095ce8d953
MD5 6cb6e18cdf51d3b5adad8ea2de51d5aa
BLAKE2b-256 b051cfc827f9acb5700a6d97f041a5518cfe1d8cb9533be527e52c68cfdf700a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp39-cp39-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 1bac5e6f947b9fa4b3de9125cf5a0223354a80ec7590aa7e4f91d65bf78fe2db
MD5 37ca32ace4b7ed283c6c13a1dfceb692
BLAKE2b-256 4f394228ca8a471d74941fc8c849555a2e260f7c13fd78dcedf952e646e3d942

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6a74890127df34717fa3610d89700cb8b270e9df5d48354291704bbb31ac88c6
MD5 f3b35e17b26f8b1bf1144cd508b531d9
BLAKE2b-256 c258312322d8c0dac80dbe56672a68ad32ea6ef0d1457365efc2ec86aca90101

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 8f0139b44859348caa465a05df25e143ec91d53fea971d53ca21f7f35cf14e3c
MD5 0acfe90ba166095722df77a34e926793
BLAKE2b-256 1145bb9ca7ce2a86a1cc759f555ab57702835c7c73745d5793f9d44544dedb27

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cdf34ee2596c026f502b7a15758cd3ad14fa0bc67213cc72dd848cec319dbda6
MD5 0d6d419c64b91c2f4203b8fd4b2bbfde
BLAKE2b-256 b45b2102b6aa6431ddc44bdef0676c606211c68df681d11335d45b9713f21682

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp38-cp38-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 33e40baf863acaadfaef4cd5248e41f0833ce1ebd6726a8fc513ea3d4480ec10
MD5 dc4c51c7664da24f395729c0873c7383
BLAKE2b-256 977e73b2e76c460eb34ed1bc0ce9d6afce82a701ad1bc25a16fe742dc44721b6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e833c615efa694fd3c14e707906ddf39c73cc16c1ea67b974eb2867b6b49db5a
MD5 97552dbfde98955b65b6c6f96eee8ff2
BLAKE2b-256 67ee9a86224c9a454d26d7ab5e09f0c248d26843640f6b7640a3fa35fd5d4128

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 295368dfa4c4660c1fedbf20a7ea81a13756242ee2e696ce25989b59e3a75798
MD5 908d018588c50b7a1295b5e8abfb8bd7
BLAKE2b-256 c2b4edabdab072d7ef37b859d5627ecafc8ec9d1be61dd93551f7bf6c345a2fa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.1.0-cp37-cp37m-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 fa0753691d7dd76655b252a304ce389b4a17f74846f4507648fa4a7475785bc0
MD5 6c9e2bfec127a9a717fc7533ef4735b9
BLAKE2b-256 95b836761479c3ee5ab2e0f68cb7bc17764c54e7180034d202857e04b9790d0c

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