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.

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:

./examples/get_deps.py

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

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

image

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

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

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

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

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

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

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

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

// ...

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

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

// ...

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

// ...

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

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

Build automation

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

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

from switchboard import SbDut

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

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

dut.build()

dut.simulate()

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

Packet format

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

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

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

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

image

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

image

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

UMI interface

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

from switchboard import UmiTxRx

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

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

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

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

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

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

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

The main while loop is essentially:

txq = []

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

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

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

This code example demonstrates several features:

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

Queue format

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

The layout of the queue is:

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

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

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

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

License

Apache 2.0

Contributing

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

Issues / Bugs

We use GitHub Issues for tracking requests and bugs.

Project details


Download files

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

Source Distributions

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

Built Distributions

switchboard_hw-0.0.33-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (280.9 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.33-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (272.3 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.33-cp311-cp311-macosx_11_0_arm64.whl (249.6 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

switchboard_hw-0.0.33-cp311-cp311-macosx_10_13_x86_64.whl (254.2 kB view details)

Uploaded CPython 3.11 macOS 10.13+ x86-64

switchboard_hw-0.0.33-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (279.4 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.33-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (271.2 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.33-cp310-cp310-macosx_11_0_arm64.whl (247.8 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

switchboard_hw-0.0.33-cp310-cp310-macosx_10_13_x86_64.whl (252.8 kB view details)

Uploaded CPython 3.10 macOS 10.13+ x86-64

switchboard_hw-0.0.33-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (279.6 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.33-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (271.2 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.33-cp39-cp39-macosx_11_0_arm64.whl (248.0 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

switchboard_hw-0.0.33-cp39-cp39-macosx_10_13_x86_64.whl (252.9 kB view details)

Uploaded CPython 3.9 macOS 10.13+ x86-64

switchboard_hw-0.0.33-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (279.5 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.33-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (271.3 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.33-cp38-cp38-macosx_11_0_arm64.whl (247.8 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

switchboard_hw-0.0.33-cp38-cp38-macosx_10_13_x86_64.whl (252.7 kB view details)

Uploaded CPython 3.8 macOS 10.13+ x86-64

switchboard_hw-0.0.33-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (281.7 kB view details)

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

switchboard_hw-0.0.33-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (274.4 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.33-cp37-cp37m-macosx_10_13_x86_64.whl (248.7 kB view details)

Uploaded CPython 3.7m macOS 10.13+ x86-64

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b30cc573e0ea5db2f31499b19b7ef662dcf26ee453a9933aa852406d17d9d6cb
MD5 ef9364d7f4510d62ebcabaf5eb1a3b56
BLAKE2b-256 74b4b1d659d399ab71515766d6e1cb71407f7ddc1c2bcb617f69daeeb83c5559

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 7a056b82362057b7da5b01f55ddf5e4a853b8af765e67d7d80dab391e8f0b14c
MD5 907bb3110226352775b0cca0570846a1
BLAKE2b-256 e2848843f6ef77191080e22be42df0f8ef8c3a3b0d754c732193cdf17f7db21f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7d6f8235493a0a44c079709fd369c2baf00fc2d78bc80cc2880275eda29aeb4a
MD5 48fed14921ca7ea4e5f5a6def1e03ca7
BLAKE2b-256 97d50e8824634732532c6fc1e497f605edb7dccc02a5ecb785a76dd4bb22bbab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp311-cp311-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 ab64afa7c6688d4d4bb7e6684a62584b368b46ae646dd7aaabf1824821668b49
MD5 6bfebe8c685a8d122ad698a6842c5de1
BLAKE2b-256 3527a74058a00d2a4a5c8142cc76c84a5f0689a8600fee2b9b8293310341899e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ba78c7096cfa2c9bd51914b9b643dbd5f2beb88cd5f9e2801f82d2a559ba325c
MD5 026b0b9dfeaf2fc1e2e15a2c793f64c9
BLAKE2b-256 ad0707a5a2431e395c92026988f1b0db1eecf5f95585103048cb6473fdb3d4da

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ddde485224094061d2e1c627e8b9cc84179d186f21ba693d3eb8c7f92fcd4361
MD5 3b185f69a9968c9a954165bf5a634c35
BLAKE2b-256 d77d35d77d2816e1452ffd252b05cc0a46f2e9039dbaf90961f3558cfe7d5352

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 64d9484dbe21f87c8cf41532ba7b1631068c453d03827dc07a353d066a8994ea
MD5 e69f7615f42132cda92af1d4308be992
BLAKE2b-256 a728aa11c5d27fcd632bd37fef1707541032301084f8c30189e3797bc155109f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp310-cp310-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 4d5a1f6117b7d07eebe4cae299155d9c6106b43e773db610bddc82caadb158a0
MD5 43e7af0c208b51ee143f84530771d3f1
BLAKE2b-256 883e438eee9003259a35aedf3b070c5cafb0e6474c374a7be7e8e6c41b45df9b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 32e85d1ce90e1635167ae49f6af6a650b8900f1deabd83b255942ce89d658a65
MD5 45660916305631ea5d07ff8d7008ad6f
BLAKE2b-256 ab04beea52071a1eba56e8fc4979f3ea55d5ba94c8cefb7bad8273e2fbebffd6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f938afcdd887c1c30b1e7c929d08521d5597fd3335de81cd1df466080cf852cc
MD5 4e877cd41cee394ec5b478269843900d
BLAKE2b-256 1a07317300481544ea2ba8800aa964714ce3fc33b7077a540f8e14d5baac6d1d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 de2f94af1dea0d7610f60634f526fd9806c067c8f83d1cc80936cd7df986ed7d
MD5 c6d293954276176ca1ad6d18ce5fc2b4
BLAKE2b-256 ac1a3d6aceadb6e6cd1b307bf93888fbfd94baad323cdf157cc90ae540e898ce

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp39-cp39-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 19f171b54592fc9441728b32a99e149bc24c0166e4cc4daee20355a43ef1139d
MD5 cb2060a0c1ff56c0b02f38646353026b
BLAKE2b-256 89ccd32851187e6d717200485989672c4fa2b342d98b292da5386039fb4ffae0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 bcd806eeb26c5e5e57fbb89e4a4445224140eadbf5d9661d74bb59b3a32220f7
MD5 29fc9718e2706c9ef566876d4b0caf3a
BLAKE2b-256 edb14bb2800d0ac2986f22d63e069c080482f41c88b117780f12aff621bdc866

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ba7825476be4703e9a84dcd581931270bea7d2188aef346a2ed44550a5d5a41c
MD5 38f8b9fe4e9b9576f6330d396a9623e1
BLAKE2b-256 f01d0ff8ebb11805623728c1dd7b73bdbfe19fcac410c6079c1ca6cc7cd36e49

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5447795001af7b87e4130ddad4e67b42dd1fb3ddebdf2db23dd68091ba9260e8
MD5 7bf957f86ac16b639789a1cb55b76fe6
BLAKE2b-256 91b21f03849db7696fa5ea32447813aa18f4f933c38190b61b1352d728c6ffb9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp38-cp38-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 ef70f246ee89fbadd839bff82675d5fa55626b160fbf72b15ef15fa7690c5e11
MD5 95aab0dffa9f004d90d0520a2ba42b05
BLAKE2b-256 7e5343e8fa9a742743b0e380a6a5bcc9693c0245844a7f82ff15370c879988cf

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 be2a0aae203d19ccaa23e3f9492721589e52323875334ace621095072dde0dd5
MD5 625ee314ab03f39223379fb0503b435e
BLAKE2b-256 4e851c5b39f5edf45902e37594570ca571aa94f79a862a29b4ebb6f25446bd07

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e9f9b71362cae2929f356f1f4366ec3b90c044dafb873f700025f37c1ac5c012
MD5 114986c97a1897f86b1746ba2359a2f1
BLAKE2b-256 3585aa96eee1ffdee22d61a3f98513183a4e3c1c4e7be6f068f7f84c080d3921

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.33-cp37-cp37m-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 1820dd416c1cbf8b54dab008cb4cb31c1bc8d4695e793c92cf23f35e0c3dd3d4
MD5 8dbf25bcf0bffd78275e9a19d1121084
BLAKE2b-256 2eb91699e8bcab65de2b6a91674dcfd8a57c686d14fe5de49d91333751c881a9

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