Pgp2bSim
Pgp2bSim builds a simulated PGP2B endpoint from stream TCP clients plus a
sideband channel.
Co-Simulation Context
In many development flows, VHDL is run in a simulator (commonly VCS) while Rogue software drives and observes the design through Rogue stream interfaces (with VHPI on the firmware side). This is often referred to as software co-simulation.
In deployed firmware, PGP2b links are commonly used between FPGA endpoints.
For simulation, SURF provides RoguePgp2bSim firmware modules that emulate
PGP link endpoints and expose TCP-backed stream interfaces.
Pgp2bSim exists to connect two of those simulated endpoints through
software. This avoids simulating full high-speed serial transceiver behavior in
VHDL, which is typically much slower, while still exercising the intended data
movement between link endpoints.
In short, this module focuses on emulating the functional purpose of the link (frame movement and sideband exchange) rather than electrical-link behavior. Although this utility may ultimately belong in SURF, it is currently part of Rogue and documented here.
Simulation Workflow
Key pieces in the simulation workflow include:
Pgp2bSim(vcCount, host, port): constructs one simulated endpoint.connectPgp2bSim(a, b): links all virtual channels and sideband between two endpoints.setRecvCb(fn)on each endpoint sideband object: registers callback for sidebandopCode/remDataevents.Context-manager usage (
with): ensures sockets/threads are cleaned up.
Configuration Example
import pyrogue.interfaces.simulation as pis
# Create one simulated endpoint with 4 virtual channels.
pgp = pis.Pgp2bSim(
vcCount=4,
host='127.0.0.1',
port=9000,
)
Key Constructor Arguments
vcCountselects how many virtual channels are created.hostselects the TCP and sideband host endpoint.portselects the base port for VC 0, with additional virtual channels on successive even-numbered ports.
The current implementation uses a fixed sideband offset at port+8 through
SideBandSim rather than deriving that offset from vcCount, so
vcCount should be kept at <= 4 to avoid port overlap with the sideband
channel.
Integrated Sideband Channel
In Pgp2bSim, sideband is not a separate topology concept; it is part of the
simulated PGP endpoint. Internally it uses SideBandSim to exchange optional
opCode and remData fields.
Sideband port behavior (per endpoint):
PULL socket connects to
port+8PUSH socket connects to
port+9These offsets are fixed in current code, independent of
vcCount.
Typical sideband callback pattern:
import pyrogue.interfaces.simulation as pis
def on_a_sideband(op_code, rem_data):
# Called when endpoint A receives sideband data.
print("A sideband:", op_code, rem_data)
def on_b_sideband(op_code, rem_data):
# Called when endpoint B receives sideband data.
print("B sideband:", op_code, rem_data)
with pis.Pgp2bSim(vcCount=4, host='127.0.0.1', port=9000) as a, \
pis.Pgp2bSim(vcCount=4, host='127.0.0.1', port=9100) as b:
pis.connectPgp2bSim(a, b)
# Register sideband callbacks on each endpoint.
a.setRecvCb(on_a_sideband)
b.setRecvCb(on_b_sideband)
# Inject sideband data from either endpoint.
a.sendOpCode(0x3A)
b.sendRemData(0x55)
Standalone SideBandSim Usage
While sideband is integrated into Pgp2bSim, SideBandSim is also useful
on its own to emulate PGP2b opcode/remData behavior in software/firmware
co-simulation.
import pyrogue.interfaces.simulation as pis
def on_sideband(op_code, rem_data):
# Receive emulated opcode/remData notifications.
print("sideband rx:", op_code, rem_data)
with pis.SideBandSim('127.0.0.1', 9008) as sb:
# Register receive callback.
sb.setRecvCb(on_sideband)
# Send opcode-only and remData-only examples.
sb.send(opCode=0x12)
sb.send(remData=0x34)
Connecting Two Simulated Endpoints
import pyrogue.interfaces.simulation as pis
# Build two simulated endpoints using different base-port ranges.
with pis.Pgp2bSim(vcCount=4, host='127.0.0.1', port=9000) as a, \
pis.Pgp2bSim(vcCount=4, host='127.0.0.1', port=9100) as b:
# Connect all VCs bidirectionally and link sideband callbacks.
pis.connectPgp2bSim(a, b)
connectPgp2bSim(a, b) links each VC pair bidirectionally and cross-connects
sideband callbacks.
Operational Notes
Use distinct base-port ranges per endpoint to avoid overlap.
Keep
vcCountmatched between both endpoints when linking.Use
withcontext management so background resources are cleaned up automatically.
Logging
Pgp2bSim itself is a composition wrapper and does not create a dedicated
logger of its own.
The useful logging comes from two lower layers:
SideBandSimuses Python logging with names of the formpyrogue.SideBandSim.<host>.<port>The underlying TCP stream endpoints can be debugged through the normal TCP bridge logger family documented in Stream TCP Bridge
Example:
import logging
import rogue
logging.getLogger('pyrogue.SideBandSim').setLevel(logging.DEBUG)
rogue.Logging.setFilter('pyrogue.stream.TcpCore', rogue.Logging.Debug)
API Reference
Python: