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

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (319.2 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.1-cp312-cp312-macosx_11_0_arm64.whl (286.0 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

switchboard_hw-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl (291.9 kB view details)

Uploaded CPython 3.12 macOS 10.13+ x86-64

switchboard_hw-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (329.8 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (321.7 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.1-cp311-cp311-macosx_11_0_arm64.whl (285.8 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

switchboard_hw-0.2.1-cp311-cp311-macosx_10_13_x86_64.whl (290.0 kB view details)

Uploaded CPython 3.11 macOS 10.13+ x86-64

switchboard_hw-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (328.5 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (320.4 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.1-cp310-cp310-macosx_11_0_arm64.whl (284.1 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

switchboard_hw-0.2.1-cp310-cp310-macosx_10_13_x86_64.whl (288.8 kB view details)

Uploaded CPython 3.10 macOS 10.13+ x86-64

switchboard_hw-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (328.5 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (320.4 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.1-cp39-cp39-macosx_11_0_arm64.whl (284.2 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

switchboard_hw-0.2.1-cp39-cp39-macosx_10_13_x86_64.whl (288.8 kB view details)

Uploaded CPython 3.9 macOS 10.13+ x86-64

switchboard_hw-0.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (328.4 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (320.4 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.1-cp38-cp38-macosx_11_0_arm64.whl (283.9 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

switchboard_hw-0.2.1-cp38-cp38-macosx_10_13_x86_64.whl (288.6 kB view details)

Uploaded CPython 3.8 macOS 10.13+ x86-64

switchboard_hw-0.2.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (331.4 kB view details)

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

switchboard_hw-0.2.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (325.2 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64

switchboard_hw-0.2.1-cp37-cp37m-macosx_10_13_x86_64.whl (285.6 kB view details)

Uploaded CPython 3.7m macOS 10.13+ x86-64

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 cce7cf23c4487ee364b8d92aa239e6e918a94a529c9ab5271424775cccea0279
MD5 b1a9bbbd49cbddf77d8cdff10d0534e2
BLAKE2b-256 ecbbe24ec149b0a243a580aaeb379dd6de6f423684818c3592dc5238c28199de

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 b879dce52471b3735e838a47b8970fdfa5f0adac28ba5a5ed8206e4f6dea0cb4
MD5 3cfdd18254b4f47692b7dc82b5b75ec9
BLAKE2b-256 b8a479fafff8520779ba8a88df77df1ce888557d0c0d1e98feacf2873001b741

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d06a0cbecd6d0717b4773086b3f5f55b00a6ccb442fb93bbf331d1850c4a6246
MD5 f1b2868ad7a69edf106b05f048bdb907
BLAKE2b-256 71fafde7a8a81c7b1b4c72604d0feec197cf5985f1c07bb99aff4ac7d65927df

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 5f2c61a364cf65de3e17bc6820fe2447fd8d81cd62ca4f44cd86db63051cd900
MD5 10443f7fbd036d48f38cf0227b1a224d
BLAKE2b-256 a3d729c9f93ce9b031d5bdfd609b3602428b23ff5b78d0dcc7a06567cb070622

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e47337ddcc2aebb9983644b84df3226704602fa2e96b1de18bb25c4d3c58bc06
MD5 dcc05f98abade142e8d70c1d4371cbaa
BLAKE2b-256 466c542ccedb957c7de478e29afc5c54ac7e9776e85ff949ed6bba01e55e6323

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 5ed36e298001ca47951dd4541a78ea500a1b22b4c20e724961424d9e33e43f18
MD5 8a9d9f0d02d11f7e0a7565a3c7e27d72
BLAKE2b-256 96cf47049134218046b141862ca1018b5af73c525695157da08682b9a48f325e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5e67ffb59f863f586df49ee6a43cf1db6fcad1fab4c8c1cf4af0c7152a20af4c
MD5 6bbfd3b80eb69bae46cfc800bab0dda5
BLAKE2b-256 4e4e7f741cac8cad5c54eec2a54f1de952eef15f32b492f6a64530274b8f2be6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp311-cp311-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 02e0a7c4809734f7f19e63f671cacae3be127df538a4506743fe79348584bb7b
MD5 8c0ff06ac8b8445b7ee9c3d722ed5760
BLAKE2b-256 c1357155c38403c680fc1acffac8119d79afb5498d4d2745808145d744419d72

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 faba61b2934702e34a9eb93b8be47abdb2c0320849713e2174d9067814d12fd4
MD5 58cf866bc5eea64a6a798f5140efe5ae
BLAKE2b-256 03cc07cee61a2e2cfb0ddced008bf3d570219378d84e85cc03417879a1fa1151

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 355ae06e27e879158fc5b96cad4dcff23c811c31218b44cc0d0b680e75ef208f
MD5 b937e5dd2c1ba96bef1cee838f6d39d0
BLAKE2b-256 fa011e0a1792808013e0cdf0a78bc898161615e978930198962a836beba5ded5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 70e4fbf446be08ce0c3009ee6cd376873dea545f795621f1cb746e99fadd193d
MD5 a4ac0148e3c1a4d12a80cfdcfd0db20c
BLAKE2b-256 5986bb8baba2052fdfea5268fa9b671098af4ba6580949315e8dcffa2529f3b2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp310-cp310-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 78ae36f5eb0601607015061241a578571a14f3f6e7c0c719b5aa8e9e8d208a73
MD5 6b383a30733ab09a9a2e5c1d3fb8fd41
BLAKE2b-256 7610b5f6cca6f1c92e6b363cf7a1c6b0f9df71b48a8b451c7e56507f5b1f4455

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 bdfe3afc285a597c784981c5c03ca5c769f57489ac5aed3b023bcec0df996184
MD5 0107861b1f8bc8f964a4075584b21408
BLAKE2b-256 4fe865aa1b083628d5d95187c581690a1781ccd29368f3cc4d1b456642040889

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 88b4eb927dfc490ef25decef3ba585b46aaccfab7ab1a760ada063b90f61b06f
MD5 4d00187e92e8d8077bdac051213a8d4d
BLAKE2b-256 3af1793d7de69cf281a574024a7c8ab6a6f999f99ee3a22ba60d9d714b907db3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 927854edcb74739f343ad4f895cc8f7301c7d57c9101d553318de493ee5174a5
MD5 7d24474c6049dc9493e12b14ad6e295b
BLAKE2b-256 9f33bcee3f0912949465e16d3a7dcc527b2c667e78bec149ed91412eb046df59

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp39-cp39-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 de3fc1bb052d55e56aedb61eae9364f7620a14224019a37f9acd4130de46aed6
MD5 03ef713269eaf031a4eba3d77040e532
BLAKE2b-256 3f924865ea634be6e43a22bcc85b94c97a6c76ad9cd02dcd972f9d96eed54aca

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 86c93142229908b540ca12a52f53103a61b5d1250d7dde428f48fdddc433f2d6
MD5 4e98af65d5fdd8b7a4a0a25b5f31a488
BLAKE2b-256 085aec00ed90b92170521c6588c050d1ebf50ca07fdef529210439787359c9b0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 c495992262a4d2639902b83f1096fa2305b8178b116c5f24bd7bf97c40df59b5
MD5 d0f532b642fcc801ae3f6b4929b479d5
BLAKE2b-256 be7526ef53e99e5c04b4ad8fa4b42f0a2f2a43b1d5020cd8f2a04e6e7c809487

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 13141ca3e4e56beae0405102bf5a5967abf8dbf1e02d81e962d121427bef1891
MD5 8c389fde496247e42793320a50fc3ada
BLAKE2b-256 1aa44dcac7f7da5c925d163dbbf8135aaa9ac3fe2c92c66a05631a36b124a34f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp38-cp38-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 73d74b1ebf84109044483054f7c8cb73daf7860ba5c938d1374baa55eb3759bd
MD5 78f61d757d971a0e5c54a3562ab0b391
BLAKE2b-256 14600f3d336e3d2595216b9c487908c3bee231ee3a75e007b654ebbde58eade4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 205c5538011acbe775d892f623f5cff54b643b3fad7eb4bc0bb7fb3ac39ba06d
MD5 18229c7f0f250465b435dcfea9361525
BLAKE2b-256 c0f1c7bedd1e92f4d11672cd244d5cb4296268c62179d66f6211222c0ad4a63d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 440f1b92abf152d23e87cb16c7208e48b21e5f4956de3f515f81676ddf71ea62
MD5 7f7fff67272c89d169381e6853292afe
BLAKE2b-256 37a077b84834b0b937de93b06da7d93d32599766e4e3781e314d6c0d07a5bfe9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.2.1-cp37-cp37m-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 e77b81daedffd4583a6c37c947b2d925c0633ac2980e0987ebd38be4a593657c
MD5 3fb20f5171943ab1325b3c58c594337c
BLAKE2b-256 03b5464fef79c08e93d129bffe08a4f38bb6941d9a83649c3409a0a5a2a2096a

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