4 Avoiding Memory Group Loops¶
How to lay out global memories across nodes so that a memory group never depends on itself, and what to do when Simplifier Manager reports a communication loop.
This guide builds on 1.14.5 Global Memories and applies to Simplifier Manager projects that use global memory groups.
4.1 What goes wrong¶
A node sends its global memories (GM) to the network in groups of 16. Each group has one age stamp, which is set when the group is sent. When another node reads a memory, it checks that age against the timeout.
If signals from a group travel through other nodes and come back into any memory of that same group, the group can only be fresh once its own data comes back fresh. At power-up nothing is fresh, so the group is never valid. It goes out timed out, the node reading it stays timed out too, and the system never gets past that state. Faster logic doesn't fix it, because the problem is a deadlock, not a delay.
| Term | Meaning |
|---|---|
| Group boundaries | GM01–GM16 is a node's first group, GM17–GM32 the second, and so on. |
| What counts | Only global memories (safe and diagnostic GM). Local memories never leave the node. |
| What makes a hop | A memory read on a different node that feeds, through any logic, a GM on that node. |
The rule
Following network hops from group to group, you must never get back to the group you started from. The memories involved don't have to be the same ones. Being in the same group is enough to close the loop.
4.2 Reading the error¶
Example error report from a project:
Communication loop: memory source A: +MC -Anlage L16 EIN affects itself or another memory
in the same memory group. The dependency runs:
N01.GM02 (A: +MC -Anlage L16 EIN) -> N03.GM05 (A: +AIR1 - Reset erforderlich)
N03.GM01 (A: +ROB1 - Not-Halt ok) -> N01.GM07 (Not-Halt lokal ok)
Each line is one network hop: the memory that was sent, then the memory it feeds on the node that reads it. Lines join at a shared group, not at a shared signal:
N01.GM02is read on N03 and feedsN03.GM05.N03.GM05andN03.GM01are both in N03's first group, so they share one age stamp.N03.GM01is read on N01 and feedsN01.GM07.N01.GM07andN01.GM02are both in N01's first group. That closes the loop.
N03's logic doesn't need to connect GM05 to GM01, and N01's logic doesn't need to connect GM02 to GM07. The loop exists because each pair is in the same group.
Figure 4.1: Group-level view of the example. Each group waits on the other to become fresh, so neither ever does.
4.3 Design approach: tier your groups¶
The most reliable way to avoid loops is to give every memory group a tier, and only let data move to a higher tier:
- Tier 0: groups driven only by the node's own inputs and logic. They read no memories from other nodes.
- Tier 1: groups that read tier-0 memories from other nodes.
- Tier 2: groups that read tier-0 or tier-1 memories from other nodes, and so on.
A memory may only be fed by remote memories from a lower tier
If you follow this, every hop goes up a tier, and the chain can never come back to where it started. Most systems need only tiers 0 and 1.
In practice, reserve a node's first group (GM01–GM16) for local status such as E-stop OK, guard closed, and button pressed. Put memories that combine results from other nodes in the second group (GM17–GM32). If a node has only one memory group, it needs a second one before you can separate them.
Figure 4.2: Tiered memory groups. Solid lines are network hops. Dashed lines are the node's own tier-0 signals feeding its tier-1 logic, which don't count as hops. Every arrow points right, so no loop can form.
Memory numbering conventions
The numbering advice in 1.14.5.1 Choosing Memory Numbers (for example, all E-stops on GM1) still applies within a tier. Assign local signals consistently inside GM01–GM16, and combined signals consistently inside GM17–GM32.
4.3.1 Handshakes across nodes¶
A two-way exchange (request → acknowledge, reset → confirmed) is fine if the reply goes into a different group from the request.
N03.GM01 reset request → N01 → N01.GM05 acknowledge → N03 → N03.GM03 reset done.
GM01 and GM03 are both in N03's first group.
N03.GM01 reset request → N01 → N01.GM17 acknowledge → N03 → N03.GM33 reset done.
The request is tier 0 and the acknowledge is tier 1. The result reads a tier-1 memory, so it goes in tier 2 (N03's third group).
A reply that uses another reply as input goes one tier higher. If a chain needs more tiers than the nodes have groups, simplify the chain. Often the node receiving the reply can do the logic itself, without sending the result back out.
4.4 Fixing a reported loop¶
- List the groups. For each line of the error, write down the group of both memories (memory number ÷ 16, rounded up).
- Find the break point. Pick one memory on the loop that receives a remote signal and shares a group with a memory that is sent on. In the example, that is
N01.GM07orN03.GM05. - Move it to a higher-tier group. For example, renumber
N01.GM07toN01.GM17, then update the memory references on other nodes that read it. - Compile again. One loop can hide another that shares a group, so repeat until the error list is clear.
4.5 What does not fix it¶
| Attempt | Result | Why |
|---|---|---|
| Inserting a Feedback loop block (Loop Gateway) | Still a loop | It delays the signal by one logic cycle. The group still waits on its own freshness, which is a deadlock, not a timing issue. |
| Adding timers or delays | Still a loop | Same reason: extra delay can't make a group fresh if its freshness depends on itself. |
| Increasing the timeout | Still a loop | The age never becomes valid, so no timeout is long enough. |
| Routing through local memories and references on the same node | Still a loop | A local memory is only another name for the signal. The check follows it. |
| Moving the memory to another number in the same 16 | Still a loop | Its group is unchanged, so the age stamp is the same. |
4.6 Checklist before downloading¶
- Every node's first group holds only memories driven by that node's own I/O and logic.
- Every memory fed by a memory reference from another node sits in a higher-tier group than the memory it reads.
- Replies in a handshake are in a different group from the request.
- No memory was moved "to fix it" within the same block of 16.
- Compiling shows no Communication loop errors.
When the check runs
The Communication loop check runs when the project is compiled. The error list reports each loop once, with its network hops in the order the signal travels.