From 6711cfe4da20989bdf10214add20f2acfb89f0bd Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 28 Nov 2020 20:23:23 +0100 Subject: [PATCH 1/4] allows to use measurement values as signals in a test case --- .../java/de/neemann/digital/core/Model.java | 17 ++++++++++++++++- .../java/de/neemann/digital/core/Signal.java | 18 ++++++++++++++++++ .../digital/core/flipflops/FlipflopBit.java | 2 +- .../digital/core/flipflops/FlipflopD.java | 2 +- .../java/de/neemann/digital/core/io/Probe.java | 2 +- .../neemann/digital/core/memory/Counter.java | 2 +- .../digital/core/memory/CounterPreset.java | 2 +- .../neemann/digital/core/memory/Register.java | 2 +- .../neemann/digital/testing/TestExecutor.java | 2 +- .../digital/testing/parser/Context.java | 2 +- .../neemann/digital/testing/parser/Parser.java | 7 ++++++- 11 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/main/java/de/neemann/digital/core/Model.java b/src/main/java/de/neemann/digital/core/Model.java index b93573a06..83f79dd25 100644 --- a/src/main/java/de/neemann/digital/core/Model.java +++ b/src/main/java/de/neemann/digital/core/Model.java @@ -66,6 +66,7 @@ public class Model implements Iterable, SyncAccess { private final ArrayList signals; private final ArrayList inputs; private final ArrayList outputs; + private final ArrayList testOutputs; private final ArrayList nodes; private ArrayList nodesToUpdateAct; @@ -92,6 +93,7 @@ public class Model implements Iterable, SyncAccess { this.buttonsToMap = new HashMap<>(); this.signals = new ArrayList<>(); this.outputs = new ArrayList<>(); + this.testOutputs = new ArrayList<>(); this.inputs = new ArrayList<>(); this.nodes = new ArrayList<>(); this.nodesToUpdateAct = new ArrayList<>(); @@ -586,8 +588,13 @@ public class Model implements Iterable, SyncAccess { * @param signal the signal */ public void addSignal(Signal signal) { - if (signal.isValid()) + if (signal.isValid()) { + if (signals.contains(signal)) + invalidSignal = signal; signals.add(signal); + if (signal.isTestOutput()) + testOutputs.add(signal); + } } /** @@ -623,6 +630,7 @@ public class Model implements Iterable, SyncAccess { invalidSignal = signal; signals.add(signal); outputs.add(signal); + testOutputs.add(signal); } else invalidSignal = signal; } @@ -649,6 +657,13 @@ public class Model implements Iterable, SyncAccess { return outputs; } + /** + * @return the models outputs + */ + public ArrayList getTestOutputs() { + return testOutputs; + } + /** * @return all registered signals */ diff --git a/src/main/java/de/neemann/digital/core/Signal.java b/src/main/java/de/neemann/digital/core/Signal.java index 456e43f7d..b56dc7656 100644 --- a/src/main/java/de/neemann/digital/core/Signal.java +++ b/src/main/java/de/neemann/digital/core/Signal.java @@ -16,6 +16,7 @@ public final class Signal implements Comparable { private String pinNumber; private ObservableValue bidirectionalReader; private boolean showInGraph; + private boolean testOutput; /** * Creates a new Instance @@ -60,6 +61,23 @@ public final class Signal implements Comparable { return showInGraph; } + /** + * Makes this signal to a test output signal + * + * @return this for chained calls + */ + public Signal setTestOutput() { + testOutput = true; + return this; + } + + /** + * @return true if this signal is a test output + */ + public boolean isTestOutput() { + return testOutput; + } + /** * @return the name */ diff --git a/src/main/java/de/neemann/digital/core/flipflops/FlipflopBit.java b/src/main/java/de/neemann/digital/core/flipflops/FlipflopBit.java index 43fe5bbcf..b2b81d797 100644 --- a/src/main/java/de/neemann/digital/core/flipflops/FlipflopBit.java +++ b/src/main/java/de/neemann/digital/core/flipflops/FlipflopBit.java @@ -86,7 +86,7 @@ abstract class FlipflopBit extends Node implements Element { out = v != 0; q.setBool(out); qn.setBool(!out); - })); + }).setTestOutput()); } void setOut(boolean out) { diff --git a/src/main/java/de/neemann/digital/core/flipflops/FlipflopD.java b/src/main/java/de/neemann/digital/core/flipflops/FlipflopD.java index 5dfc900ee..da4340bd5 100644 --- a/src/main/java/de/neemann/digital/core/flipflops/FlipflopD.java +++ b/src/main/java/de/neemann/digital/core/flipflops/FlipflopD.java @@ -120,7 +120,7 @@ public class FlipflopD extends Node implements Element, Countable { value = v; q.setValue(value); qn.setValue(~value); - })); + }).setTestOutput()); } /** diff --git a/src/main/java/de/neemann/digital/core/io/Probe.java b/src/main/java/de/neemann/digital/core/io/Probe.java index 9465f9682..fbcd0da9d 100644 --- a/src/main/java/de/neemann/digital/core/io/Probe.java +++ b/src/main/java/de/neemann/digital/core/io/Probe.java @@ -56,7 +56,7 @@ public class Probe implements Element { @Override public void registerNodes(Model model) { - model.addOutput(new Signal(label, value).setShowInGraph(showInGraph).setFormat(format)); + model.addSignal(new Signal(label, value).setShowInGraph(showInGraph).setFormat(format).setTestOutput()); model.registerGlobalValue(label, value); } diff --git a/src/main/java/de/neemann/digital/core/memory/Counter.java b/src/main/java/de/neemann/digital/core/memory/Counter.java index c3ef06ae4..af11f6df6 100644 --- a/src/main/java/de/neemann/digital/core/memory/Counter.java +++ b/src/main/java/de/neemann/digital/core/memory/Counter.java @@ -105,7 +105,7 @@ public class Counter extends Node implements Element, ProgramCounter { boolean o = (counter == maxValue) && enable.getBool(); out.setValue(counter); ovf.setBool(o); - })); + }).setTestOutput()); } @Override diff --git a/src/main/java/de/neemann/digital/core/memory/CounterPreset.java b/src/main/java/de/neemann/digital/core/memory/CounterPreset.java index fc307359f..8132d67f7 100644 --- a/src/main/java/de/neemann/digital/core/memory/CounterPreset.java +++ b/src/main/java/de/neemann/digital/core/memory/CounterPreset.java @@ -146,7 +146,7 @@ public class CounterPreset extends Node implements Element, ProgramCounter { boolean o = getOvfValue(counter, dir.getBool(), enable.getBool()); out.setValue(counter); ovf.setBool(o); - })); + }).setTestOutput()); } @Override diff --git a/src/main/java/de/neemann/digital/core/memory/Register.java b/src/main/java/de/neemann/digital/core/memory/Register.java index 7443031ac..4c74be678 100644 --- a/src/main/java/de/neemann/digital/core/memory/Register.java +++ b/src/main/java/de/neemann/digital/core/memory/Register.java @@ -90,7 +90,7 @@ public class Register extends Node implements Element, Countable, ProgramCounter model.addSignal(new Signal(label, q, (v, z) -> { value = v; q.setValue(value); - })); + }).setTestOutput()); } @Override diff --git a/src/main/java/de/neemann/digital/testing/TestExecutor.java b/src/main/java/de/neemann/digital/testing/TestExecutor.java index 1fa721212..3504dc810 100644 --- a/src/main/java/de/neemann/digital/testing/TestExecutor.java +++ b/src/main/java/de/neemann/digital/testing/TestExecutor.java @@ -119,7 +119,7 @@ public class TestExecutor { } } - for (Signal s : model.getOutputs()) { + for (Signal s : model.getTestOutputs()) { final int index = getIndexOf(s.getName()); if (index >= 0) { outputs.add(new TestSignal(index, s.getValue())); diff --git a/src/main/java/de/neemann/digital/testing/parser/Context.java b/src/main/java/de/neemann/digital/testing/parser/Context.java index 25e976161..dff59bad4 100644 --- a/src/main/java/de/neemann/digital/testing/parser/Context.java +++ b/src/main/java/de/neemann/digital/testing/parser/Context.java @@ -49,7 +49,7 @@ public class Context { if (model != null) { // inputs are not supported because there are cases where values // are evaluated and model inputs are not set! - for (Signal s : model.getOutputs()) + for (Signal s : model.getTestOutputs()) if (s.getName().equals(name)) return s.getValue().getValue(); } diff --git a/src/main/java/de/neemann/digital/testing/parser/Parser.java b/src/main/java/de/neemann/digital/testing/parser/Parser.java index 5515fa60c..847c4f95c 100644 --- a/src/main/java/de/neemann/digital/testing/parser/Parser.java +++ b/src/main/java/de/neemann/digital/testing/parser/Parser.java @@ -115,10 +115,15 @@ public class Parser { expect(Tokenizer.Token.IDENT); final String sName = tok.getIdent(); expect(Tokenizer.Token.EQUAL); + int sign = 1; + if (tok.peek() == Tokenizer.Token.SUB) { + tok.consume(); + sign = -1; + } expect(Tokenizer.Token.NUMBER); long n = convToLong(tok.getIdent()); expect(Tokenizer.Token.SEMICOLON); - signalInitMap.put(sName, n); + signalInitMap.put(sName, sign * n); break; case PROGRAM: tok.consume(); From e986b303832607ee2e5d5999684a76bef6ffb581 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 28 Nov 2020 20:31:37 +0100 Subject: [PATCH 2/4] updates a test circuit --- src/test/resources/dig/test/programTestSignal.dig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/resources/dig/test/programTestSignal.dig b/src/test/resources/dig/test/programTestSignal.dig index b00217520..123a56221 100644 --- a/src/test/resources/dig/test/programTestSignal.dig +++ b/src/test/resources/dig/test/programTestSignal.dig @@ -13,11 +13,11 @@ Testdata - en Out + en Out R init R=1; -0 1 +0 1 1 @@ -100,11 +100,11 @@ init R=1; Testdata - en Out + en Out R init R=7; -0 7 +0 7 7 From 084459f8a1b3ec5fd077fd76878efb9bb3fbba8a Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 29 Nov 2020 08:54:58 +0100 Subject: [PATCH 3/4] allows to init ram in test cases --- .../digital/testing/TestCaseDescription.java | 28 +--- .../neemann/digital/testing/TestExecutor.java | 23 +--- .../testing/parser/ModelInitializer.java | 120 ++++++++++++++++++ .../digital/testing/parser/Parser.java | 30 ++--- .../digital/testing/parser/Tokenizer.java | 3 +- src/main/resources/lang/lang_de.xml | 2 + src/main/resources/lang/lang_en.xml | 2 + .../testing/parser/ModelInitializerTest.java | 87 +++++++++++++ .../digital/testing/parser/ParserTest.java | 22 +--- 9 files changed, 240 insertions(+), 77 deletions(-) create mode 100644 src/main/java/de/neemann/digital/testing/parser/ModelInitializer.java create mode 100644 src/test/java/de/neemann/digital/testing/parser/ModelInitializerTest.java diff --git a/src/main/java/de/neemann/digital/testing/TestCaseDescription.java b/src/main/java/de/neemann/digital/testing/TestCaseDescription.java index 5e615db7a..03e89f944 100644 --- a/src/main/java/de/neemann/digital/testing/TestCaseDescription.java +++ b/src/main/java/de/neemann/digital/testing/TestCaseDescription.java @@ -5,16 +5,11 @@ */ package de.neemann.digital.testing; -import de.neemann.digital.core.memory.DataField; import de.neemann.digital.lang.Lang; -import de.neemann.digital.testing.parser.LineEmitter; -import de.neemann.digital.testing.parser.Parser; -import de.neemann.digital.testing.parser.ParserException; -import de.neemann.digital.testing.parser.VirtualSignal; +import de.neemann.digital.testing.parser.*; import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; /** * The test data. @@ -24,8 +19,7 @@ public class TestCaseDescription { private transient LineEmitter lines; private transient ArrayList names; private transient ArrayList virtualSignals; - private transient DataField program; - private transient HashMap signalInit; + private transient ModelInitializer modelInitializer; /** @@ -78,8 +72,7 @@ public class TestCaseDescription { lines = tdp.getLines(); names = tdp.getNames(); virtualSignals = tdp.getVirtualSignals(); - program = tdp.getProgram(); - signalInit = tdp.getSignalInit(); + modelInitializer = tdp.getModelInitializer(); } /** @@ -110,21 +103,12 @@ public class TestCaseDescription { } /** - * @return the program data or null if not available + * @return the model initializer * @throws TestingDataException TestingDataException */ - public DataField getProgram() throws TestingDataException { + public ModelInitializer getModelInitializer() throws TestingDataException { check(); - return program; - } - - /** - * @return the signal init values - * @throws TestingDataException TestingDataException - */ - public HashMap getSignalInit() throws TestingDataException { - check(); - return signalInit; + return modelInitializer; } @Override diff --git a/src/main/java/de/neemann/digital/testing/TestExecutor.java b/src/main/java/de/neemann/digital/testing/TestExecutor.java index 3504dc810..2ed548c56 100644 --- a/src/main/java/de/neemann/digital/testing/TestExecutor.java +++ b/src/main/java/de/neemann/digital/testing/TestExecutor.java @@ -7,7 +7,6 @@ package de.neemann.digital.testing; import de.neemann.digital.core.*; import de.neemann.digital.core.element.Keys; -import de.neemann.digital.core.memory.ProgramMemory; import de.neemann.digital.core.wiring.Clock; import de.neemann.digital.data.Value; import de.neemann.digital.draw.elements.Circuit; @@ -21,8 +20,6 @@ import de.neemann.digital.testing.parser.*; import java.util.ArrayList; import java.util.HashSet; -import java.util.List; -import java.util.Map; /** * Runs the test and stores the test results created by a single {@link TestCaseDescription} instance. @@ -150,25 +147,7 @@ public class TestExecutor { if (outputs.size() == 0) throw new TestingDataException(Lang.get("err_noTestOutputSignalsDefined")); - if (testCase.getProgram() != null) { - List nodes = model.findNode(n -> n instanceof ProgramMemory && ((ProgramMemory) n).isProgramMemory()); - switch (nodes.size()) { - case 0: - throw new TestingDataException(Lang.get("err_noRomFound")); - case 1: - ((ProgramMemory) nodes.get(0)).setProgramMemory(testCase.getProgram()); - break; - default: - throw new TestingDataException(Lang.get("err_multipleRomsFound")); - } - } - - for (Map.Entry r : testCase.getSignalInit().entrySet()) { - Signal.Setter signal = model.getSignalSetter(r.getKey()); - if (signal == null) - throw new TestingDataException(Lang.get("err_testSignal_N_notFound", r.getKey())); - signal.set(r.getValue(), 0); - } + testCase.getModelInitializer().init(model); model.init(); model.addObserver(event -> { diff --git a/src/main/java/de/neemann/digital/testing/parser/ModelInitializer.java b/src/main/java/de/neemann/digital/testing/parser/ModelInitializer.java new file mode 100644 index 000000000..b5af867ec --- /dev/null +++ b/src/main/java/de/neemann/digital/testing/parser/ModelInitializer.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2020 Helmut Neemann. + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.testing.parser; + +import de.neemann.digital.core.Model; +import de.neemann.digital.core.Node; +import de.neemann.digital.core.Signal; +import de.neemann.digital.core.memory.DataField; +import de.neemann.digital.core.memory.ProgramMemory; +import de.neemann.digital.lang.Lang; +import de.neemann.digital.testing.TestingDataException; + +import java.util.ArrayList; +import java.util.List; + +/** + * Is prepared by the test data parser and then used to initialize the + * model for the test. + */ +public class ModelInitializer { + private final ArrayList inits; + + ModelInitializer() { + this.inits = new ArrayList<>(); + } + + void initSignal(String name, long value) { + inits.add(new InitSignal(name, value)); + } + + void initProgramMemory(DataField memory) { + inits.add(new InitProgramMemory(memory)); + } + + void initMemory(String ramName, DataField memory) { + inits.add(new InitMemory(ramName, memory)); + } + + /** + * Aplies the init steps to the given model + * + * @param model the model to initialize + * @throws TestingDataException TestingDataException + */ + public void init(Model model) throws TestingDataException { + for (ModelInit mi : inits) + mi.init(model); + } + + private interface ModelInit { + void init(Model model) throws TestingDataException; + } + + private static final class InitSignal implements ModelInit { + private final String name; + private final long value; + + private InitSignal(String name, long value) { + this.name = name; + this.value = value; + } + + @Override + public void init(Model model) throws TestingDataException { + Signal.Setter s = model.getSignalSetter(name); + if (s == null) + throw new TestingDataException(Lang.get("err_testSignal_N_notFound", name)); + s.set(value, 0); + } + } + + private static final class InitProgramMemory implements ModelInit { + private final DataField dataField; + + private InitProgramMemory(DataField dataField) { + this.dataField = dataField; + } + + @Override + public void init(Model model) throws TestingDataException { + List nodes = model.findNode(n -> n instanceof ProgramMemory && ((ProgramMemory) n).isProgramMemory()); + switch (nodes.size()) { + case 0: + throw new TestingDataException(Lang.get("err_noRomFound")); + case 1: + ((ProgramMemory) nodes.get(0)).setProgramMemory(dataField); + break; + default: + throw new TestingDataException(Lang.get("err_multipleRomsFound")); + } + } + } + + private static final class InitMemory implements ModelInit { + private final String memoryName; + private final DataField memory; + + private InitMemory(String memoryName, DataField memory) { + this.memoryName = memoryName; + this.memory = memory; + } + + @Override + public void init(Model model) throws TestingDataException { + List nodes = model.findNode(n -> n instanceof ProgramMemory && ((ProgramMemory) n).getLabel().equals(memoryName)); + switch (nodes.size()) { + case 0: + throw new TestingDataException(Lang.get("err_noMemoryFound", memoryName)); + case 1: + ((ProgramMemory) nodes.get(0)).setProgramMemory(memory); + break; + default: + throw new TestingDataException(Lang.get("err_multipleMemoriesFound", memoryName)); + } + } + } +} diff --git a/src/main/java/de/neemann/digital/testing/parser/Parser.java b/src/main/java/de/neemann/digital/testing/parser/Parser.java index 847c4f95c..be8a8e8f6 100644 --- a/src/main/java/de/neemann/digital/testing/parser/Parser.java +++ b/src/main/java/de/neemann/digital/testing/parser/Parser.java @@ -5,7 +5,7 @@ */ package de.neemann.digital.testing.parser; -import de.neemann.digital.core.Bits; +import de.neemann.digital.core.*; import de.neemann.digital.core.memory.DataField; import de.neemann.digital.lang.Lang; import de.neemann.digital.data.Value; @@ -33,12 +33,11 @@ import java.util.HashMap; public class Parser { private final ArrayList names; - private final HashMap signalInitMap; + private final ModelInitializer modelInit; private final ArrayList virtualSignals; private final Tokenizer tok; private final HashMap functions = new HashMap<>(); private LineEmitter emitter; - private DataField program; /** * Creates a new instance @@ -51,7 +50,7 @@ public class Parser { functions.put("ite", new IfThenElse()); names = new ArrayList<>(); virtualSignals = new ArrayList<>(); - signalInitMap = new HashMap<>(); + modelInit = new ModelInitializer(); tok = new Tokenizer(new BufferedReader(new StringReader(data))); } @@ -123,11 +122,17 @@ public class Parser { expect(Tokenizer.Token.NUMBER); long n = convToLong(tok.getIdent()); expect(Tokenizer.Token.SEMICOLON); - signalInitMap.put(sName, sign * n); + modelInit.initSignal(sName, sign * n); + break; + case MEMORY: + tok.consume(); + expect(Tokenizer.Token.IDENT); + final String ramName = tok.getIdent(); + modelInit.initMemory(ramName, parseData()); break; case PROGRAM: tok.consume(); - program = parseData(); + modelInit.initProgramMemory(parseData()); break; case DECLARE: tok.consume(); @@ -283,17 +288,10 @@ public class Parser { } /** - * @return returns the program data or null if not available + * @return the model init actions */ - public DataField getProgram() { - return program; - } - - /** - * @return the signal init map - */ - public HashMap getSignalInit() { - return signalInitMap; + public ModelInitializer getModelInitializer() { + return modelInit; } /** diff --git a/src/main/java/de/neemann/digital/testing/parser/Tokenizer.java b/src/main/java/de/neemann/digital/testing/parser/Tokenizer.java index 51f0ffed6..b5d54a7b5 100644 --- a/src/main/java/de/neemann/digital/testing/parser/Tokenizer.java +++ b/src/main/java/de/neemann/digital/testing/parser/Tokenizer.java @@ -17,7 +17,7 @@ public class Tokenizer { enum Token { UNKNOWN, IDENT, AND, OR, XOR, BIN_NOT, OPEN, CLOSE, NUMBER, EOL, EOF, SHIFTLEFT, SHIFTRIGHT, COMMA, EQUAL, ADD, SUB, MUL, GREATER, GREATEREQUAL, SMALER, SMALEREQUAL, DIV, MOD, END, LOOP, REPEAT, BITS, SEMICOLON, - LET, LOG_NOT, DECLARE, PROGRAM, INIT, WHILE + LET, LOG_NOT, DECLARE, PROGRAM, INIT, MEMORY, WHILE } private final static HashMap STATEMENT_MAP = new HashMap<>(); @@ -32,6 +32,7 @@ public class Tokenizer { STATEMENT_MAP.put("declare", Token.DECLARE); STATEMENT_MAP.put("program", Token.PROGRAM); STATEMENT_MAP.put("init", Token.INIT); + STATEMENT_MAP.put("memory", Token.MEMORY); } private final Reader in; diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 309a81500..e41baa7a2 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -1123,6 +1123,8 @@ Sind evtl. die Namen der Variablen nicht eindeutig? Fehler beim Export zu Verilog. Kein Programmspeicher im Modell gefunden! Ein Programmspeicher muss gewählt werden! Mehrere Programmspeicher im Modell gefunden! Es darf nur ein Programmspeicher muss gewählt werden! + Kein Speicher "{0}" im Modell gefunden! + Mehrere Speicher "{0}" im Modell gefunden! Fehler beim Laden des Programmspeichers. Fehler beim Laden der SVG-Datei. Die SVG-Datei enthält Pins, die es in der Schaltung nicht gibt. diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 28bae2add..df355b8d0 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -1135,6 +1135,8 @@ Error during export to Verilog. No program memory found! The program memory needs to be flagged as such. Multiple program memories found! Only one program memory is allowed. + No memory "{0}" found in the model! + Multiple memories "{0}" found in the model! Error loading the program memory. Error while reading the SVG file. The SVG file contains pins that do not exist in the circuit. diff --git a/src/test/java/de/neemann/digital/testing/parser/ModelInitializerTest.java b/src/test/java/de/neemann/digital/testing/parser/ModelInitializerTest.java new file mode 100644 index 000000000..5efb2386d --- /dev/null +++ b/src/test/java/de/neemann/digital/testing/parser/ModelInitializerTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2020 Helmut Neemann + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.testing.parser; + +import de.neemann.digital.core.Model; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.Signal; +import de.neemann.digital.core.element.ElementAttributes; +import de.neemann.digital.core.element.Keys; +import de.neemann.digital.core.memory.DataField; +import de.neemann.digital.core.memory.RAMSinglePort; +import de.neemann.digital.testing.TestingDataException; +import junit.framework.TestCase; + +import java.io.IOException; + +public class ModelInitializerTest extends TestCase { + + public void test_program() throws IOException, ParserException, TestingDataException { + ModelInitializer mi = new Parser("A B Y\n" + + "program(1,2,3,4)\n" + + "1 1 1").parse().getModelInitializer(); + + Model m = new Model(); + RAMSinglePort ram = m.add(new RAMSinglePort(new ElementAttributes().set(Keys.IS_PROGRAM_MEMORY, true))); + + mi.init(m); + + DataField program = ram.getMemory(); + assertNotNull(program); + assertEquals(4, program.trim()); + assertEquals(1, program.getDataWord(0)); + assertEquals(2, program.getDataWord(1)); + assertEquals(3, program.getDataWord(2)); + assertEquals(4, program.getDataWord(3)); + assertEquals(0, program.getDataWord(4)); + } + + public void test_signal() throws IOException, ParserException, TestingDataException { + ModelInitializer mi = new Parser("A B Y\n" + + "init s1=5;\n" + + "init s2=-1;\n" + + "1 1 1").parse().getModelInitializer(); + + Model m = new Model(); + ObservableValue s1 = new ObservableValue("s", 8); + ObservableValue s2 = new ObservableValue("s", 8); + m.addSignal(new Signal("s1", s1, (value, highZ) -> s1.setValue(value))); + m.addSignal(new Signal("s2", s2, (value, highZ) -> s2.setValue(value))); + + mi.init(m); + + assertEquals(5, s1.getValue()); + assertEquals(-1, s2.getValueSigned()); + } + + public void test_ram() throws IOException, ParserException, TestingDataException { + ModelInitializer mi = new Parser("A B Y\n" + + "memory myRam (1,2)\n" + + "1 1 1").parse().getModelInitializer(); + + Model m = new Model(); + RAMSinglePort ram = m.add(new RAMSinglePort(new ElementAttributes().set(Keys.LABEL, "myRam"))); + + mi.init(m); + + DataField ramData = ram.getMemory(); + assertNotNull(ram); + assertEquals(2, ramData.trim()); + assertEquals(1, ramData.getDataWord(0)); + assertEquals(2, ramData.getDataWord(1)); + + + m = new Model(); + m.add(new RAMSinglePort(new ElementAttributes().set(Keys.LABEL, "wrongName"))); + try { + mi.init(m); + fail(); + } catch (TestingDataException e) { + assertTrue(e.getMessage().contains("myRam")); + } + } + +} \ No newline at end of file diff --git a/src/test/java/de/neemann/digital/testing/parser/ParserTest.java b/src/test/java/de/neemann/digital/testing/parser/ParserTest.java index 8086228d6..eae8e8a7f 100644 --- a/src/test/java/de/neemann/digital/testing/parser/ParserTest.java +++ b/src/test/java/de/neemann/digital/testing/parser/ParserTest.java @@ -8,8 +8,13 @@ package de.neemann.digital.testing.parser; import de.neemann.digital.core.Model; import de.neemann.digital.core.ObservableValue; import de.neemann.digital.core.Signal; +import de.neemann.digital.core.element.ElementAttributes; +import de.neemann.digital.core.element.Keys; import de.neemann.digital.core.memory.DataField; +import de.neemann.digital.core.memory.RAMSinglePort; +import de.neemann.digital.core.memory.ROM; import de.neemann.digital.data.Value; +import de.neemann.digital.testing.TestingDataException; import junit.framework.TestCase; import java.io.IOException; @@ -193,7 +198,7 @@ public class ParserTest extends TestCase { assertEquals(1, td.getLines().size()); } - public void test_modelInitState() throws IOException, ParserException { + public void test_modelSetVar() throws IOException, ParserException { Model model = new Model(); model.addOutput(new Signal("A", new ObservableValue("A", 3).setValue(2))); model.addOutput(new Signal("B", new ObservableValue("B", 3).setValue(3))); @@ -204,19 +209,4 @@ public class ParserTest extends TestCase { new LineCollector(parser, context); assertEquals(5, context.getVar("a")); } - - public void test_program() throws IOException, ParserException { - Parser parser = new Parser("A B Y\n" + - "program(1,2,3,4)\n" + - "1 1 1").parse(); - DataField program = parser.getProgram(); - assertNotNull(program); - assertEquals(4, program.trim()); - assertEquals(1, program.getDataWord(0)); - assertEquals(2, program.getDataWord(1)); - assertEquals(3, program.getDataWord(2)); - assertEquals(4, program.getDataWord(3)); - assertEquals(0, program.getDataWord(4)); - } - } From dc93400815a8a843257e40d21c50a75d3797a04b Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 29 Nov 2020 09:33:02 +0100 Subject: [PATCH 4/4] simplifies ram initialization is test cases --- .../testing/parser/ModelInitializer.java | 17 ++++++++++------- .../neemann/digital/testing/parser/Parser.java | 10 +++++++++- .../testing/parser/ModelInitializerTest.java | 3 ++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/neemann/digital/testing/parser/ModelInitializer.java b/src/main/java/de/neemann/digital/testing/parser/ModelInitializer.java index b5af867ec..45ffc9d1b 100644 --- a/src/main/java/de/neemann/digital/testing/parser/ModelInitializer.java +++ b/src/main/java/de/neemann/digital/testing/parser/ModelInitializer.java @@ -10,6 +10,7 @@ import de.neemann.digital.core.Node; import de.neemann.digital.core.Signal; import de.neemann.digital.core.memory.DataField; import de.neemann.digital.core.memory.ProgramMemory; +import de.neemann.digital.core.memory.RAMInterface; import de.neemann.digital.lang.Lang; import de.neemann.digital.testing.TestingDataException; @@ -35,8 +36,8 @@ public class ModelInitializer { inits.add(new InitProgramMemory(memory)); } - void initMemory(String ramName, DataField memory) { - inits.add(new InitMemory(ramName, memory)); + void initMemory(String ramName, int addr, long value) { + inits.add(new InitMemory(ramName, addr, value)); } /** @@ -96,21 +97,23 @@ public class ModelInitializer { private static final class InitMemory implements ModelInit { private final String memoryName; - private final DataField memory; + private final int addr; + private final long value; - private InitMemory(String memoryName, DataField memory) { + private InitMemory(String memoryName, int addr, long value) { this.memoryName = memoryName; - this.memory = memory; + this.addr = addr; + this.value = value; } @Override public void init(Model model) throws TestingDataException { - List nodes = model.findNode(n -> n instanceof ProgramMemory && ((ProgramMemory) n).getLabel().equals(memoryName)); + List nodes = model.findNode(n -> n instanceof RAMInterface && ((RAMInterface) n).getLabel().equals(memoryName)); switch (nodes.size()) { case 0: throw new TestingDataException(Lang.get("err_noMemoryFound", memoryName)); case 1: - ((ProgramMemory) nodes.get(0)).setProgramMemory(memory); + ((RAMInterface) nodes.get(0)).getMemory().setData(addr, value); break; default: throw new TestingDataException(Lang.get("err_multipleMemoriesFound", memoryName)); diff --git a/src/main/java/de/neemann/digital/testing/parser/Parser.java b/src/main/java/de/neemann/digital/testing/parser/Parser.java index be8a8e8f6..80829ee2e 100644 --- a/src/main/java/de/neemann/digital/testing/parser/Parser.java +++ b/src/main/java/de/neemann/digital/testing/parser/Parser.java @@ -128,7 +128,15 @@ public class Parser { tok.consume(); expect(Tokenizer.Token.IDENT); final String ramName = tok.getIdent(); - modelInit.initMemory(ramName, parseData()); + expect(Tokenizer.Token.OPEN); + expect(Tokenizer.Token.NUMBER); + long addr = convToLong(tok.getIdent()); + expect(Tokenizer.Token.CLOSE); + expect(Tokenizer.Token.EQUAL); + expect(Tokenizer.Token.NUMBER); + long val = convToLong(tok.getIdent()); + expect(Tokenizer.Token.SEMICOLON); + modelInit.initMemory(ramName, (int) addr, val); break; case PROGRAM: tok.consume(); diff --git a/src/test/java/de/neemann/digital/testing/parser/ModelInitializerTest.java b/src/test/java/de/neemann/digital/testing/parser/ModelInitializerTest.java index 5efb2386d..d8591a705 100644 --- a/src/test/java/de/neemann/digital/testing/parser/ModelInitializerTest.java +++ b/src/test/java/de/neemann/digital/testing/parser/ModelInitializerTest.java @@ -59,7 +59,8 @@ public class ModelInitializerTest extends TestCase { public void test_ram() throws IOException, ParserException, TestingDataException { ModelInitializer mi = new Parser("A B Y\n" + - "memory myRam (1,2)\n" + + "memory myRam(0)=1;\n" + + "memory myRam(1)=2;\n" + "1 1 1").parse().getModelInitializer(); Model m = new Model();