mirror of
https://github.com/Stone-Red-Code/StoneRed.LogicSimulator.git
synced 2026-09-04 00:56:23 +02:00
Switch gate watchers to notify on input mask changes, add DivideByNCounter
This commit is contained in:
@@ -17,6 +17,7 @@ public sealed class CycleCircuitSimulator : SimulatorBase
|
||||
private int[] nextInputMasks = [];
|
||||
private Action<int[], int[], int[]> computeOutputs = (_, _, _) => { };
|
||||
private int[] previousOutputMasks = [];
|
||||
private int[] previousInputMasks = [];
|
||||
|
||||
/// <summary>
|
||||
/// Ensures internal storage arrays are properly sized for the current gate count.
|
||||
@@ -28,6 +29,7 @@ public sealed class CycleCircuitSimulator : SimulatorBase
|
||||
{
|
||||
nextInputMasks = new int[gateKinds.Count];
|
||||
previousOutputMasks = new int[gateKinds.Count];
|
||||
previousInputMasks = new int[gateKinds.Count];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +41,7 @@ public sealed class CycleCircuitSimulator : SimulatorBase
|
||||
base.Reset();
|
||||
Array.Clear(nextInputMasks);
|
||||
Array.Clear(previousOutputMasks);
|
||||
Array.Clear(previousInputMasks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -55,10 +58,14 @@ public sealed class CycleCircuitSimulator : SimulatorBase
|
||||
|
||||
(outputMasks, previousOutputMasks) = (previousOutputMasks, outputMasks);
|
||||
computeOutputs(inputMasks, outputMasks, sourceStates);
|
||||
if (hasAnyWatchers)
|
||||
{
|
||||
Array.Copy(inputMasks, previousInputMasks, inputMasks.Length);
|
||||
}
|
||||
PropagateAndSwap();
|
||||
if (hasAnyWatchers)
|
||||
{
|
||||
NotifyAllWatchers(previousOutputMasks);
|
||||
NotifyAllWatchers(previousInputMasks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,10 +143,14 @@ public sealed class CycleCircuitSimulator : SimulatorBase
|
||||
steps++;
|
||||
(outputMasks, previousOutputMasks) = (previousOutputMasks, outputMasks);
|
||||
computeOutputs(inputMasks, outputMasks, sourceStates);
|
||||
if (hasAnyWatchers)
|
||||
{
|
||||
Array.Copy(inputMasks, previousInputMasks, inputMasks.Length);
|
||||
}
|
||||
changed = PropagateAndSwapDetectChange();
|
||||
if (hasAnyWatchers)
|
||||
{
|
||||
NotifyAllWatchers(previousOutputMasks);
|
||||
NotifyAllWatchers(previousInputMasks);
|
||||
}
|
||||
}
|
||||
return !changed;
|
||||
|
||||
@@ -84,7 +84,6 @@ public sealed class EventCircuitSimulator : SimulatorBase
|
||||
if (outputMasks[gateId] != oldOutput)
|
||||
{
|
||||
Propagate(gateId);
|
||||
NotifyGateWatchers(gateId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,6 +102,10 @@ public sealed class EventCircuitSimulator : SimulatorBase
|
||||
if (oldBit != outVal)
|
||||
{
|
||||
inputMasks[toGate] ^= 1 << bit;
|
||||
if (hasAnyWatchers)
|
||||
{
|
||||
NotifyGateWatchers(toGate);
|
||||
}
|
||||
Enqueue(toGate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,11 +114,11 @@ public interface ICircuitSimulator
|
||||
bool TryRunUntilStable(int maxSteps, out int steps);
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to output changes on a specific gate.
|
||||
/// The callback is invoked whenever the gate's output value changes.
|
||||
/// Subscribes to input mask changes on a specific gate.
|
||||
/// The callback is invoked whenever the gate's input mask changes.
|
||||
/// </summary>
|
||||
/// <param name="gateId">The gate ID to watch.</param>
|
||||
/// <param name="callback">Action to invoke on change. Parameters are (gateId, newOutputMask).</param>
|
||||
/// <param name="callback">Action to invoke on change. Parameters are (gateId, newInputMask).</param>
|
||||
/// <returns>An <see cref="IDisposable"/> that unsubscribes the watcher when disposed.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when callback is null.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when gateId is invalid.</exception>
|
||||
|
||||
@@ -246,18 +246,18 @@ public abstract class SimulatorBase : ICircuitSimulator
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notifies all registered watchers of gates that changed between the previous and current output states.
|
||||
/// Notifies all registered watchers of gates that changed between the previous and current input states.
|
||||
/// </summary>
|
||||
/// <param name="previousOutputMasks">The output states from before the change.</param>
|
||||
protected void NotifyAllWatchers(int[] previousOutputMasks)
|
||||
/// <param name="previousInputMasks">The input states from before the change.</param>
|
||||
protected void NotifyAllWatchers(int[] previousInputMasks)
|
||||
{
|
||||
for (int i = 0; i < gatesWithWatchers.Length; i++)
|
||||
{
|
||||
int gateId = gatesWithWatchers[i];
|
||||
if (outputMasks[gateId] != previousOutputMasks[gateId])
|
||||
if (inputMasks[gateId] != previousInputMasks[gateId])
|
||||
{
|
||||
Action<int, int>[] callbacks = watcherCache[gateId];
|
||||
int val = outputMasks[gateId];
|
||||
int val = inputMasks[gateId];
|
||||
for (int j = 0; j < callbacks.Length; j++)
|
||||
{
|
||||
callbacks[j](gateId, val);
|
||||
@@ -267,7 +267,7 @@ public abstract class SimulatorBase : ICircuitSimulator
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notifies watchers of a specific gate that its output has changed.
|
||||
/// Notifies watchers of a specific gate that its input has changed.
|
||||
/// </summary>
|
||||
/// <param name="gateId">The ID of the gate that changed.</param>
|
||||
protected void NotifyGateWatchers(int gateId)
|
||||
@@ -283,7 +283,7 @@ public abstract class SimulatorBase : ICircuitSimulator
|
||||
return;
|
||||
}
|
||||
|
||||
int val = outputMasks[gateId];
|
||||
int val = inputMasks[gateId];
|
||||
for (int i = 0; i < callbacks.Length; i++)
|
||||
{
|
||||
callbacks[i](gateId, val);
|
||||
|
||||
Reference in New Issue
Block a user