Skip to main content

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

Project description

Switchboard

Actions Status Documentation Status PyPI version License

Introduction

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.

For an in depth explanation of the theory and philosophy behind Switchboard, we recommend reading the paper Switchboard: an Open-Source Framework for Modular Simulation of Large Hardware Systems".

If used for research, please cite Switchboard by the following publication:

@misc{herbst2024switchboardopensourceframeworkmodular,
      title={Switchboard: An Open-Source Framework for Modular Simulation of Large Hardware Systems},
      author={Steven Herbst and Noah Moroze and Edgar Iglesias and Andreas Olofsson},
      year={2024},
      eprint={2407.20537},
      archivePrefix={arXiv},
      primaryClass={cs.DC},
      url={https://arxiv.org/abs/2407.20537},
}

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

If you're not sure about the file name format, learn more about wheel file names.

switchboard_hw-0.3.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (342.2 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

switchboard_hw-0.3.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (379.2 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ x86-64

switchboard_hw-0.3.2-cp314-cp314t-macosx_11_0_arm64.whl (341.9 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

switchboard_hw-0.3.2-cp314-cp314t-macosx_10_15_x86_64.whl (347.1 kB view details)

Uploaded CPython 3.14tmacOS 10.15+ x86-64

switchboard_hw-0.3.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (339.4 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

switchboard_hw-0.3.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (375.5 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

switchboard_hw-0.3.2-cp314-cp314-macosx_11_0_arm64.whl (329.4 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

switchboard_hw-0.3.2-cp314-cp314-macosx_10_15_x86_64.whl (336.0 kB view details)

Uploaded CPython 3.14macOS 10.15+ x86-64

switchboard_hw-0.3.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (338.2 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

switchboard_hw-0.3.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (375.4 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

switchboard_hw-0.3.2-cp313-cp313-macosx_11_0_arm64.whl (329.0 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

switchboard_hw-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl (336.2 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

switchboard_hw-0.3.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (338.4 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

switchboard_hw-0.3.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (375.3 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

switchboard_hw-0.3.2-cp312-cp312-macosx_11_0_arm64.whl (328.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

switchboard_hw-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl (336.2 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

switchboard_hw-0.3.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (336.6 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

switchboard_hw-0.3.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (375.8 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

switchboard_hw-0.3.2-cp311-cp311-macosx_11_0_arm64.whl (327.3 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

switchboard_hw-0.3.2-cp311-cp311-macosx_10_13_x86_64.whl (332.9 kB view details)

Uploaded CPython 3.11macOS 10.13+ x86-64

switchboard_hw-0.3.2-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (334.8 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

switchboard_hw-0.3.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (374.8 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

switchboard_hw-0.3.2-cp310-cp310-macosx_11_0_arm64.whl (325.9 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

switchboard_hw-0.3.2-cp310-cp310-macosx_10_13_x86_64.whl (331.6 kB view details)

Uploaded CPython 3.10macOS 10.13+ x86-64

File details

Details for the file switchboard_hw-0.3.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9c3587ddd87669bdd20272565b9e31a845ad780ac2af31c39781e91b9147fd9d
MD5 869b391dd853d4149684edcd1e475eb1
BLAKE2b-256 4821512aefaafd71a334a0df780f6a06706f476d6e48e9e13e7794dda4cd5ff7

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 d975537c2159f5a9684d3c0349fb155f5de61e82aed48ff3e9bc4a0b0dcafef5
MD5 be9e4ebf77cd5fe8a3b2f133c5cdfc4a
BLAKE2b-256 b86ec2d7f3ab5b701b044f62710a26b9944c3542b68377cc2af68aeabacee7eb

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8b900d327dbcae03e77a29dfcd57ff52fb5dcbb84c0a4d842030c08fdca816a3
MD5 155c4728296a8625d59a911e6ff4d1c8
BLAKE2b-256 739652d7d9abb6f5a59fd83ccfc9be8b7d739a8f809951d929bb059172cad9bf

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp314-cp314t-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp314-cp314t-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 7d8fec61343e4939b598d9004afb6a72f9af3be0a8dbf5eb1eee6134b2560a0e
MD5 3fd43b9c88bc7d8adcb72c74add864f4
BLAKE2b-256 7394a267e22c70cc5c6f7f6d5550dcd1fe718242208d010cb62c518db705217d

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 2f62b5d3f0556ff8e52fff08f3e3292175f1230a1bfb9b238d888016167eb985
MD5 4ed0454b16adfa150508e2b5b4ada63e
BLAKE2b-256 69a7af13b49aa808eefefe2fc3ed8f5c99208c69288bc8ca3dbf9fa4a76e05da

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 1ffab19845d68bbef9e72b1a465d406e5fca3f033419b693864b5d8426f60289
MD5 3222ba11cd2f3f3010f97b6107b5257c
BLAKE2b-256 df69e75ce9835b71e097c852a8574fbe3fb38315b69723fe2215f4da9cde8c4d

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c3d74f0b0263271ba359cbceef800ae81bf142ad05521c122bd4d118cbec9b03
MD5 92ea6310667c1e0036e03367976a04a2
BLAKE2b-256 43f0883afd3a7b744ff3e74d05ebde9935b34895552795366ff4dd05775f564f

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp314-cp314-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp314-cp314-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 8fd275f90a0cdb391ea22f320f2b91da3e04059bd61606a58c0857e14d8c3096
MD5 1385d4616bab2ce9fb5a22e2244a5f20
BLAKE2b-256 75bf9933f6df7420a7e2c0f3564fa92b184f7dbbfe0c0de5ebcfab9ef7da1e55

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 5f5bd5ff7a5401e5dada7f0f2425ce5e14e0c52d178687c764b492f8cf126dd0
MD5 d33b11356ba5ac264198a803b87c5c4f
BLAKE2b-256 29c4b74b4f42f9b4701b8a0452fe1ebf32ac600d7fdd5fdbdca09844a8ed5b72

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 164daaa917aaec47198643a6a1ce6fba6e4c6f866ce2a2ade5b6cafec5d5e6bd
MD5 91b0d3c498a3b4c77a705803d72cc6db
BLAKE2b-256 162b3d757f43d88958103dc150acf838affabe449a4d7aaadd82e8b58be49556

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d2bdfd53cf00b2bd31a750364b752738a31a610b9a6ceaec8ded1d6c2ce096a4
MD5 6656d210fa1b9b1e564ed1b6d1e47966
BLAKE2b-256 5e3c08fae2485e96082b5a2e74a46e711514aa277ccbdc31c12a5e66cf7c229e

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 59e43ac6e7c3811cae8f426b2c547c126e82f92bf5adeb1ee74007bc0757c492
MD5 7e710c903825562d14e5088129bdcf64
BLAKE2b-256 cc1a5f4ca105d8490e09ee2a504ef861ab4e28c3919b81daccbb26639eadf85f

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 bf0f558dc31c67b297d9bce4a848e8ea168abd6d0a0f9e56e10ceb80e0975e17
MD5 8b8c5badf57aaae1f54985cda1a87cee
BLAKE2b-256 cbb3fe1b71f84509bbb6e211c3e6ee0691c44ced0312364766f336ef9501c27e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 638c27df544dae2bda488e403bc754993dfe4373206e185312079951182e7051
MD5 ab73949088b67736f34addac65fe6cf6
BLAKE2b-256 bdfdaf91c83aec73da8692cdb1c3cf5f651d532468ed81cfc555d2a2c70d6371

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 54c71fd1d7d88c59fa1c01789103965cf280c19b79cd7ac22906e5211b626218
MD5 31f57b939511a2becd2bca4b5c9e543b
BLAKE2b-256 46b7eaa82fa797a687edb6aeea482e9a99b06b77bea86a57e7abe3b688b33f8a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 b432078d481871d4b9b216b3678064fdf467c9d0fcc3224c058cc7e370072841
MD5 436de16aae77ea38b1b5b6bf108658f5
BLAKE2b-256 f90e8c97f8196d515a8893cc85617b7eeb42bb4426be07be773dc4550a1029c1

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 74054baa9ab0b023c6e12818d6832b0257e846c7c9d63d33b6a2d7c0696b4d09
MD5 fb483f123292cea59f7c638d1e2976d2
BLAKE2b-256 84654d3ed1c28f660f63770bdc4b86a98ba889169166540ced7d60ac33a09c77

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 7717d29e273391b1fe0ba92101e98bf4e6632d13119bb620d74e832f0d8ebbc9
MD5 a95509c02549d0a846cb587e694b27af
BLAKE2b-256 cdc68c45a57d4ba6ff6a56acd6eca70c63455b02aa90677c181f25ddd2d3c03c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2bdd2af59cd24ac2565ab2c08ddec1556a95d6027ab60d5af49462e85bad37ef
MD5 0a5578a7841d910ec89614ad3faad12a
BLAKE2b-256 af8f7b7323e305e1ec47eb6ad458a3c530bfaccd04e0378db36d2f8d70651e42

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp311-cp311-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 cdc8e81273d6b9cc6d7333856bd35f45b7e32ec9c2dc29239e7167c4d2e631c9
MD5 7b5d90e88f663978f0b53afc6c8b0c8d
BLAKE2b-256 27967a0adec98e1c0a30a4b1e6228225c082044965bab26ffc6a1d62a181f95c

See more details on using hashes here.

File details

Details for the file switchboard_hw-0.3.2-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 31a3eab22628601a6b9553cca6626a34fe2afba6f69cced78a71babee6821922
MD5 8b3a12e2c78fa0bf2ab67154a1adc89c
BLAKE2b-256 af00a6b3aace5b6cc44259a103339b8992ae003f3d1a299253b8dec3de788bc4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 8e8d68b0440fa8b046a95f9759c817f5029c9ad54c06dd6bb7c8466f9c6f26b1
MD5 fcca61bd2b052f108f7e78f4a06178e7
BLAKE2b-256 89d598dc78c0e78510be822602f4828b4426b56cf688218a8d264fd038b666ae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 059a98fd10747b9f36ff82eaec1515e8ee36c2bbe8edac5958e094b13a0145e5
MD5 fc3a670e412f40e331d1337739eeef1c
BLAKE2b-256 2813cca80d029530e9c93751feb40f7b05bdd457403cbf8c7318c6b5af120da5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.3.2-cp310-cp310-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 678d02bae7aa9a0178fb98a7fd84991828168766381e38c7590c832508871ad2
MD5 8325e9c34650e7e95a3650da4bc2d524
BLAKE2b-256 01e15024912e686eb051aa4f47214d4b3a9eefad116e00ca9103f42f9baf1361

See more details on using hashes here.

Supported by

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