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.32-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (276.5 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.32-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (267.9 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.32-cp311-cp311-macosx_11_0_arm64.whl (245.2 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

switchboard_hw-0.0.32-cp311-cp311-macosx_10_13_x86_64.whl (249.8 kB view details)

Uploaded CPython 3.11 macOS 10.13+ x86-64

switchboard_hw-0.0.32-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (275.0 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.32-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (266.8 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.32-cp310-cp310-macosx_11_0_arm64.whl (243.4 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

switchboard_hw-0.0.32-cp310-cp310-macosx_10_13_x86_64.whl (248.3 kB view details)

Uploaded CPython 3.10 macOS 10.13+ x86-64

switchboard_hw-0.0.32-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (275.1 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.32-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (266.8 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.32-cp39-cp39-macosx_11_0_arm64.whl (243.6 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

switchboard_hw-0.0.32-cp39-cp39-macosx_10_13_x86_64.whl (248.5 kB view details)

Uploaded CPython 3.9 macOS 10.13+ x86-64

switchboard_hw-0.0.32-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (275.1 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.32-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (266.8 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.32-cp38-cp38-macosx_11_0_arm64.whl (243.4 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

switchboard_hw-0.0.32-cp38-cp38-macosx_10_13_x86_64.whl (248.2 kB view details)

Uploaded CPython 3.8 macOS 10.13+ x86-64

switchboard_hw-0.0.32-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (277.3 kB view details)

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

switchboard_hw-0.0.32-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (270.0 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.32-cp37-cp37m-macosx_10_13_x86_64.whl (244.3 kB view details)

Uploaded CPython 3.7m macOS 10.13+ x86-64

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b2c9a48c14ab539b9b908d0b4a9548188f7851f1392e994033ced4e2103c76a1
MD5 ea0bd0eba8d8d027c4326a97fb45f336
BLAKE2b-256 bc2f33034276f821a28fc21165d04d95e848b0fff7e166ee811081bdd5586858

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d585001ccaf313c9ffe94eaed9d818916f0022df6dcdb6d89d7ab9f325cc7651
MD5 f7534a96a15fb0cdb2e0b05a9cbfef81
BLAKE2b-256 c0cc8ff3f65ab780e2eb9a41e9938536a88a0fa815c755a7d2b17a98993e9cef

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e6ed13dbc75a87b010e1ce39a1e2305d690412f1089e2c070a40753e7d5de253
MD5 0697d4e98d03c2e5d85ebb9e477afbcf
BLAKE2b-256 e0582d9ac02c25cd65c916af34836d9ac1556ec1d639eaae2243d3d1b05f2db7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp311-cp311-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 96de712734d464c0f7a4753283f8ccf7ad0effe6a06ad9ce31a6d828da5bc06e
MD5 d33295e49263eea955105b75ce0a3562
BLAKE2b-256 aa48fd985d48980aedeed20fcd3ae56978b6631243171ba9992e3f2333504cfb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 47a942e1edfc22e91de6fc20d7f48d9dd21122c69b737516befb60e68f48171f
MD5 5b1fb3b0a54218aca7ce105ab04580e5
BLAKE2b-256 a4b2d05ff654cffefbffffe6d3b8b33e4f1afa161c51b699ac58d34192004bea

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ca702dcc884558a1d9147797314d1064338e8ad0f608966973deabfd2db848e2
MD5 13eed9f867ea86559b3a2f3459952790
BLAKE2b-256 41ad338dc7a5e4238a337dc6584a998f8ec70a8e48a059d7b0f1b959b45b6198

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a539e8f82283dbac803dbeef715f034e8a8720e82ba9c43145d867577981de8f
MD5 5d76d5440704dbcb84cc161c6843b6b9
BLAKE2b-256 be07482172e700b833cb94b41afac332a0329efe0ddeb4fc17e257e5848222bc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp310-cp310-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 d182c7aba5f164086671f543aff2f599f02471f83f5642d99a38114c57d6e6b3
MD5 2c4f1b0ce4e050c819a91558061ac7b1
BLAKE2b-256 2779f4e4a91451f1a90591201b55929628fdd880e8e49c9bf6b2b6c568522006

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fc51d3112a01c3002b6269497ecfe7a3e684096c58660fa4adde3bc36ac32cf5
MD5 7cc1143da71ee980ffd03d8328c1c6bb
BLAKE2b-256 b146e71da77217189ed6909b8c9a19d99d671210dd78509d0b4074c90a1aceba

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 77fe4143c18644ea8b8637078fc8beac813205959c71ba44fd9a67f5f13d1992
MD5 401876b58460a26608e6eb4aadc59b99
BLAKE2b-256 4d8bc5ea58063802b92200a784bdd31230f7ba33b1fa6737bf8c2e302ca8b79a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ab8513f40bfc01369f5ae4ff93a76709a87a79a5ff2cb292063f33d812046e66
MD5 ecd37db90322a7df5e130a9273f2b5dc
BLAKE2b-256 e51b10417d04d6153b3dbb4c291405d8717a3e43e60fa90c28ca36eb0bf020a5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp39-cp39-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 a4acd394468e33d83052a6a640fc0980f2b19560a2bf9fea097c2677d8141b3b
MD5 b219d0d033ccc17bb776526676e16be1
BLAKE2b-256 62a2c924ac73034b35869c38065fa3995150ea6f4235132a0d6f254f016d9628

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 998cd667ff1e611688df096ce5e1c49b0c468292f26dafd9217853ae7a80ebdf
MD5 aad10e504f4206db3b1fe87bb68f3b97
BLAKE2b-256 1e5cfce180d224bc5ba4c4a6a64295ba4175c7ff9a5937dd96f1cf2dfdc794e5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 55e8d7cc2205d9aa7bc5e9a0682850d7a951f94435988b176ff85f3609bb92f5
MD5 c7053203a742108acc0ed319c6f1f976
BLAKE2b-256 e1c793fda4509aa8f5bbb1a3392c12473340623da991c2d5215dcda9081fc6c9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b0a64f6e8cec2ab9d385f68e7b719dc52717477a4aad4f4238a45c699ecb823f
MD5 e4faa79d21946d2bd6ede5f8d686787f
BLAKE2b-256 26c339fd2047e12c446911648a36f706233ca248e335a277e0b4738da55f92a6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp38-cp38-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 eedd25ae45089cef6190a023dd735a4ebfee0e41372b46ad6a7b2a03865fb23f
MD5 b3f60329d188d6cca38186bf7a57d944
BLAKE2b-256 293ece9631fe79c2478df4d5bebb5cd2820f145882e0fe6d7fb8dcf1601fdd7a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b83db8df5843aa9377fb524a91bdac29d3ffee7e1bbce3d804c7c51e14ea879f
MD5 028084a37d2def477427f1596196019e
BLAKE2b-256 6e323272fac2efd2c02237993344a5f06b63289fc238d084eaa80b31b691626d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 2789ff1ac9cde8c0bf7c92d899ff0c07e3ad8a723a81abb01f075cb00f2c6f84
MD5 506b7443ddc96fc4fbff34142c0ded1a
BLAKE2b-256 0fe40c5d56e90bc60bf157e8cf20d4cd6fd17ce0ec22fc415f0fa5f668bdbb6b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.32-cp37-cp37m-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 9a0812ded1bc8b47d1c9351c2b7a94f71722aa80d800216215f217f7d6a2b9cf
MD5 cc683cc1505c431ab8723b6fabbe8af6
BLAKE2b-256 1806b76875ed9476ecc53406416cd5d7d4e1958b148b77590b2b3c08899deda6

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