Connecting Memory Elements

A memory bus is built by connecting a transaction source, usually a Master, to a transaction sink, usually a Slave, optionally through one or more Hub layers.

You typically connect memory elements when assembling an address map from several components. Common cases include attaching multiple upstream initiators to a shared protocol endpoint, inserting a Hub that translates address windows, or connecting a custom bus component to a hardware-facing or network-facing Slave.

At a high level, the bus topology usually looks like this:

  1. Upstream Master objects issue transactions.

  2. Hub layers apply routing, offset, or splitting behavior.

  3. A protocol or hardware-facing Slave services the final transaction.

Operator Syntax And Helpers

Python

import pyrogue as pr

# Build a tree with two upstream Masters feeding two Hubs and then a
# protocol-facing Slave.
master_a >> hub_a >> srp
srp << hub_b << master_b

# Equivalent helper style
pr.busConnect(master_a, hub_a)
pr.busConnect(hub_a, srp)

The operator form is concise and reads naturally once the topology is familiar. The helper form is useful when code style or readability favors explicit calls.

C++

#include "rogue/Helpers.h"

// Build a tree with two upstream Masters feeding two Hubs and then a
// protocol-facing Slave.
*(*masterA >> hubA) >> srp;
*(*srp << hubB) << masterB;

// Equivalent helper style
rogueBusConnect(masterA, hubA);
rogueBusConnect(hubA, srp);

Addressing Model

One of the main jobs of a memory bus is to let each layer expose a clean local address window while still reaching the correct downstream absolute address. Hub and device layers often present relative upstream address spaces and map them to different downstream base offsets.

That means the bus can be organized in terms of logical subregions while still arriving at the correct physical register addresses underneath.

What To Explore Next

API Reference