switchboard-hw 0.3.0__cp314-cp314-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- _switchboard.cpython-314-darwin.so +0 -0
- switchboard/__init__.py +24 -0
- switchboard/ams.py +668 -0
- switchboard/apb.py +278 -0
- switchboard/autowrap.py +1000 -0
- switchboard/axi.py +571 -0
- switchboard/axil.py +348 -0
- switchboard/bitvector.py +112 -0
- switchboard/cmdline.py +142 -0
- switchboard/cpp/Makefile +13 -0
- switchboard/cpp/bitutil.h +39 -0
- switchboard/cpp/pagemap.h +91 -0
- switchboard/cpp/pciedev.h +86 -0
- switchboard/cpp/router.cc +89 -0
- switchboard/cpp/spsc_queue.h +267 -0
- switchboard/cpp/switchboard.hpp +257 -0
- switchboard/cpp/switchboard_pcie.hpp +234 -0
- switchboard/cpp/switchboard_tlm.hpp +98 -0
- switchboard/cpp/umilib.h +144 -0
- switchboard/cpp/umilib.hpp +113 -0
- switchboard/cpp/umisb.hpp +364 -0
- switchboard/cpp/xyce.hpp +90 -0
- switchboard/deps/__init__.py +0 -0
- switchboard/deps/verilog_axi.py +23 -0
- switchboard/dpi/__init__.py +0 -0
- switchboard/dpi/switchboard_dpi.cc +119 -0
- switchboard/dpi/switchboard_dpi.py +13 -0
- switchboard/dpi/xyce_dpi.cc +43 -0
- switchboard/gpio.py +108 -0
- switchboard/icarus.py +85 -0
- switchboard/loopback.py +157 -0
- switchboard/network.py +714 -0
- switchboard/pytest_plugin.py +11 -0
- switchboard/sbdesign.py +55 -0
- switchboard/sbdut.py +744 -0
- switchboard/sbtcp.py +345 -0
- switchboard/sc/__init__.py +0 -0
- switchboard/sc/morty/__init__.py +0 -0
- switchboard/sc/morty/uniquify.py +67 -0
- switchboard/sc/sed/__init__.py +0 -0
- switchboard/sc/sed/sed_remove.py +47 -0
- switchboard/sc/standalone_netlist_flow.py +25 -0
- switchboard/switchboard.py +53 -0
- switchboard/test_util.py +46 -0
- switchboard/uart_xactor.py +66 -0
- switchboard/umi.py +793 -0
- switchboard/util.py +131 -0
- switchboard/verilator/__init__.py +0 -0
- switchboard/verilator/config.vlt +13 -0
- switchboard/verilator/testbench.cc +143 -0
- switchboard/verilator/verilator.py +13 -0
- switchboard/verilator_run.py +31 -0
- switchboard/verilog/__init__.py +0 -0
- switchboard/verilog/common/__init__.py +0 -0
- switchboard/verilog/common/common.py +26 -0
- switchboard/verilog/common/switchboard.vh +429 -0
- switchboard/verilog/common/uart_xactor.sv +247 -0
- switchboard/verilog/common/umi_gpio.v +236 -0
- switchboard/verilog/fpga/__init__.py +0 -0
- switchboard/verilog/fpga/axi_reader.sv +82 -0
- switchboard/verilog/fpga/axi_writer.sv +111 -0
- switchboard/verilog/fpga/config_registers.sv +249 -0
- switchboard/verilog/fpga/fpga.py +21 -0
- switchboard/verilog/fpga/include/sb_queue_regmap.vh +21 -0
- switchboard/verilog/fpga/include/spsc_queue.vh +7 -0
- switchboard/verilog/fpga/memory_fault.sv +40 -0
- switchboard/verilog/fpga/sb_fpga_queues.sv +416 -0
- switchboard/verilog/fpga/sb_rx_fpga.sv +303 -0
- switchboard/verilog/fpga/sb_tx_fpga.sv +294 -0
- switchboard/verilog/fpga/umi_fpga_queues.sv +146 -0
- switchboard/verilog/sim/__init__.py +0 -0
- switchboard/verilog/sim/auto_stop_sim.sv +25 -0
- switchboard/verilog/sim/perf_meas_sim.sv +97 -0
- switchboard/verilog/sim/queue_to_sb_sim.sv +176 -0
- switchboard/verilog/sim/queue_to_umi_sim.sv +66 -0
- switchboard/verilog/sim/sb_apb_m.sv +146 -0
- switchboard/verilog/sim/sb_axi_m.sv +199 -0
- switchboard/verilog/sim/sb_axil_m.sv +180 -0
- switchboard/verilog/sim/sb_axil_s.sv +180 -0
- switchboard/verilog/sim/sb_clk_gen.sv +89 -0
- switchboard/verilog/sim/sb_jtag_rbb_sim.sv +148 -0
- switchboard/verilog/sim/sb_rx_sim.sv +55 -0
- switchboard/verilog/sim/sb_to_queue_sim.sv +196 -0
- switchboard/verilog/sim/sb_tx_sim.sv +55 -0
- switchboard/verilog/sim/switchboard_sim.py +49 -0
- switchboard/verilog/sim/umi_rx_sim.sv +61 -0
- switchboard/verilog/sim/umi_to_queue_sim.sv +66 -0
- switchboard/verilog/sim/umi_tx_sim.sv +61 -0
- switchboard/verilog/sim/xyce_intf.sv +67 -0
- switchboard/vpi/switchboard_vpi.cc +431 -0
- switchboard/vpi/xyce_vpi.cc +200 -0
- switchboard/warn.py +14 -0
- switchboard/xyce.py +27 -0
- switchboard_hw-0.3.0.dist-info/METADATA +303 -0
- switchboard_hw-0.3.0.dist-info/RECORD +99 -0
- switchboard_hw-0.3.0.dist-info/WHEEL +6 -0
- switchboard_hw-0.3.0.dist-info/entry_points.txt +6 -0
- switchboard_hw-0.3.0.dist-info/licenses/LICENSE +190 -0
- switchboard_hw-0.3.0.dist-info/top_level.txt +2 -0
switchboard/apb.py
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# Python interface for AXI-Lite reads and writes
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2024 Zero ASIC Corporation
|
|
4
|
+
# This code is licensed under Apache License 2.0 (see LICENSE for details)
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from math import floor, ceil, log2
|
|
9
|
+
from numbers import Integral
|
|
10
|
+
|
|
11
|
+
from _switchboard import PySbPacket, PySbTx, PySbRx
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ApbTxRx:
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
uri: str,
|
|
18
|
+
fresh: bool = True,
|
|
19
|
+
data_width: int = 32,
|
|
20
|
+
addr_width: int = 16,
|
|
21
|
+
prot: int = 0,
|
|
22
|
+
slv_err_expected: bool = False,
|
|
23
|
+
queue_suffix: str = '.q',
|
|
24
|
+
max_rate: float = -1
|
|
25
|
+
):
|
|
26
|
+
"""
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
uri: str
|
|
30
|
+
Base name of for switchboard queues used to convey APB transactions.
|
|
31
|
+
fresh: bool, optional
|
|
32
|
+
If True (default), the queue specified by the uri parameter will get cleared
|
|
33
|
+
before executing the simulation.
|
|
34
|
+
data_width: int, optional
|
|
35
|
+
Width the write and read data buses, in bits.
|
|
36
|
+
addr_width: int, optional
|
|
37
|
+
Width the write and read address buses, in bits.
|
|
38
|
+
prot: int, optional
|
|
39
|
+
Default value of PROT to use for read and write transactions. Can be
|
|
40
|
+
overridden on a transaction-by-transaction basis.
|
|
41
|
+
slv_err_expected: bool, optional
|
|
42
|
+
Default response to expect from reads and writes.
|
|
43
|
+
None means "don't check the response".
|
|
44
|
+
This default can be overridden on a transaction-by-transaction basis.
|
|
45
|
+
queue_suffix: str, optional
|
|
46
|
+
File extension/suffix to use when naming switchboard queues that carry
|
|
47
|
+
APB transactions. For example, if set to ".queue", the write address
|
|
48
|
+
queue name will be "{uri}-aw.queue"
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
# check data types
|
|
52
|
+
assert isinstance(data_width, Integral), 'data_width must be an integer'
|
|
53
|
+
assert isinstance(addr_width, Integral), 'addr_width must be an integer'
|
|
54
|
+
|
|
55
|
+
# check that data width is a multiple of a byte
|
|
56
|
+
data_width_choices = [8, 16, 32, 64, 128, 256, 512, 1024]
|
|
57
|
+
assert data_width in data_width_choices, \
|
|
58
|
+
f'data_width must be in {data_width_choices}'
|
|
59
|
+
|
|
60
|
+
# check that data and address widths are supported
|
|
61
|
+
SBDW = 416
|
|
62
|
+
assert 0 < data_width <= floor(SBDW / (1 + (1 / 8))), 'data_width out of range'
|
|
63
|
+
assert 0 < addr_width <= SBDW - 3, 'addr_width out of range'
|
|
64
|
+
|
|
65
|
+
# save settings
|
|
66
|
+
self.data_width = data_width
|
|
67
|
+
self.addr_width = addr_width
|
|
68
|
+
self.default_prot = prot
|
|
69
|
+
self.default_slv_err_expected = slv_err_expected
|
|
70
|
+
|
|
71
|
+
# create the queues
|
|
72
|
+
self.apb_req = PySbTx(f'{uri}_apb_req{queue_suffix}', fresh=fresh, max_rate=max_rate)
|
|
73
|
+
self.apb_resp = PySbRx(f'{uri}_apb_resp{queue_suffix}', fresh=fresh, max_rate=max_rate)
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def strb_width(self):
|
|
77
|
+
return self.data_width // 8
|
|
78
|
+
|
|
79
|
+
def write(
|
|
80
|
+
self,
|
|
81
|
+
addr: Integral,
|
|
82
|
+
data,
|
|
83
|
+
prot: Integral = None,
|
|
84
|
+
slv_err_expected: bool = None
|
|
85
|
+
):
|
|
86
|
+
"""
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
addr: int
|
|
90
|
+
Address to write to
|
|
91
|
+
|
|
92
|
+
data: np.uint8, np.uint16, np.uint32, np.uint64, or np.array
|
|
93
|
+
Data to write
|
|
94
|
+
|
|
95
|
+
prot: Integral
|
|
96
|
+
Value of PROT for this transaction. Defaults to the value provided in the
|
|
97
|
+
ApbTxRx constructor if not provided, which in turn defaults to 0.
|
|
98
|
+
|
|
99
|
+
slv_err_expected: str, optional
|
|
100
|
+
Response to expect for this transaction.
|
|
101
|
+
None means, "don't check the response". Defaults to the
|
|
102
|
+
value provided in the ApbTxRx constructor if not provided, which in turn
|
|
103
|
+
defaults to False.
|
|
104
|
+
|
|
105
|
+
Returns
|
|
106
|
+
-------
|
|
107
|
+
bool
|
|
108
|
+
slv_err: True if SLVERR was received, False otherwise.
|
|
109
|
+
"""
|
|
110
|
+
(rd_data, slv_err) = self.transaction(
|
|
111
|
+
write=True,
|
|
112
|
+
addr=addr,
|
|
113
|
+
data=data,
|
|
114
|
+
prot=prot,
|
|
115
|
+
slv_err_expected=slv_err_expected
|
|
116
|
+
)
|
|
117
|
+
return slv_err
|
|
118
|
+
|
|
119
|
+
def read(
|
|
120
|
+
self,
|
|
121
|
+
addr: Integral,
|
|
122
|
+
prot: Integral = None,
|
|
123
|
+
resp_expected: str = None
|
|
124
|
+
):
|
|
125
|
+
"""
|
|
126
|
+
Parameters
|
|
127
|
+
----------
|
|
128
|
+
addr: int
|
|
129
|
+
Address to read from
|
|
130
|
+
|
|
131
|
+
prot: Integral
|
|
132
|
+
Value of PROT for this transaction. Defaults to the value provided in the
|
|
133
|
+
AxiLiteTxRx constructor if not provided, which in turn defaults to 0.
|
|
134
|
+
|
|
135
|
+
resp_expected: str, optional
|
|
136
|
+
Response to expect for this transaction. Options are 'OKAY', 'EXOKAY', 'SLVERR',
|
|
137
|
+
'DECERR', and None. None means, "don't check the response". Defaults to the
|
|
138
|
+
value provided in the AxiLiteTxRx constructor if not provided, which in turn
|
|
139
|
+
defaults to 'OKAY'
|
|
140
|
+
|
|
141
|
+
Returns
|
|
142
|
+
-------
|
|
143
|
+
int
|
|
144
|
+
Value read, as an arbitrary-size Python integer.
|
|
145
|
+
"""
|
|
146
|
+
(rd_data, slv_err) = self.transaction(
|
|
147
|
+
write=False,
|
|
148
|
+
addr=addr,
|
|
149
|
+
data=None,
|
|
150
|
+
prot=prot,
|
|
151
|
+
slv_err_expected=resp_expected
|
|
152
|
+
)
|
|
153
|
+
return rd_data
|
|
154
|
+
|
|
155
|
+
def transaction(
|
|
156
|
+
self,
|
|
157
|
+
write: bool,
|
|
158
|
+
addr: Integral,
|
|
159
|
+
data,
|
|
160
|
+
prot: Integral = None,
|
|
161
|
+
slv_err_expected: bool = None
|
|
162
|
+
):
|
|
163
|
+
"""
|
|
164
|
+
Parameters
|
|
165
|
+
----------
|
|
166
|
+
addr: int
|
|
167
|
+
Address to write to
|
|
168
|
+
|
|
169
|
+
data: np.uint8, np.uint16, np.uint32, np.uint64
|
|
170
|
+
Data to write
|
|
171
|
+
|
|
172
|
+
prot: Integral
|
|
173
|
+
Value of PROT for this transaction. Defaults to the value provided in the
|
|
174
|
+
ApbTxRx constructor if not provided, which in turn defaults to 0.
|
|
175
|
+
|
|
176
|
+
slv_err_expected: str, optional
|
|
177
|
+
Response to expect for this transaction.
|
|
178
|
+
None means, "don't check the response". Defaults to the
|
|
179
|
+
value provided in the ApbTxRx constructor if not provided, which in turn
|
|
180
|
+
defaults to False.
|
|
181
|
+
|
|
182
|
+
Returns
|
|
183
|
+
-------
|
|
184
|
+
bool
|
|
185
|
+
slv_err: True if SLVERR was received, False otherwise.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
# set defaults
|
|
189
|
+
|
|
190
|
+
if prot is None:
|
|
191
|
+
prot = self.default_prot
|
|
192
|
+
|
|
193
|
+
if slv_err_expected is None:
|
|
194
|
+
slv_err_expected = self.default_slv_err_expected
|
|
195
|
+
|
|
196
|
+
# check/standardize data types
|
|
197
|
+
|
|
198
|
+
assert isinstance(addr, Integral), 'addr must be an integer'
|
|
199
|
+
addr = int(addr)
|
|
200
|
+
|
|
201
|
+
assert isinstance(prot, Integral), 'prot must be an integer'
|
|
202
|
+
prot = int(prot)
|
|
203
|
+
|
|
204
|
+
if data is None:
|
|
205
|
+
data = np.zeros((self.data_width // 8,), dtype=np.uint8)
|
|
206
|
+
elif isinstance(data, np.integer):
|
|
207
|
+
data = np.frombuffer(data.tobytes(), dtype=np.uint8)
|
|
208
|
+
else:
|
|
209
|
+
raise TypeError(f"Unknown data type: {type(data)}")
|
|
210
|
+
|
|
211
|
+
bytes_to_send = data.size
|
|
212
|
+
|
|
213
|
+
# range validation
|
|
214
|
+
|
|
215
|
+
assert 0 <= addr < (1 << self.addr_width), 'addr out of range'
|
|
216
|
+
assert addr + bytes_to_send <= (1 << self.addr_width), \
|
|
217
|
+
"transaction exceeds the address space."
|
|
218
|
+
|
|
219
|
+
assert 0 <= prot < (1 << 3), 'prot out of range'
|
|
220
|
+
|
|
221
|
+
header_bytes: int = int(ceil((1 + 3 + self.strb_width) / 8.0))
|
|
222
|
+
data_bytes: int = self.data_width // 8
|
|
223
|
+
addr_bytes: int = self.addr_width // 8
|
|
224
|
+
|
|
225
|
+
addr_mask = (1 << self.addr_width) - 1
|
|
226
|
+
addr_mask >>= ceil(log2(data_bytes))
|
|
227
|
+
addr_mask <<= ceil(log2(data_bytes))
|
|
228
|
+
|
|
229
|
+
# calculate strobe value based on the offset and number
|
|
230
|
+
# of bytes that we're writing.
|
|
231
|
+
strb = (1 << data_bytes) - 1
|
|
232
|
+
header = int(write)
|
|
233
|
+
header = (header << 3) | prot
|
|
234
|
+
header = (header << self.strb_width) | strb
|
|
235
|
+
header = np.frombuffer(
|
|
236
|
+
header.to_bytes(header_bytes, 'little'),
|
|
237
|
+
dtype=np.uint8
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
addr_as_buff = np.frombuffer(
|
|
241
|
+
(addr & addr_mask).to_bytes((self.addr_width + 7) // 8, 'little'),
|
|
242
|
+
dtype=np.uint8
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
pack = np.empty((header_bytes + addr_bytes + data_bytes,), dtype=np.uint8)
|
|
246
|
+
pack[0:data_bytes] = data
|
|
247
|
+
pack[data_bytes:data_bytes + addr_bytes] = addr_as_buff
|
|
248
|
+
pack[data_bytes + addr_bytes:] = header
|
|
249
|
+
pack = PySbPacket(data=pack, flags=1, destination=0)
|
|
250
|
+
# Transmit request
|
|
251
|
+
self.apb_req.send(pack, True)
|
|
252
|
+
|
|
253
|
+
# wait for response
|
|
254
|
+
pack = self.apb_resp.recv(True)
|
|
255
|
+
pack = pack.data.tobytes()
|
|
256
|
+
pack = int.from_bytes(pack, 'little')
|
|
257
|
+
|
|
258
|
+
# decode the response
|
|
259
|
+
rd_data = pack & ((1 << self.data_width) - 1)
|
|
260
|
+
slv_err = bool((pack >> self.data_width) & 0b1)
|
|
261
|
+
|
|
262
|
+
# check the response if desired
|
|
263
|
+
if slv_err_expected is not None:
|
|
264
|
+
assert slv_err == slv_err_expected, f'Unexpected response: slv_err = {slv_err}'
|
|
265
|
+
|
|
266
|
+
return (rd_data, slv_err)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def apb_uris(prefix, suffix='.q'):
|
|
270
|
+
# returns a list of the URIs associated with a given APB
|
|
271
|
+
# prefix. For example, apb_uris('apb') returns ['apb_apb_req.q',
|
|
272
|
+
# 'apb_apb_resp.q']. Changing the optional suffix
|
|
273
|
+
# argument changes the file extension assumed in generating this list.
|
|
274
|
+
|
|
275
|
+
return [
|
|
276
|
+
f'{prefix}_apb_req{suffix}',
|
|
277
|
+
f'{prefix}_apb_resp{suffix}'
|
|
278
|
+
]
|