SRP Protocol Version 3
For current SRP register links, Rogue provides
rogue.protocols.srp.SrpV3. SrpV3 converts Rogue memory transactions
into SRPv3 stream frames and decodes hardware responses back into memory
transaction completion.
Rogue does not re-document the SRPv3 wire format here. Use the protocol specification for packet-level details:
SRPv3 reference: https://confluence.slac.stanford.edu/x/cRmVD
When To Use SrpV3
Use for current systems unless endpoint compatibility requires SRP Protocol Version 0.
Use when the link needs SRP register semantics rather than raw commands.
Pair it with a stream transport such as DMA or UDP/RSSI/packetizer.
Behavior
Rogue can issue multiple SRPv3 requests before responses return; these are tracked as in-flight transactions by transaction ID.
Responses are matched by ID, so response order does not need to match request order.
If a response is missing, the initiating memory master times out based on the configured software timeout (see
Master.setTimeout(), microseconds).Late responses that arrive after timeout are treated as expired and ignored.
SRPv3 also carries a hardware timeout field in the request header (C++:
setHardwareTimeout(), Python binding:_setHardwareTimeout()), which is separate from Rogue software wait timeout handling.SrpV3enforces 4-byte alignment and defaults to a 4096-byte max transaction size (from constructormemory::Slave(4, 4096)).
The class sits directly between the memory and stream interfaces. Connect it to
a lower stream transport, then use the SRP object as the memBase for
PyRogue devices or other memory clients.
Threading And Locking
doTransaction()andacceptFrame()can be invoked from different runtime contexts.In-flight transaction matching is protected by the base memory-slave mutex.
Per-transaction payload/state access is protected via
TransactionLock.
Logging
SrpV3 uses Rogue C++ logging, not Python logging.
Logger name:
pyrogue.SrpV3Configuration API:
rogue.Logging.setFilter('pyrogue.SrpV3', rogue.Logging.Debug)Typical messages: transmitted request headers, received response headers, undersized frames, bad headers, error tails, and transaction-ID mismatches
Set the filter before constructing the SrpV3 object. Rogue C++ loggers
copy their level when the logger instance is created.
Python Example
The most common PyRogue pattern is to construct the transport and SrpV3
inside a Root subclass, then pass the SRP object as memBase when adding
devices.
import pyrogue as pr
import rogue.hardware.axi
import rogue.protocols.srp
class MyRegs(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.RemoteVariable(
name='ScratchPad',
description='Example RW register',
offset=0x0000,
bitSize=32,
mode='RW',
base=pr.UInt,
))
class MyRoot(pr.Root):
def __init__(self, dev='/dev/datadev_0', **kwargs):
super().__init__(timeout=2.0, **kwargs)
# Stream transport carrying SRPv3 frames.
self.regStream = rogue.hardware.axi.AxiStreamDma(dev, 0, True)
# SRPv3 protocol bridge.
self.srp = rogue.protocols.srp.SrpV3()
# Bidirectional stream connection: transport <-> SRPv3.
self.regStream == self.srp
# Optional protocol timeout field encoded into SRPv3 header.
self.srp._setHardwareTimeout(0x0A) # Python binding name.
# Attach register map device to SRPv3 memory slave interface.
self.add(MyRegs(
name='Regs',
offset=0x00000000,
memBase=self.srp,
expand=True,
))