From 8a8f1260fc8faaa19a5e5024429b86b419f77bca Mon Sep 17 00:00:00 2001 From: hneemann Date: Tue, 9 Feb 2021 12:38:03 +0100 Subject: [PATCH] fixes #640 --- .../java/de/neemann/digital/core/Model.java | 34 ++++++++----- .../de/neemann/digital/core/ModelEvent.java | 4 ++ .../neemann/digital/core/ModelEventType.java | 8 ++- .../wiring/bus/BusModelStateObserver.java | 4 +- .../digital/integration/TestExamples.java | 2 +- src/test/resources/dig/test/burnError.dig | 50 +++++++++++++++++++ 6 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 src/test/resources/dig/test/burnError.dig diff --git a/src/main/java/de/neemann/digital/core/Model.java b/src/main/java/de/neemann/digital/core/Model.java index 83f79dd25..4040b6cac 100644 --- a/src/main/java/de/neemann/digital/core/Model.java +++ b/src/main/java/de/neemann/digital/core/Model.java @@ -277,20 +277,27 @@ public class Model implements Iterable, SyncAccess { synchronized private void stepWithCondition(boolean noise, StepCondition cond) { try { - int counter = 0; - while (cond.doNextMicroStep() && state != State.CLOSED) { - if (counter++ > MAX_LOOP_COUNTER) { - if (oscillatingNodes == null) - oscillatingNodes = new HashSet<>(); - if (counter > COLLECTING_LOOP_COUNTER) { - NodeException seemsToOscillate = new NodeException(Lang.get("err_seemsToOscillate")).addNodes(oscillatingNodes); - oscillatingNodes = null; - throw seemsToOscillate; - } else { - oscillatingNodes.addAll(nodesToUpdateNext); + if (cond.doNextMicroStep()) { + int counter = 0; + while (cond.doNextMicroStep() && state != State.CLOSED) { + if (counter++ > MAX_LOOP_COUNTER) { + if (oscillatingNodes == null) + oscillatingNodes = new HashSet<>(); + if (counter > COLLECTING_LOOP_COUNTER) { + NodeException seemsToOscillate = new NodeException(Lang.get("err_seemsToOscillate")).addNodes(oscillatingNodes); + oscillatingNodes = null; + throw seemsToOscillate; + } else { + oscillatingNodes.addAll(nodesToUpdateNext); + } } + doMicroStep(noise); } - doMicroStep(noise); + } else { + // if a calculation is initiated but there is nothing to do because there was + // no gate input change, perform a burn check to detect short circuits caused by + // directly connected inputs. + fireEvent(ModelEvent.CHECKBURN); } } catch (Exception e) { errorOccurred(e); @@ -473,7 +480,7 @@ public class Model implements Iterable, SyncAccess { private void addObserverForEvent(ModelStateObserver observer, ModelEventType event) { ArrayList obs = observers; - if (event == ModelEventType.STEP) { + if (event == ModelEventType.STEP || event == ModelEventType.CHECKBURN) { if (observersStep == null) observersStep = new ArrayList<>(); obs = observersStep; @@ -529,6 +536,7 @@ public class Model implements Iterable, SyncAccess { for (ModelStateObserver observer : observersMicroStep) observer.handleEvent(event); break; + case CHECKBURN: case STEP: if (observersStep != null) for (ModelStateObserver observer : observersStep) diff --git a/src/main/java/de/neemann/digital/core/ModelEvent.java b/src/main/java/de/neemann/digital/core/ModelEvent.java index 2ca211d94..5d038b848 100644 --- a/src/main/java/de/neemann/digital/core/ModelEvent.java +++ b/src/main/java/de/neemann/digital/core/ModelEvent.java @@ -27,6 +27,10 @@ public class ModelEvent { * Shorthand for a ModelEventType.STEP event */ public static final ModelEvent STEP = new ModelEvent(ModelEventType.STEP); + /** + * Shorthand for a ModelEventType.CHECKBURN event + */ + public static final ModelEvent CHECKBURN = new ModelEvent(ModelEventType.CHECKBURN); /** * Shorthand for a ModelEventType.MICROSTEP event */ diff --git a/src/main/java/de/neemann/digital/core/ModelEventType.java b/src/main/java/de/neemann/digital/core/ModelEventType.java index 19f554676..ccdaa9989 100644 --- a/src/main/java/de/neemann/digital/core/ModelEventType.java +++ b/src/main/java/de/neemann/digital/core/ModelEventType.java @@ -48,11 +48,17 @@ public enum ModelEventType { EXTERNALCHANGE, /** - * If fired if a micro step is calculated. + * Is fired if a micro step is calculated. * This means the aktual nodes are calculated, but not the effected nodes. */ MICROSTEP, + /** + * Is fired in case a burn check needs to be done without the change of a gate. + * Can happen if inputs are connected directly. + */ + CHECKBURN, + /** * Used to notify an error */ diff --git a/src/main/java/de/neemann/digital/core/wiring/bus/BusModelStateObserver.java b/src/main/java/de/neemann/digital/core/wiring/bus/BusModelStateObserver.java index 112327b65..0dc04d0c1 100644 --- a/src/main/java/de/neemann/digital/core/wiring/bus/BusModelStateObserver.java +++ b/src/main/java/de/neemann/digital/core/wiring/bus/BusModelStateObserver.java @@ -31,7 +31,7 @@ public final class BusModelStateObserver implements ModelStateObserverTyped { @Override public void handleEvent(ModelEvent event) { - if (event == ModelEvent.STEP && !busList.isEmpty()) { + if ((event == ModelEvent.STEP || event == ModelEvent.CHECKBURN) && !busList.isEmpty()) { for (AbstractBusHandler bus : busList) { bus.checkBurn(); } @@ -42,7 +42,7 @@ public final class BusModelStateObserver implements ModelStateObserverTyped { @Override public ModelEventType[] getEvents() { - return new ModelEventType[]{ModelEventType.STEP}; + return new ModelEventType[]{ModelEventType.STEP, ModelEventType.CHECKBURN}; } /** diff --git a/src/test/java/de/neemann/digital/integration/TestExamples.java b/src/test/java/de/neemann/digital/integration/TestExamples.java index a5764c70d..6a0a4fc84 100644 --- a/src/test/java/de/neemann/digital/integration/TestExamples.java +++ b/src/test/java/de/neemann/digital/integration/TestExamples.java @@ -51,7 +51,7 @@ public class TestExamples extends TestCase { */ public void testTestExamples() throws Exception { File examples = new File(Resources.getRoot(), "/dig/test"); - assertEquals(206, new FileScanner(this::check).scan(examples)); + assertEquals(207, new FileScanner(this::check).scan(examples)); assertEquals(192, testCasesInFiles); } diff --git a/src/test/resources/dig/test/burnError.dig b/src/test/resources/dig/test/burnError.dig new file mode 100644 index 000000000..f5360445b --- /dev/null +++ b/src/test/resources/dig/test/burnError.dig @@ -0,0 +1,50 @@ + + + 1 + + + + In + + + InDefault + + + + + + + In + + + + + Out + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file