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

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

switchboard_hw-0.0.35-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (281.2 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.35-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (272.6 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.35-cp311-cp311-macosx_11_0_arm64.whl (249.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

switchboard_hw-0.0.35-cp311-cp311-macosx_10_13_x86_64.whl (254.5 kB view details)

Uploaded CPython 3.11macOS 10.13+ x86-64

switchboard_hw-0.0.35-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (279.7 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.35-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (271.5 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.35-cp310-cp310-macosx_11_0_arm64.whl (248.1 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

switchboard_hw-0.0.35-cp310-cp310-macosx_10_13_x86_64.whl (253.0 kB view details)

Uploaded CPython 3.10macOS 10.13+ x86-64

switchboard_hw-0.0.35-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (279.8 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.35-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (271.5 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.35-cp39-cp39-macosx_11_0_arm64.whl (248.3 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

switchboard_hw-0.0.35-cp39-cp39-macosx_10_13_x86_64.whl (253.2 kB view details)

Uploaded CPython 3.9macOS 10.13+ x86-64

switchboard_hw-0.0.35-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (279.8 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.35-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (271.5 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.35-cp38-cp38-macosx_11_0_arm64.whl (248.1 kB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

switchboard_hw-0.0.35-cp38-cp38-macosx_10_13_x86_64.whl (252.9 kB view details)

Uploaded CPython 3.8macOS 10.13+ x86-64

switchboard_hw-0.0.35-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (282.0 kB view details)

Uploaded CPython 3.7mmanylinux: glibc 2.17+ x86-64

switchboard_hw-0.0.35-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (274.7 kB view details)

Uploaded CPython 3.7mmanylinux: glibc 2.17+ ARM64

switchboard_hw-0.0.35-cp37-cp37m-macosx_10_13_x86_64.whl (249.0 kB view details)

Uploaded CPython 3.7mmacOS 10.13+ x86-64

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9575154bbbed28d44f41c66982b0f171f59ddf13779be8126b27c7e86f99476f
MD5 1e9a84267203282f9c53c346ae3a1d72
BLAKE2b-256 f2e9f6733bea6baefc994cfdb8f5ae6d869889d67823a8f9ccd912d3939bb2f4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 9ed796a2432dcc4967e37ababdff7d60071a4a7982e0157af206a5ff4ce48993
MD5 1f5bdc2cfe4e024a3294a237d5616dee
BLAKE2b-256 c3290f2b4f802b72b7f6d583311ba5ff6fdbe659a4f1cd5da59f534de195855f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6bc7549fece342761e7aee8708b7d00b17e136cc488f313e5b860e2d8291f65e
MD5 5c961e39a90456f256698643bf55ab99
BLAKE2b-256 d521f86bfd1ff5e724cc35bdae107639730e9746dc163948e9be26689c2f3fd9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp311-cp311-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 09419b52f86f127dab604b5112ce36d332ae9b9f13a3dd5dd86c986fe9e543cd
MD5 45086baa6eef790311f554de331f5368
BLAKE2b-256 b3773988460331c6807194cf543b8ed3bfd95821946eb8b79394cd8187da5aed

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 02ff7331eb077b9b836bdaeae4e8de960015418364568773f1e42607bb5fa860
MD5 b1d37adc48c457e307c2debabac00dad
BLAKE2b-256 43d9d4ff72485e128cbcbde718d16c378be41a411eba7fa9a2e12f18716e72b8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 7dc74d356898e747f1b413843c9bfa544480ad21ef5f0ef57ba5f8a30f3acc12
MD5 6a2783ed8bc903563850caaa1169c259
BLAKE2b-256 b6a1292641aab5a5500e49415e82914aab490111502ae04dc99f403a169b979f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4455d4e584a3e1b3964747c436ec8bca4285e86ed0932cefc07c64722c4bcd4b
MD5 ddd9873320c449ad4f7355cdf99b58cb
BLAKE2b-256 57275d48f2fa594e9bfa88d99d0359ae887e39a19c25a70af67a7531b9ba758d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp310-cp310-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 f485623014615cb9625ecce403fc7a38d72976635ab799fc46d22a89e1965263
MD5 e870c6492628b256a4d3dc20e97bc9d0
BLAKE2b-256 94dd0a41eb4cc21590fa27fb61671548a5ee961d89ebb804ea5a3f27ed5db1d5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 cdd3b9960a23835e865719d67bea0197d05b99bc99fa566e258a18fea6f358eb
MD5 62e45fa24ca3d165751193706f2ff654
BLAKE2b-256 fa847a4dd533c83e86a0bbb4841abfbe9db51ce9011bc147e9d6198bf4f6fcb0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ad7c6489bbfe39ca595f0ac6ff1fcf213ccebdf424aac5ac3e5811ee30d6f6ff
MD5 ac806227b212d84439abc101d037737a
BLAKE2b-256 d20a45787259e5ae20240d39d89d29a6d15e9f6f64ae14a9cbed42783112246d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b8cd4b03018108d2e19caef30313d7498cf33704fbbffdf8618e61d430dee781
MD5 bfa7add0130b7e1bf5aba403d12d123d
BLAKE2b-256 fe1c1a87706847d7dd6b4555bf751da97dc573a311341cdade07ada80072ab5a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp39-cp39-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 3931f3db2c96001114c850cb2252aca3bd013d0b81c50e7642273b880cfcf519
MD5 c90491b4c9753c7fe5fe4d3680c0a6b5
BLAKE2b-256 59ac547b0ba4d51a09b1f3fdf12b56ca3fbb830e1265071379605ae35e481782

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a5d92295783aca47526d5425bf7bac7b5f70af326e74bfa3a619d27bfecba549
MD5 268bdc4569003e2c6813e7fc9d592aef
BLAKE2b-256 1bb707ca887f382b90f86b789779ba88930385d973fb98021aada7dd172c5ef3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 530acb33b96c26d4c582ff7f2e2ee85bfa13ff59dd082d0ad32dd72739eaf2c2
MD5 75966558a3dbf9f6088ebf6ebc7bef5f
BLAKE2b-256 af45b4adb61d543089833ac7c58435ea5c4ab8cc04a0bd08f970a35f4b8b4241

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ab20dff3d6079142cd6da5cff5929d9941bf1cb97276f7f47ea0cf95145d9a61
MD5 d1eabfffcdc3e48224b6303cf6a3a253
BLAKE2b-256 036df6535d92cc6c798ca5fa4dc7b70a642da84e9d5628b00c2a5d5ccb613d94

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp38-cp38-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 14f0bb29a19ffa05d837a6408b127f4d7f9a0aa63843859a48a77b6f68eea2a5
MD5 24333bf7bcf9e1e0f570213065ff8c08
BLAKE2b-256 327ceeea1028a897acef65a23846fdfa2354333a166bb731626e0d1583806375

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b7ce2693c32ce8417f32be66f7b553508175a4ff213f84a01ba514eb35b6a9e4
MD5 023daf9a38c18a3846df7a27cb7a8eda
BLAKE2b-256 f4ac8cf4d6690bb4c5d5dffd65fa82443c963d972fcf2f16392cd98ac3984fd7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 fd44d42769f49c5ec41d2652a4b310b377addefeae4719c5b3f080bb46329b3e
MD5 4afce20d188813cc60158f60ece0f7cd
BLAKE2b-256 01e4bcddca1c1a1fe25e4134969eb597b38e96e6873f97487c10d6c455b1bdd1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for switchboard_hw-0.0.35-cp37-cp37m-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 5c159c37756a87e1f6134a5fadbed433c39dedee2984ee6be292dd075bc9b51e
MD5 20bb3b4b00986f40dc9d4064653f458e
BLAKE2b-256 a2859f9440fb88bef2e8df85fd1cc876ebe59952028ca02780ac7604d3eb8278

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