package net.mograsim.logic.core.components;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
+import net.mograsim.logic.core.LogicObservable;
+import net.mograsim.logic.core.LogicObserver;
import net.mograsim.logic.core.timeline.Timeline;
import net.mograsim.logic.core.types.Bit;
import net.mograsim.logic.core.types.BitVector;
import net.mograsim.logic.core.wires.Wire.ReadEnd;
import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-public class BitDisplay extends BasicComponent
+public class BitDisplay extends BasicComponent implements LogicObservable
{
+ private Collection<LogicObserver> observers;
private final ReadEnd in;
private BitVector displayedValue;
public BitDisplay(Timeline timeline, ReadEnd in)
{
super(timeline, 1);
+ observers = new ArrayList<>();
this.in = in;
in.registerObserver(this);
compute();
protected void compute()
{
displayedValue = in.getValues();
+ notifyObservers();
}
public BitVector getDisplayedValue()
{
return List.of();
}
+
+ @Override
+ public void registerObserver(LogicObserver ob)
+ {
+ observers.add(ob);
+ }
+
+ @Override
+ public void deregisterObserver(LogicObserver ob)
+ {
+ observers.remove(ob);
+ }
+
+ @Override
+ public void notifyObservers()
+ {
+ observers.forEach(ob -> ob.update(this));
+ }
}
package net.mograsim.logic.core.components;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
+import net.mograsim.logic.core.LogicObservable;
+import net.mograsim.logic.core.LogicObserver;
import net.mograsim.logic.core.timeline.Timeline;
import net.mograsim.logic.core.types.Bit;
import net.mograsim.logic.core.wires.Wire.ReadEnd;
* @author Christian Femers
*
*/
-public class ManualSwitch extends Component
+public class ManualSwitch extends Component implements LogicObservable
{
+ private Collection<LogicObserver> observers;
private ReadWriteEnd output;
private boolean isOn;
public ManualSwitch(Timeline timeline, ReadWriteEnd output)
{
super(timeline);
+ observers = new ArrayList<>();
if (output.length() != 1)
throw new IllegalArgumentException("Switch output can be only a single wire");
this.output = output;
return;
this.isOn = isOn;
output.feedSignals(getValue());
+ notifyObservers();
}
public boolean isOn()
return List.of(output);
}
+ @Override
+ public void registerObserver(LogicObserver ob)
+ {
+ observers.add(ob);
+ }
+
+ @Override
+ public void deregisterObserver(LogicObserver ob)
+ {
+ observers.remove(ob);
+ }
+
+ @Override
+ public void notifyObservers()
+ {
+ observers.forEach(ob -> ob.update(this));
+ }
+
}
private final List<Consumer<TimelineEvent>> eventAddedListener;
+ public final LongSupplier stepByStepExec = () -> lastTimeUpdated;
+ public final LongSupplier realTimeExec = () -> System.currentTimeMillis();
+
+ /**
+ * Constructs a Timeline object. Per default the time function is set to step by step execution.
+ *
+ * @param initCapacity The initial capacity of the event queue.
+ */
public Timeline(int initCapacity)
{
events = new PriorityQueue<>(initCapacity);
-
eventAddedListener = new ArrayList<>();
- time = () -> lastTimeUpdated;
+ time = stepByStepExec;
}
/**
* @param timestamp exclusive
- * @return true if the first event is later than the timestamp
+ * @return <code>true</code> if the first event in queue is later than the given timestamp
*/
public BooleanSupplier laterThan(long timestamp)
{
return () -> timeCmp(events.peek().getTiming(), timestamp) > 0;
}
+ /**
+ * @return <code>true</code> if there is at least one event enqueued. <code>false</code> otherwise
+ */
public boolean hasNext()
{
return !events.isEmpty();
executeUntil(laterThan(first.getTiming()), -1);
}
+ /**
+ * Executes all events enqueued in the {@link Timeline}. Use very carefully! Events may generate new events, causing an infinite loop.
+ */
public void executeAll()
{
while (hasNext())
* <code>EXEC_UNTIL_CONDITION</code> if the condition was met
* <code>EXEC_UNTIL_EMPTY</code> if events were executed until the {@link Timeline} was empty
* @formatter:on
- * @author Christian Femers, Fabian Stemmler
*/
public ExecutionResult executeUntil(BooleanSupplier condition, long stopMillis)
{
return hasNext() ? ExecutionResult.EXEC_UNTIL_EMPTY : ExecutionResult.EXEC_UNTIL_CONDITION;
}
+ /**
+ * Sets the function, which defines the current simulation time at any time.
+ *
+ * @param time The return value of calling this function is the current simulation time.
+ */
public void setTimeFunction(LongSupplier time)
{
this.time = time;
}
+ /**
+ * Calculates the current simulation time.
+ *
+ * @return The simulation time as defined by the time function.
+ */
public long getSimulationTime()
{
return time.getAsLong();
}
+ /**
+ * Retrieves the timestamp of the next event.
+ *
+ * @return The timestamp of the next enqueued event, if the {@link Timeline} is not empty, -1 otherwise.
+ */
public long nextEventTime()
{
if (!hasNext())
return events.peek().getTiming();
}
+ /**
+ * Clears the {@link Timeline} of enqueued events.
+ */
public void reset()
{
events.clear();
lastTimeUpdated = 0;
}
+ /**
+ * Adds a listener, that is called when a {@link TimelineEvent} is added.
+ */
public void addEventAddedListener(Consumer<TimelineEvent> listener)
{
eventAddedListener.add(listener);
}
+ /**
+ * Removes the listener, if possible. It will no longer be called when a {@link TimelineEvent} is added.
+ */
public void removeEventAddedListener(Consumer<TimelineEvent> listener)
{
eventAddedListener.remove(listener);
}
}
- public static int timeCmp(long a, long b)
+ static int timeCmp(long a, long b)
{
return Long.signum(a - b);
}
private void notifyObservers()
{
- for (ReadEnd o : attached)
- o.update();
+ attached.forEach(r -> r.update());
}
/**
@Override
public void notifyObservers()
{
- for (LogicObserver ob : observers)
- ob.update(this);
+ observers.forEach(ob -> ob.update(this));
}
}
this.logicSwitch = logicSwitch;
this.end = end;
// TODO when ManualSwitch supports it, add listeners
- end.addObserver((i, o) -> callComponentLookChangedListeners());
+ end.registerObserver((i) -> callComponentLookChangedListeners());
}
@Override
public void setLogicModelBinding(ReadEnd end)
{
this.end = end;
- end.addObserver((i, o) -> callWireLookChangedListeners());
+ end.registerObserver((i) -> callWireLookChangedListeners());
}
public Pin getPin1()
public void setLogicModelBinding(ReadEnd end)
{
this.end = end;
- end.addObserver((i, o) -> callComponentLookChangedListeners());
+ end.registerObserver((i) -> callComponentLookChangedListeners());
}
public int getLogicWidth()