mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-22 11:55:15 -04:00
first mostly working attempt of new modify logic
This commit is contained in:
parent
9eb1b23073
commit
b84a921f86
@ -8,6 +8,10 @@
|
||||
{{de 4-Bit Ripple-Carry addierer bestehend aus vier
|
||||
Volladdierern.}}</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>showDataGraphMicro</string>
|
||||
<boolean>true</boolean>
|
||||
</entry>
|
||||
</attributes>
|
||||
<visualElements>
|
||||
<visualElement>
|
||||
@ -692,4 +696,20 @@ end loop</dataString>
|
||||
<p2 x="140" y="0"/>
|
||||
</wire>
|
||||
</wires>
|
||||
<measurementOrdering>
|
||||
<string>C_-1</string>
|
||||
<string>A_0</string>
|
||||
<string>A_1</string>
|
||||
<string>A_2</string>
|
||||
<string>A_3</string>
|
||||
<string>B_0</string>
|
||||
<string>B_1</string>
|
||||
<string>B_2</string>
|
||||
<string>B_3</string>
|
||||
<string>S_0</string>
|
||||
<string>S_1</string>
|
||||
<string>S_2</string>
|
||||
<string>S_3</string>
|
||||
<string>C_3</string>
|
||||
</measurementOrdering>
|
||||
</circuit>
|
@ -209,7 +209,7 @@ public class Model implements Iterable<Node>, SyncAccess {
|
||||
* Closes the model.
|
||||
* A STOPPED event is fired.
|
||||
*/
|
||||
public void close() {
|
||||
public synchronized void close() {
|
||||
if (state != State.CLOSED) {
|
||||
state = State.CLOSED;
|
||||
int obs = observers.size();
|
||||
@ -463,7 +463,7 @@ public class Model implements Iterable<Node>, SyncAccess {
|
||||
* @param event the mandatory event
|
||||
* @param events more optional events
|
||||
*/
|
||||
public void addObserver(ModelStateObserver observer, ModelEventType event, ModelEventType... events) {
|
||||
public synchronized void addObserver(ModelStateObserver observer, ModelEventType event, ModelEventType... events) {
|
||||
addObserverForEvent(observer, event);
|
||||
for (ModelEventType ev : events)
|
||||
addObserverForEvent(observer, ev);
|
||||
@ -474,13 +474,12 @@ public class Model implements Iterable<Node>, SyncAccess {
|
||||
*
|
||||
* @param observer the observer to add
|
||||
*/
|
||||
public void addObserver(ModelStateObserverTyped observer) {
|
||||
public synchronized void addObserver(ModelStateObserverTyped observer) {
|
||||
for (ModelEventType ev : observer.getEvents())
|
||||
addObserverForEvent(observer, ev);
|
||||
}
|
||||
|
||||
|
||||
private void addObserverForEvent(ModelStateObserver observer, ModelEventType event) {
|
||||
private synchronized void addObserverForEvent(ModelStateObserver observer, ModelEventType event) {
|
||||
ArrayList<ModelStateObserver> obs = observers;
|
||||
if (event == ModelEventType.STEP || event == ModelEventType.CHECKBURN) {
|
||||
if (observersStep == null)
|
||||
@ -501,7 +500,7 @@ public class Model implements Iterable<Node>, SyncAccess {
|
||||
*
|
||||
* @param observer the observer to remove
|
||||
*/
|
||||
public void removeObserver(ModelStateObserver observer) {
|
||||
public synchronized void removeObserver(ModelStateObserver observer) {
|
||||
observers.remove(observer);
|
||||
if (observersStep != null)
|
||||
observersStep.remove(observer);
|
||||
@ -516,7 +515,7 @@ public class Model implements Iterable<Node>, SyncAccess {
|
||||
* @param <T> the type of the observer
|
||||
* @return the found observer or null if not present
|
||||
*/
|
||||
public <T extends ModelStateObserver> T getObserver(Class<T> observerClass) {
|
||||
public synchronized <T extends ModelStateObserver> T getObserver(Class<T> observerClass) {
|
||||
for (ModelStateObserver mso : observers)
|
||||
if (mso.getClass() == observerClass)
|
||||
return (T) mso;
|
||||
@ -908,10 +907,40 @@ public class Model implements Iterable<Node>, SyncAccess {
|
||||
synchronized (this) {
|
||||
run.run();
|
||||
}
|
||||
fireEvent(ModelEvent.EXTERNALCHANGE);
|
||||
fireEvent(ModelEvent.MICROSTEP); // record the external modification as a micro step!
|
||||
doStep();
|
||||
return run;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SyncAccess} instance to access the model.
|
||||
* If microStep is true, there is no foll step performed, in case of a user interaction.
|
||||
*
|
||||
* @param microStep if true no full step is calculated at a user interaction
|
||||
* @return the instance
|
||||
*/
|
||||
public SyncAccess createSync(boolean microStep) {
|
||||
if (microStep) {
|
||||
return new SyncAccess() {
|
||||
@Override
|
||||
public <A extends Runnable> A modify(A run) {
|
||||
synchronized (this) {
|
||||
run.run();
|
||||
}
|
||||
fireEvent(ModelEvent.MICROSTEP); // record the external modification as a micro step!
|
||||
return run;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A extends Runnable> A read(A run) {
|
||||
return Model.this.read(run);
|
||||
}
|
||||
};
|
||||
} else
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <A extends Runnable> A read(A run) {
|
||||
synchronized (this) {
|
||||
|
@ -43,10 +43,6 @@ public class ModelEvent {
|
||||
* Shorthand for a ModelEventType.BREAK event
|
||||
*/
|
||||
public static final ModelEvent BREAK = new ModelEvent(ModelEventType.BREAK);
|
||||
/**
|
||||
* Shorthand for a ModelEventType.EXTERNALCHANGE event
|
||||
*/
|
||||
public static final ModelEvent EXTERNALCHANGE = new ModelEvent(ModelEventType.EXTERNALCHANGE);
|
||||
|
||||
private final ModelEventType type;
|
||||
private Exception cause;
|
||||
|
@ -42,11 +42,6 @@ public enum ModelEventType {
|
||||
*/
|
||||
BREAK,
|
||||
|
||||
/**
|
||||
* Here was a manual change to the model by the user.
|
||||
*/
|
||||
EXTERNALCHANGE,
|
||||
|
||||
/**
|
||||
* Is fired if a micro step is calculated.
|
||||
* This means the aktual nodes are calculated, but not the effected nodes.
|
||||
|
@ -57,7 +57,7 @@ public class DataPlotter implements Drawable {
|
||||
* Fits the data in the visible area
|
||||
*/
|
||||
public void fitInside() {
|
||||
modelSync.modify(() -> size = ((double) (width - textWidth)) / dataOriginal.getRows());
|
||||
modelSync.read(() -> size = ((double) (width - textWidth)) / dataOriginal.getRows());
|
||||
offset = 0;
|
||||
manualScaling = false;
|
||||
}
|
||||
|
@ -97,7 +97,6 @@ public class RealTimeClock implements ModelStateObserverTyped {
|
||||
frequencyCalculator = null;
|
||||
timer = executor.scheduleAtFixedRate(() -> {
|
||||
model.modify(() -> output.setValue(1 - output.getValue()));
|
||||
model.doStep();
|
||||
if (frequencyCalculator != null)
|
||||
frequencyCalculator.calc();
|
||||
}, delay, delay, TimeUnit.MICROSECONDS);
|
||||
@ -123,7 +122,6 @@ public class RealTimeClock implements ModelStateObserverTyped {
|
||||
FrequencyCalculator frequencyCalculator = new FrequencyCalculator(status, frequency);
|
||||
while (!Thread.interrupted()) {
|
||||
model.modify(() -> output.setValue(1 - output.getValue()));
|
||||
model.doStep();
|
||||
frequencyCalculator.calc();
|
||||
}
|
||||
});
|
||||
|
@ -1382,7 +1382,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
|
||||
private void clearModelDescription() {
|
||||
if (model != null)
|
||||
model.modify(() -> model.close());
|
||||
model.close();
|
||||
|
||||
modelCreator = null;
|
||||
model = null;
|
||||
@ -1397,11 +1397,9 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
modelCreator = new ModelCreator(circuitComponent.getCircuit(), library);
|
||||
|
||||
if (model != null) {
|
||||
model.modify(() -> {
|
||||
ModelClosedObserver mco = model.getObserver(ModelClosedObserver.class);
|
||||
if (mco != null) mco.setClosedByRestart(true);
|
||||
model.close();
|
||||
});
|
||||
ModelClosedObserver mco = model.getObserver(ModelClosedObserver.class);
|
||||
if (mco != null) mco.setClosedByRestart(true);
|
||||
model.close();
|
||||
circuitComponent.getCircuit().clearState();
|
||||
model = null;
|
||||
}
|
||||
@ -1448,7 +1446,8 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
}
|
||||
}
|
||||
|
||||
circuitComponent.setModeAndReset(true, model);
|
||||
circuitComponent.setModeAndReset(true,
|
||||
model.createSync(updateEvent == ModelEventType.MICROSTEP));
|
||||
if (circuitComponent.getCircuit().getAttributes().get(Keys.IS_GENERIC))
|
||||
circuitComponent.setCopy(modelCreator.getCircuit());
|
||||
|
||||
@ -1456,12 +1455,12 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
CircuitModifierPostClosed cmpc = new CircuitModifierPostClosed(
|
||||
modification -> SwingUtilities.invokeLater(() -> circuitComponent.modify(modification)));
|
||||
modelCreator.connectToGui(cmpc);
|
||||
model.addObserver(cmpc);
|
||||
this.model.addObserver(cmpc);
|
||||
|
||||
handleKeyboardComponents();
|
||||
|
||||
doMicroStep.setEnabled(false);
|
||||
if (!realTimeClockRunning && model.isRunToBreakAllowed()) {
|
||||
if (!realTimeClockRunning && this.model.isRunToBreakAllowed()) {
|
||||
if (updateEvent == ModelEventType.MICROSTEP)
|
||||
runToBreakMicroAction.setEnabled(true);
|
||||
else
|
||||
@ -1478,30 +1477,30 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
showMeasurementGraph(ModelEventType.MICROSTEP);
|
||||
|
||||
if (modelModifier != null)
|
||||
modelModifier.preInit(model);
|
||||
modelModifier.preInit(this.model);
|
||||
else {
|
||||
if (settings.get(Keys.PRELOAD_PROGRAM)) {
|
||||
File romHex = new FileLocator(settings.get(Keys.PROGRAM_TO_PRELOAD))
|
||||
.setupWithMain(this)
|
||||
.locate();
|
||||
new ProgramMemoryLoader(romHex)
|
||||
.preInit(model);
|
||||
.preInit(this.model);
|
||||
}
|
||||
}
|
||||
|
||||
if (updateEvent == ModelEventType.MICROSTEP) {
|
||||
checkMicroStepActions(model);
|
||||
model.addObserver(new MicroStepObserver(model, modelCreator));
|
||||
checkMicroStepActions(this.model);
|
||||
this.model.addObserver(new UpdateViewMicroStepObserver(this.model, modelCreator));
|
||||
} else if (updateEvent == ModelEventType.STEP) {
|
||||
if (maxFrequency <= 50)
|
||||
model.addObserver(new FullStepObserver(model));
|
||||
this.model.addObserver(new UpdateViewAtEventObserver());
|
||||
else
|
||||
model.addObserver(new FastObserver());
|
||||
this.model.addObserver(new UpdateViewPeriodicObserver());
|
||||
}
|
||||
|
||||
model.addObserver(new ModelClosedObserver());
|
||||
this.model.addObserver(new ModelClosedObserver());
|
||||
|
||||
model.init();
|
||||
this.model.init();
|
||||
|
||||
} catch (NodeException | PinException | RuntimeException | ElementNotFoundException e) {
|
||||
if (model != null)
|
||||
@ -1736,20 +1735,15 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
/**
|
||||
* Updates the graphic at every modification.
|
||||
*/
|
||||
private class FullStepObserver implements ModelStateObserverTyped {
|
||||
private final Model model;
|
||||
|
||||
FullStepObserver(Model model) {
|
||||
this.model = model;
|
||||
private class UpdateViewAtEventObserver implements ModelStateObserverTyped {
|
||||
UpdateViewAtEventObserver() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(ModelEvent event) {
|
||||
switch (event.getType()) {
|
||||
case EXTERNALCHANGE:
|
||||
model.doStep();
|
||||
circuitComponent.graphicHasChanged();
|
||||
break;
|
||||
case CHECKBURN:
|
||||
case STEP:
|
||||
case BREAK:
|
||||
circuitComponent.graphicHasChanged();
|
||||
break;
|
||||
@ -1758,17 +1752,17 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
|
||||
@Override
|
||||
public ModelEventType[] getEvents() {
|
||||
return new ModelEventType[]{ModelEventType.EXTERNALCHANGE, ModelEventType.BREAK};
|
||||
return new ModelEventType[]{ModelEventType.CHECKBURN, ModelEventType.STEP, ModelEventType.BREAK};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the graphic at every 100ms
|
||||
*/
|
||||
private final class FastObserver implements ModelStateObserverTyped {
|
||||
private final class UpdateViewPeriodicObserver implements ModelStateObserverTyped {
|
||||
private final Timer timer;
|
||||
|
||||
private FastObserver() {
|
||||
private UpdateViewPeriodicObserver() {
|
||||
timer = new Timer(100, actionEvent -> circuitComponent.graphicHasChanged());
|
||||
}
|
||||
|
||||
@ -1795,11 +1789,11 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
/**
|
||||
* Updates the graphic at every micro step
|
||||
*/
|
||||
private final class MicroStepObserver implements ModelStateObserverTyped {
|
||||
private final class UpdateViewMicroStepObserver implements ModelStateObserverTyped {
|
||||
private final Model model;
|
||||
private final ModelCreator modelCreator;
|
||||
|
||||
private MicroStepObserver(Model model, ModelCreator modelCreator) {
|
||||
private UpdateViewMicroStepObserver(Model model, ModelCreator modelCreator) {
|
||||
this.model = model;
|
||||
this.modelCreator = modelCreator;
|
||||
}
|
||||
@ -1807,7 +1801,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
@Override
|
||||
public void handleEvent(ModelEvent event) {
|
||||
switch (event.getType()) {
|
||||
case EXTERNALCHANGE:
|
||||
case CHECKBURN:
|
||||
case MICROSTEP:
|
||||
case BREAK:
|
||||
if (!realTimeClockRunning) {
|
||||
@ -1823,7 +1817,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
|
||||
@Override
|
||||
public ModelEventType[] getEvents() {
|
||||
return new ModelEventType[]{ModelEventType.EXTERNALCHANGE, ModelEventType.MICROSTEP, ModelEventType.BREAK};
|
||||
return new ModelEventType[]{ModelEventType.CHECKBURN, ModelEventType.MICROSTEP, ModelEventType.BREAK};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1961,12 +1955,9 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
||||
if (cl.size() == 1) {
|
||||
ObservableValue clkVal = cl.get(0).getClockOutput();
|
||||
model.modify(() -> clkVal.setBool(!clkVal.getBool()));
|
||||
model.doStep();
|
||||
if (model != null) {
|
||||
if (clkVal.getBool() && model.isRunning()) {
|
||||
if (clkVal.getBool() && model.isRunning())
|
||||
model.modify(() -> clkVal.setBool(!clkVal.getBool()));
|
||||
model.doStep();
|
||||
}
|
||||
addressPicker.getProgramROMAddress(model);
|
||||
}
|
||||
}
|
||||
|
@ -60,12 +60,12 @@ public class ProbeDialog extends JDialog implements ModelStateObserverTyped {
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowOpened(WindowEvent e) {
|
||||
model.modify(() -> model.addObserver(ProbeDialog.this));
|
||||
model.addObserver(ProbeDialog.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
model.modify(() -> model.removeObserver(ProbeDialog.this));
|
||||
model.removeObserver(ProbeDialog.this);
|
||||
}
|
||||
});
|
||||
|
||||
@ -109,7 +109,7 @@ public class ProbeDialog extends JDialog implements ModelStateObserverTyped {
|
||||
|
||||
@Override
|
||||
public void handleEvent(ModelEvent event) {
|
||||
if (event.getType() == type || event == ModelEvent.EXTERNALCHANGE) {
|
||||
if (event.getType() == type || event == ModelEvent.CHECKBURN) {
|
||||
if (tableUpdateEnable) {
|
||||
if (paintPending.compareAndSet(false, true)) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
@ -133,7 +133,7 @@ public class ProbeDialog extends JDialog implements ModelStateObserverTyped {
|
||||
|
||||
@Override
|
||||
public ModelEventType[] getEvents() {
|
||||
return new ModelEventType[]{type, ModelEventType.EXTERNALCHANGE, ModelEventType.FASTRUN, ModelEventType.BREAK, ModelEventType.CLOSED};
|
||||
return new ModelEventType[]{type, ModelEventType.CHECKBURN, ModelEventType.FASTRUN, ModelEventType.BREAK, ModelEventType.CLOSED};
|
||||
}
|
||||
|
||||
private static class SignalTableModel implements TableModel {
|
||||
|
@ -109,11 +109,11 @@ public final class SingleValueDialog extends JDialog implements ModelStateObserv
|
||||
|
||||
JPanel checkBoxPanel = createCheckBoxPanel(editValue);
|
||||
|
||||
model.modify(() -> model.addObserver(this));
|
||||
model.addObserver(this);
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosed(WindowEvent windowEvent) {
|
||||
model.modify(() -> model.removeObserver(SingleValueDialog.this));
|
||||
model.removeObserver(SingleValueDialog.this);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -78,12 +78,12 @@ public class GraphDialog extends JDialog implements Observer {
|
||||
graphDialog.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowOpened(WindowEvent e) {
|
||||
model.modify(() -> model.addObserver(valueTableObserver));
|
||||
model.addObserver(valueTableObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
model.modify(() -> model.removeObserver(valueTableObserver));
|
||||
model.removeObserver(valueTableObserver);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -167,7 +167,7 @@ public class ScopeTrigger extends Node implements Element {
|
||||
graphDialog.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
model.modify(() -> model.removeObserver(scopeModelStateObserver));
|
||||
model.removeObserver(scopeModelStateObserver);
|
||||
}
|
||||
});
|
||||
graphDialog.setVisible(true);
|
||||
|
@ -24,8 +24,6 @@ public class ValueTableObserver implements ModelStateObserverTyped {
|
||||
private final ModelEventType type;
|
||||
private final ArrayList<Signal> signals;
|
||||
|
||||
private Value[] manualSample;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
@ -51,18 +49,7 @@ public class ValueTableObserver implements ModelStateObserverTyped {
|
||||
if (event == ModelEvent.STARTED)
|
||||
logData.clear();
|
||||
|
||||
if (event == ModelEvent.EXTERNALCHANGE && type == ModelEventType.MICROSTEP) {
|
||||
if (manualSample == null)
|
||||
manualSample = new Value[logData.getColumns()];
|
||||
for (int i = 0; i < logData.getColumns(); i++)
|
||||
manualSample[i] = new Value(signals.get(i).getValue());
|
||||
}
|
||||
|
||||
if (event.getType() == type) {
|
||||
if (manualSample != null) {
|
||||
logData.add(new TestRow(manualSample));
|
||||
manualSample = null;
|
||||
}
|
||||
Value[] row = new Value[logData.getColumns()];
|
||||
for (int i = 0; i < logData.getColumns(); i++)
|
||||
row[i] = new Value(signals.get(i).getValue());
|
||||
@ -72,7 +59,7 @@ public class ValueTableObserver implements ModelStateObserverTyped {
|
||||
|
||||
@Override
|
||||
public ModelEventType[] getEvents() {
|
||||
return new ModelEventType[]{type, ModelEventType.STARTED, ModelEventType.EXTERNALCHANGE};
|
||||
return new ModelEventType[]{type, ModelEventType.STARTED};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -228,12 +228,12 @@ public class InitialTutorial extends JDialog implements CircuitComponent.Tutoria
|
||||
|
||||
@Override
|
||||
public ModelEventType[] getEvents() {
|
||||
return new ModelEventType[]{ModelEventType.EXTERNALCHANGE};
|
||||
return new ModelEventType[]{ModelEventType.STEP};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(ModelEvent event) {
|
||||
if (event == ModelEvent.EXTERNALCHANGE)
|
||||
if (event == ModelEvent.STEP)
|
||||
modified(null);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user