mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-29 07:50:29 -04:00
refactoring of input don't care handling
This commit is contained in:
parent
311793d7dd
commit
4d92a55cbb
@ -11,6 +11,7 @@ import de.neemann.digital.lang.Lang;
|
|||||||
import de.neemann.digital.testing.*;
|
import de.neemann.digital.testing.*;
|
||||||
import de.neemann.gui.ErrorMessage;
|
import de.neemann.gui.ErrorMessage;
|
||||||
import de.neemann.gui.IconCreator;
|
import de.neemann.gui.IconCreator;
|
||||||
|
import de.neemann.gui.StringUtils;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
@ -73,7 +74,12 @@ public class TestResultDialog extends JDialog {
|
|||||||
tabIcon = ICON_FAILED;
|
tabIcon = ICON_FAILED;
|
||||||
errorTabIndex = i;
|
errorTabIndex = i;
|
||||||
}
|
}
|
||||||
|
if (tr.toManyResults())
|
||||||
|
tabName += " " + Lang.get("msg_test_missingLines");
|
||||||
|
|
||||||
tp.addTab(tabName, tabIcon, new JScrollPane(table));
|
tp.addTab(tabName, tabIcon, new JScrollPane(table));
|
||||||
|
if (tr.toManyResults())
|
||||||
|
tp.setToolTipTextAt(i, StringUtils.textToHTML(Lang.get("msg_test_missingLines_tt")));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (errorTabIndex >= 0)
|
if (errorTabIndex >= 0)
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package de.neemann.digital.testing;
|
||||||
|
|
||||||
|
import de.neemann.digital.testing.parser.LineListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves don't cares in the inputs list
|
||||||
|
* Created by hneemann on 19.04.17.
|
||||||
|
*/
|
||||||
|
public class LineListenerResolveDontCare implements LineListener {
|
||||||
|
|
||||||
|
private final LineListener parent;
|
||||||
|
private final ArrayList<TestResult.TestSignal> inputs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance
|
||||||
|
*
|
||||||
|
* @param parent the parent listener
|
||||||
|
* @param inputs the input test signals
|
||||||
|
*/
|
||||||
|
public LineListenerResolveDontCare(LineListener parent, ArrayList<TestResult.TestSignal> inputs) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.inputs = inputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(Value[] rowWithDontCare) {
|
||||||
|
ArrayList<Integer> dcIndex = null;
|
||||||
|
for (TestResult.TestSignal in : inputs) {
|
||||||
|
if (rowWithDontCare[in.getIndex()].getType() == Value.Type.DONTCARE) {
|
||||||
|
if (dcIndex == null)
|
||||||
|
dcIndex = new ArrayList<>();
|
||||||
|
dcIndex.add(in.getIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dcIndex == null)
|
||||||
|
parent.add(rowWithDontCare);
|
||||||
|
else {
|
||||||
|
int count = 1 << dcIndex.size();
|
||||||
|
for (int n = 0; n < count; n++) {
|
||||||
|
int mask = 1;
|
||||||
|
for (int in : dcIndex) {
|
||||||
|
boolean val = (n & mask) != 0;
|
||||||
|
rowWithDontCare[in] = new Value(val ? 1 : 0);
|
||||||
|
mask *= 2;
|
||||||
|
}
|
||||||
|
parent.add(rowWithDontCare);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,8 +12,6 @@ import de.neemann.digital.testing.parser.ParserException;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the test results created by a single {@link TestData} instance.
|
* Stores the test results created by a single {@link TestData} instance.
|
||||||
@ -31,6 +29,8 @@ public class TestResult {
|
|||||||
private boolean allPassed;
|
private boolean allPassed;
|
||||||
private Exception exception;
|
private Exception exception;
|
||||||
private boolean toManyResults = false;
|
private boolean toManyResults = false;
|
||||||
|
private ArrayList<TestSignal> inputs;
|
||||||
|
private ArrayList<TestSignal> outputs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new testing result
|
* Creates a new testing result
|
||||||
@ -56,7 +56,7 @@ public class TestResult {
|
|||||||
allPassed = true;
|
allPassed = true;
|
||||||
HashSet<String> usedSignals = new HashSet<>();
|
HashSet<String> usedSignals = new HashSet<>();
|
||||||
|
|
||||||
ArrayList<TestSignal> inputs = new ArrayList<>();
|
inputs = new ArrayList<>();
|
||||||
for (Signal s : model.getInputs()) {
|
for (Signal s : model.getInputs()) {
|
||||||
final int index = getIndexOf(s.getName());
|
final int index = getIndexOf(s.getName());
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
@ -72,7 +72,7 @@ public class TestResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<TestSignal> outputs = new ArrayList<>();
|
outputs = new ArrayList<>();
|
||||||
for (Signal s : model.getOutputs()) {
|
for (Signal s : model.getOutputs()) {
|
||||||
final int index = getIndexOf(s.getName());
|
final int index = getIndexOf(s.getName());
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
@ -94,9 +94,20 @@ public class TestResult {
|
|||||||
model.init();
|
model.init();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
lines.emitLines(rowWithDontCare -> {
|
lines.emitLines(new LineListenerResolveDontCare(values -> checkRow(model, values), inputs), new Context());
|
||||||
for (Value[] row : resolveDontCares(inputs, rowWithDontCare)) {
|
} catch (ParserException e) {
|
||||||
|
throw new TestingDataException(e);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
if (allPassed) {
|
||||||
|
allPassed = false;
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkRow(Model model, Value[] row) {
|
||||||
Value[] res = new Value[row.length];
|
Value[] res = new Value[row.length];
|
||||||
|
|
||||||
boolean clockIsUsed = false;
|
boolean clockIsUsed = false;
|
||||||
@ -150,34 +161,6 @@ public class TestResult {
|
|||||||
else
|
else
|
||||||
toManyResults = true;
|
toManyResults = true;
|
||||||
}
|
}
|
||||||
}, new Context());
|
|
||||||
} catch (ParserException e) {
|
|
||||||
throw new TestingDataException(e);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
if (allPassed) {
|
|
||||||
allPassed = false;
|
|
||||||
exception = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Iterable<Value[]> resolveDontCares(ArrayList<TestSignal> inputs, Value[] rowWithDontCare) {
|
|
||||||
ArrayList<Integer> dcIndex = null;
|
|
||||||
for (TestSignal in : inputs) {
|
|
||||||
if (rowWithDontCare[in.index].getType() == Value.Type.DONTCARE) {
|
|
||||||
if (dcIndex == null)
|
|
||||||
dcIndex = new ArrayList<>();
|
|
||||||
dcIndex.add(in.index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dcIndex == null)
|
|
||||||
return new SingleItemIterator<>(rowWithDontCare);
|
|
||||||
else {
|
|
||||||
return new VariantsIterator(dcIndex, rowWithDontCare);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if all tests have passed
|
* @return true if all tests have passed
|
||||||
@ -193,7 +176,7 @@ public class TestResult {
|
|||||||
*
|
*
|
||||||
* @return true if there are missing items in the results list.
|
* @return true if there are missing items in the results list.
|
||||||
*/
|
*/
|
||||||
public boolean isToManyResults() {
|
public boolean toManyResults() {
|
||||||
return toManyResults;
|
return toManyResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +227,10 @@ public class TestResult {
|
|||||||
return results.get(rowIndex)[columnIndex];
|
return results.get(rowIndex)[columnIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TestSignal {
|
/**
|
||||||
|
* A test signal
|
||||||
|
*/
|
||||||
|
public static class TestSignal {
|
||||||
private final int index;
|
private final int index;
|
||||||
private final ObservableValue value;
|
private final ObservableValue value;
|
||||||
|
|
||||||
@ -252,91 +238,12 @@ public class TestResult {
|
|||||||
this.index = index;
|
this.index = index;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static class SingleItemIterator<T> implements Iterable<T> {
|
/**
|
||||||
private final T value;
|
* @return the index of this value
|
||||||
|
*/
|
||||||
SingleItemIterator(T value) {
|
public int getIndex() {
|
||||||
this.value = value;
|
return index;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<T> iterator() {
|
|
||||||
return new SingleItemIterable<>(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class SingleItemIterable<T> implements Iterator<T> {
|
|
||||||
private T value;
|
|
||||||
|
|
||||||
SingleItemIterable(T value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return value != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T next() {
|
|
||||||
if (value == null)
|
|
||||||
throw new NoSuchElementException();
|
|
||||||
T r = value;
|
|
||||||
value = null;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class VariantsIterator implements Iterable<Value[]> {
|
|
||||||
private final ArrayList<Integer> dcIndex;
|
|
||||||
private final Value[] rowWithDontCare;
|
|
||||||
|
|
||||||
VariantsIterator(ArrayList<Integer> dcIndex, Value[] rowWithDontCare) {
|
|
||||||
this.dcIndex = dcIndex;
|
|
||||||
this.rowWithDontCare = rowWithDontCare;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<Value[]> iterator() {
|
|
||||||
Value[] copy = new Value[rowWithDontCare.length];
|
|
||||||
for (int i = 0; i < copy.length; i++)
|
|
||||||
copy[i] = new Value(rowWithDontCare[i]);
|
|
||||||
return new VariantsIterable(dcIndex, copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class VariantsIterable implements Iterator<Value[]> {
|
|
||||||
private final ArrayList<Integer> dcIndex;
|
|
||||||
private final Value[] row;
|
|
||||||
private final int count;
|
|
||||||
private int n;
|
|
||||||
|
|
||||||
VariantsIterable(ArrayList<Integer> dcIndex, Value[] row) {
|
|
||||||
this.dcIndex = dcIndex;
|
|
||||||
this.row = row;
|
|
||||||
count = 1 << dcIndex.size();
|
|
||||||
n = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return n < count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Value[] next() {
|
|
||||||
if (n >= count)
|
|
||||||
throw new NoSuchElementException();
|
|
||||||
int mask = 1;
|
|
||||||
for (int in : dcIndex) {
|
|
||||||
boolean val = (n & mask) != 0;
|
|
||||||
row[in] = new Value(val ? 1 : 0);
|
|
||||||
mask *= 2;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,6 +768,10 @@ Die Icons stammen aus dem Tango Desktop Project.</string>
|
|||||||
<string name="msg_testResult">Testergebnis</string>
|
<string name="msg_testResult">Testergebnis</string>
|
||||||
<string name="msg_test_N_Passed">{0}: ok</string>
|
<string name="msg_test_N_Passed">{0}: ok</string>
|
||||||
<string name="msg_test_N_Failed">{0}: Fehler</string>
|
<string name="msg_test_N_Failed">{0}: Fehler</string>
|
||||||
|
<string name="msg_test_missingLines">(Zu viele Einträge!)</string>
|
||||||
|
<string name="msg_test_missingLines_tt">Es wurden alle Testfälle ausgeführt, aber nicht alle Ergebnisse werden angezeigt.
|
||||||
|
Die Bewertung des Testergebnises ist dennoch korrekt!</string>
|
||||||
|
|
||||||
<string name="msg_testExp_N0_found_N1">E: {0} / F: {1}</string>
|
<string name="msg_testExp_N0_found_N1">E: {0} / F: {1}</string>
|
||||||
<string name="msg_creatingHelp">Fehler bei der Erzeugung der Hilfe!</string>
|
<string name="msg_creatingHelp">Fehler bei der Erzeugung der Hilfe!</string>
|
||||||
<string name="msg_clipboardContainsNoImportableData">In der Zwischenablage befinden sich keine importierbaren Daten!</string>
|
<string name="msg_clipboardContainsNoImportableData">In der Zwischenablage befinden sich keine importierbaren Daten!</string>
|
||||||
|
@ -770,6 +770,9 @@ The icons are taken from the Tango Desktop Project.</string>
|
|||||||
<string name="msg_fileIsNotUnique">The file name is not unique!</string>
|
<string name="msg_fileIsNotUnique">The file name is not unique!</string>
|
||||||
<string name="msg_fileNotImportedYet">The file has not yet been imported.</string>
|
<string name="msg_fileNotImportedYet">The file has not yet been imported.</string>
|
||||||
<string name="msg_fileExists">The file {0} already exists! Do you want to overwrite the file?</string>
|
<string name="msg_fileExists">The file {0} already exists! Do you want to overwrite the file?</string>
|
||||||
|
<string name="msg_test_missingLines">(To many entries!)</string>
|
||||||
|
<string name="msg_test_missingLines_tt">All test cases are executed, but not all results are shown.
|
||||||
|
The evaluation of the test result is nevertheless correct!</string>
|
||||||
|
|
||||||
<string name="ok">Ok</string>
|
<string name="ok">Ok</string>
|
||||||
<string name="rot_0">0°</string>
|
<string name="rot_0">0°</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user