Arrays#
Note
This page describes the target API for register, regfile, and field arrays. It is aspirational and tracks the design sketch; not every behavior is wired up in the current release.
Overview#
SystemRDL arrays apply to reg, regfile, field, and addrmap
nodes. The Python model treats every array as a typed Sequence: it has
a length, supports integer and slice indexing, iterates lazily, and
participates in in membership tests. Arrays are bus-bound — every element
access remains a real handle that issues bus transactions when read or
written.
Multi-dimensional RDL arrays (reg my_reg[4][16]) are exposed both as
chained subscripts (my_reg[2][5]) and as native tuple index
(my_reg[2, 5]), with a NumPy-style .shape attribute reporting the
dimensions.
Single dimension#
A 1-D array is the common case: soc.dma.channel below is a
ChannelArray of length 8.
soc.dma.channel # ChannelArray, len=8
soc.dma.channel[3] # one channel
soc.dma.channel[-1] # last
soc.dma.channel[2:6] # ChannelSlice (still bus-bound)
list(soc.dma.channel) # iterate
3 in soc.dma.channel # by index
Negative indices count from the end, slicing yields a ChannelSlice that
remains bus-bound (no values are read until you ask), and iteration produces
each element in order.
Multi-dimension#
For multi-dimensional RDL arrays, both tuple index and chained subscripts
are supported. The .shape attribute reports the array’s dimensions as a
tuple, mirroring numpy.ndarray.shape.
# rdl: reg my_reg[4][16];
soc.regblock.my_reg[2, 5] # tuple index — natural for users
soc.regblock.my_reg[2][5] # also supported
soc.regblock.my_reg.shape # (4, 16)
Bulk reads and writes#
Indexing a register array with a slice returns an ArrayView. An
ArrayView:
Coalesces reads into bursts when the master supports it.
Returns
ndarray[uint{regwidth}]for a single field or single register array.Returns a structured ndarray when multiple fields are projected.
NumPy is a hard runtime dependency — bulk array reads, memory bursts, and the buffer protocol are first-class.
# Read all 64 entries of a lookup table
vals = soc.lut.entry[:].read() # ndarray[uint32], shape (64,)
# Read one field across the array
enables = soc.dma.channel[:].config.enable.read() # ndarray[bool], shape (8,)
# Write same value to all
soc.lut.entry[:] = 0
# Write per-element
soc.lut.entry[:] = np.arange(64)
# Modify one field across the array
soc.dma.channel[:].config.modify(enable=0) # 8 RMWs (or 1 burst-RMW if supported)
# Filter
[c for c in soc.dma.channel if c.config.enable.read()]
The .modify(**fields) form on an ArrayView runs one RMW per element
by default and collapses to a single burst-RMW when the master advertises
that capability — see /bus_layer for details on burst negotiation
and the soc.batch() context that lets you queue many such operations.
Field arrays#
Field arrays are conceptually rare but supported — for instance, a register
that packs sixteen single-bit mode flags as mode[16]. They expose as a
FieldArray with the same indexing, slicing, and iteration semantics as
register arrays:
soc.gpio.mode # FieldArray, len=16
soc.gpio.mode[5].read() # one bit
soc.gpio.mode[:].read() # ndarray[bool], shape (16,)
soc.gpio.mode[0:8] = 0xAA # bitmask write across the slice
See also#
/memory — memory regions, bursts, and the NumPy buffer protocol.
/bus_layer — how
soc.batch(), masters, and burst capability back the array fast paths described above.