03Implementation
Split work across two rules
Problem
mkRuleOrder collects four values into accumulator and then hands the
finished total to result. Two rules divide that work: fill accumulates while
collecting is true and clears the flag once four values are taken, and drain
moves the finished total across and empties the accumulator.
Both rules currently carry the same condition, so they want the same cycles and
the same register. With the compiler used by Run, G0010 reports that fill
was treated as more urgent and G0021 reports that drain can never fire in the
generated schedule.
Give drain at the TODO a condition that becomes true after fill stops and
becomes false again after the completed result has been drained once.
Read the starter
Track the five registers in mkRuleOrder. fill accumulates four terms while
collecting is true. drained records whether the one allowed transfer already
happened. drain should copy the completed sum and clear the accumulator only
after collection ends.
Predict before editing
Both rules currently use the same condition and both write accumulator.
Predict the write conflict while collecting is true, then inspect what can
happen after it becomes false.
Trace the broken starter before editing:
| Cycle | total | emitted | filling | Meaning |
|---|---|---|---|---|
| 0 | 0 | 0 | 1 | fill can add 1 |
| 1 | 1 | 0 | 1 | next add 2 |
| 2 | 3 | 0 | 1 | next add 3 |
| 3 | 6 | 0 | 1 | next add 4 |
| 4 | 10 | 0 | 0 | collection ended; starter drain is now disabled |
| 5 and later | 10 | 0 | 0 | the completed total remains stranded |
Make the smallest change
- Accumulate all four values in the
fillrule, reaching a total of ten. - Move the finished total to
emittedfrom thedrainrule. - Keep the two rules from ever wanting the same cycle.
- Keep the emitted result stable after the single drain cycle.
Change only the readiness condition on drain. Do not add priority attributes
or state registers.
The readiness condition must establish two facts from the existing state: collection is no longer active, and the single drain opportunity has not been used. Derive the Boolean expression from those facts. Grading checks the resulting one-transaction behavior rather than one source spelling.
Run and explain
Run the repaired design and follow filling, total, and emitted. The
corrected conditions divide execution into collection and drain phases. Explain why the
rules no longer compete for accumulator and why drain sees the fully
committed sum.
With the repair, cycle 4 is the handoff observation (total = 10,
emitted = 0). drain then fires once. Cycle 5 observes total = 0 and
emitted = 10; later cycles keep that emitted result stable.
Completion check
fillowns every collection cycle.draincannot fire while collection is active.- The emitted value contains the complete accumulated result.
- The emitted value remains stable after the accumulator is empty.
- The guards divide collection and drain into disjoint phases.
Progressive hints and concept
Hint 1
fill runs while collecting holds. drain needs the opposite phase and an
unused one-shot token.
Hint 2
Combine the completed-collection state with the false state of drained.
Concept
The compiler builds a schedule from each rule's conditions and the state it
touches. Two rules conflict when each reads what the other writes; then only one
fires in that cycle. Two rules that merely write the same register can both fire,
with the later write in schedule order winning and bsc warning about the other.
Making the conditions mutually exclusive removes the conflict. The drained
state also closes the transfer after one firing, so the result is not
overwritten by a later empty accumulator.
Extension experiment
After the required solution works, initialize accumulator to eight instead of
zero. Predict the trace 8, 9, 11, 14, 18 and an emitted total of 18, then verify
that the one-shot drain still preserves that result on later cycles.