diff --git a/src/main/java/de/neemann/digital/core/Model.java b/src/main/java/de/neemann/digital/core/Model.java index 59b032334..7de24b2ff 100644 --- a/src/main/java/de/neemann/digital/core/Model.java +++ b/src/main/java/de/neemann/digital/core/Model.java @@ -41,37 +41,41 @@ public class Model { public void doStep(boolean noise) throws NodeException { int counter = 0; - while (!nodesToUpdateNext.isEmpty()) { - version++; - // swap lists - ArrayList nl = nodesToUpdateNext; - nodesToUpdateNext = nodesToUpdateAct; - nodesToUpdateAct = nl; - - nodesToUpdateNext.clear(); - - if (noise) { - Collections.shuffle(nodesToUpdateAct); - for (Node n : nodesToUpdateAct) { - n.readInputs(); - n.writeOutputs(); - } - } else { - for (Node n : nodesToUpdateAct) { - n.readInputs(); - } - for (Node n : nodesToUpdateAct) { - n.writeOutputs(); - } - } + while (!doMicroStep(noise)) { + if (listener != null) + listener.needsUpdate(); if (counter++ > maxCounter) { throw new NodeException("seemsToOscillate"); } - if (listener != null) - listener.needsUpdate(); } } + public boolean doMicroStep(boolean noise) throws NodeException { + version++; + // swap lists + ArrayList nl = nodesToUpdateNext; + nodesToUpdateNext = nodesToUpdateAct; + nodesToUpdateAct = nl; + + nodesToUpdateNext.clear(); + + if (noise) { + Collections.shuffle(nodesToUpdateAct); + for (Node n : nodesToUpdateAct) { + n.readInputs(); + n.writeOutputs(); + } + } else { + for (Node n : nodesToUpdateAct) { + n.readInputs(); + } + for (Node n : nodesToUpdateAct) { + n.writeOutputs(); + } + } + return nodesToUpdateNext.isEmpty(); + } + public void init() throws NodeException { init(false); } diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index 24f39033b..ad481da78 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -3,6 +3,7 @@ package de.neemann.digital.gui; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; import com.thoughtworks.xstream.io.xml.StaxDriver; +import de.neemann.digital.core.Listener; import de.neemann.digital.core.Model; import de.neemann.digital.core.PartDescription; import de.neemann.digital.core.basic.*; @@ -121,14 +122,29 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { JMenu run = new JMenu("Run"); bar.add(run); + JCheckBox microStep = new JCheckBox("micro"); + ToolTipAction runModel = new ToolTipAction("Run") { @Override public void actionPerformed(ActionEvent e) { try { - ModelDescription m = new ModelDescription(circuitComponent.getCircuit()); - Model model = m.create(circuitComponent); - model.init(true); circuitComponent.setMode(CircuitComponent.Mode.running); + ModelDescription m = new ModelDescription(circuitComponent.getCircuit()); + Model model = m.createModel(circuitComponent); + if (microStep.isSelected()) { + model.setListener(new Listener() { + @Override + public void needsUpdate() { + circuitComponent.paintImmediately(circuitComponent.getVisibleRect()); + try { + Thread.sleep(2000); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + }); + } + model.init(true); } catch (Exception e1) { new ErrorMessage("error creating model").addCause(e1).show(Main.this); } @@ -142,6 +158,8 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { toolBar.add(partsMode.createJButton()); toolBar.add(wireMode.createJButton()); toolBar.add(selectionMode.createJButton()); + toolBar.add(runModel.createJButton()); + toolBar.add(microStep); toolBar.addSeparator(); insertHistory = new InsertHistory(toolBar); diff --git a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java index 09cb4f0a7..919975bd1 100644 --- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java @@ -75,6 +75,7 @@ public class CircuitComponent extends JComponent implements Listener { addMouseMotionListener(listener); addMouseListener(listener); requestFocusInWindow(); + circuit.clearState(); repaint(); } diff --git a/src/main/java/de/neemann/digital/gui/draw/model/ModelDescription.java b/src/main/java/de/neemann/digital/gui/draw/model/ModelDescription.java index 6d3f9afd8..fc1bbf14f 100644 --- a/src/main/java/de/neemann/digital/gui/draw/model/ModelDescription.java +++ b/src/main/java/de/neemann/digital/gui/draw/model/ModelDescription.java @@ -30,7 +30,7 @@ public class ModelDescription { } } - public Model create(Listener listener) throws PinException, NodeException { + public Model createModel(Listener listener) throws PinException, NodeException { for (Net n : netList) n.interconnect(); diff --git a/src/main/java/de/neemann/digital/gui/draw/parts/Circuit.java b/src/main/java/de/neemann/digital/gui/draw/parts/Circuit.java index cebb05af7..a49a4900b 100644 --- a/src/main/java/de/neemann/digital/gui/draw/parts/Circuit.java +++ b/src/main/java/de/neemann/digital/gui/draw/parts/Circuit.java @@ -105,4 +105,11 @@ public class Circuit implements Drawable { dots = WireConsistencyChecker.createDots(wires); return dots; } + + public void clearState() { + for (VisualPart vp : visualParts) + vp.setState(null, null, null); + for (Wire w : wires) + w.setValue(null); + } } diff --git a/src/main/java/de/neemann/digital/gui/draw/parts/VisualPart.java b/src/main/java/de/neemann/digital/gui/draw/parts/VisualPart.java index fc81b4ea3..a286229a0 100644 --- a/src/main/java/de/neemann/digital/gui/draw/parts/VisualPart.java +++ b/src/main/java/de/neemann/digital/gui/draw/parts/VisualPart.java @@ -132,7 +132,10 @@ public class VisualPart implements Drawable, Moveable { */ public void setState(State state, Listener listener, Model model) { this.state = state; - interactor = partDescription.getShape().applyStateMonitor(state, listener, model); + if (state == null) + interactor = null; + else + interactor = partDescription.getShape().applyStateMonitor(state, listener, model); } public void clicked(CircuitComponent cc, Vector pos) { diff --git a/src/main/java/de/neemann/digital/gui/draw/shapes/GenericShape.java b/src/main/java/de/neemann/digital/gui/draw/shapes/GenericShape.java index 69e398ddd..4c21a4587 100644 --- a/src/main/java/de/neemann/digital/gui/draw/shapes/GenericShape.java +++ b/src/main/java/de/neemann/digital/gui/draw/shapes/GenericShape.java @@ -76,21 +76,6 @@ public class GenericShape implements Shape { @Override public Interactor applyStateMonitor(State state, Listener listener, Model model) { - if (symmetric) { - state.getOutput(0).addListener(new Listener() { - public long lastValue = 0; - - @Override - public void needsUpdate() { - long value = state.getInput(0).getValue(); - if (lastValue != value) { - lastValue = value; - listener.needsUpdate(); - } - } - }); - - } return null; } @@ -99,9 +84,9 @@ public class GenericShape implements Shape { int max = Math.max(inputs, outputs); int height = (max - 1) * SIZE + SIZE2; - if (symmetric && state != null) { - graphic.drawText(new Vector(width * SIZE, 0), new Vector((width + 1) * SIZE, 0), Long.toString(state.getOutput(0).getValue())); - } +// if (symmetric && state != null) { +// graphic.drawText(new Vector(width * SIZE, 0), new Vector((width + 1) * SIZE, 0), Long.toString(state.getOutput(0).getValue())); +// } if (symmetric && ((inputs & 1) == 0)) height += SIZE;