diff --git a/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterTestCase.java b/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterTestCase.java index c0ba9aef6..f298601fb 100644 --- a/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterTestCase.java +++ b/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterTestCase.java @@ -5,55 +5,113 @@ */ package de.neemann.digital.analyse.format; +import de.neemann.digital.analyse.ModelAnalyserInfo; import de.neemann.digital.analyse.TruthTable; import de.neemann.digital.analyse.expression.ContextFiller; import de.neemann.digital.analyse.expression.ExpressionException; import de.neemann.digital.analyse.expression.Variable; import de.neemann.digital.analyse.quinemc.ThreeStateValue; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + /** * Creates a test case which represents the truth table */ public class TruthTableFormatterTestCase implements TruthTableFormatter { + private enum Type {NORMAL, FIRSTBIN, BIN} + + private final HashMap> inputBusMap; + private final HashMap> outputBusMap; + + /** + * Creates a new instance. + * + * @param modelAnalyzerInfo the information about the usage of multi bit signals + */ + public TruthTableFormatterTestCase(ModelAnalyserInfo modelAnalyzerInfo) { + if (modelAnalyzerInfo == null) { + inputBusMap = new HashMap<>(); + outputBusMap = new HashMap<>(); + } else { + inputBusMap = modelAnalyzerInfo.getInputBusMap(); + outputBusMap = modelAnalyzerInfo.getOutputBusMap(); + } + } + @Override public String format(TruthTable truthTable) throws ExpressionException { StringBuilder sb = new StringBuilder(); - for (Variable v : truthTable.getVars()) - sb.append(v.getIdentifier()).append(" "); - for (int i = 0; i < truthTable.getResultCount(); i++) { - sb.append(truthTable.getResultName(i)); - if (i < truthTable.getResultCount() - 1) - sb.append(" "); - } + ArrayList inputs = new ArrayList<>(); + for (Variable v : truthTable.getVars()) + inputs.add(v.getIdentifier()); + ArrayList inputOutType = outVars(sb, inputs, inputBusMap); + + ArrayList outputs = new ArrayList<>(); + for (int i = 0; i < truthTable.getResultCount(); i++) + outputs.add(truthTable.getResultName(i)); + ArrayList outputOutType = outVars(sb, outputs, outputBusMap); + sb.append("\n\n"); ContextFiller cf = new ContextFiller(truthTable.getVars()); for (int i = 0; i < cf.getRowCount(); i++) { cf.setContextTo(i); - for (Variable v : cf) { - sb.append(format(cf.get(v))); - for (int j = 0; j < v.getIdentifier().length(); j++) - sb.append(" "); - } + int ind = 0; + for (Variable v : cf) + outValue(sb, inputOutType.get(ind++), ThreeStateValue.value(cf.get(v))); - for (int j = 0; j < truthTable.getResultCount(); j++) { - ThreeStateValue r = truthTable.getResult(j).get(i); - sb.append(format(r)); - if (j < truthTable.getResultCount() - 1) - for (int k = 0; k < truthTable.getResultName(j).length(); k++) - sb.append(" "); - } + ind = 0; + for (int j = 0; j < truthTable.getResultCount(); j++) + outValue(sb, outputOutType.get(ind++), truthTable.getResult(j).get(i)); sb.append("\n"); } return sb.toString(); } - private String format(boolean b) { - return format(ThreeStateValue.value(b)); + private void outValue(StringBuilder sb, Type type, ThreeStateValue b) { + switch (type) { + case NORMAL: + sb.append(" ").append(formatValue(b)); + break; + case FIRSTBIN: + sb.append(" 0b").append(formatValue(b)); + break; + case BIN: + sb.append(formatValue(b)); + break; + } + } - private String format(ThreeStateValue r) { + private ArrayList outVars(StringBuilder sb, ArrayList vars, HashMap> busMap) { + ArrayList types = new ArrayList<>(vars.size()); + HashMap map = new HashMap<>(); + for (Map.Entry> e : busMap.entrySet()) { + String last = null; + for (String s : e.getValue()) { + map.put(s, ""); + last = s; + } + map.put(last, e.getKey()); + } + for (String n : vars) { + String r = map.get(n); + if (r == null) { + sb.append(n).append(" "); + types.add(Type.NORMAL); + } else if (!r.isEmpty()) { + sb.append(r).append(" "); + types.add(Type.FIRSTBIN); + } else + types.add(Type.BIN); + } + return types; + } + + private String formatValue(ThreeStateValue r) { switch (r) { case one: return "1"; diff --git a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java index c1355b594..5863b3c1c 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java @@ -427,7 +427,7 @@ public class TableDialog extends JDialog { @Override public void actionPerformed(ActionEvent e) { try { - TruthTableFormatter test = new TruthTableFormatterTestCase(); + TruthTableFormatter test = new TruthTableFormatterTestCase(undoManager.getActual().getModelAnalyzerInfo()); String testCase = test.format(undoManager.getActual()); new ShowStringDialog(TableDialog.this, Lang.get("win_table_exportDialog"), testCase).setVisible(true); diff --git a/src/test/java/de/neemann/digital/analyse/format/TruthTableFormatterTestCaseTest.java b/src/test/java/de/neemann/digital/analyse/format/TruthTableFormatterTestCaseTest.java new file mode 100644 index 000000000..fcf6d5321 --- /dev/null +++ b/src/test/java/de/neemann/digital/analyse/format/TruthTableFormatterTestCaseTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019 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.analyse.format; + +import de.neemann.digital.analyse.ModelAnalyser; +import de.neemann.digital.analyse.TruthTable; +import de.neemann.digital.core.Model; +import de.neemann.digital.integration.ToBreakRunner; +import junit.framework.TestCase; + +public class TruthTableFormatterTestCaseTest extends TestCase { + + public void testFormat() throws Exception { + TruthTable tt = new TruthTable(3); + tt.addResult("Y_0"); + tt.addResult("Y_1"); + + assertEquals("A B C Y_0 Y_1 \n" + + "\n" + + " 0 0 0 0 0\n" + + " 0 0 1 0 0\n" + + " 0 1 0 0 0\n" + + " 0 1 1 0 0\n" + + " 1 0 0 0 0\n" + + " 1 0 1 0 0\n" + + " 1 1 0 0 0\n" + + " 1 1 1 0 0\n", new TruthTableFormatterTestCase(null).format(tt)); + } + + public void testBus() throws Exception { + Model m = new ToBreakRunner("dig/analyze/testCaseCreation.dig").getModel(); + TruthTable tt = new ModelAnalyser(m).analyse(); + + assertEquals("b a C_i C_o S \n" + + "\n" + + " 0b00 0b00 0 0 0b00\n" + + " 0b00 0b00 1 0 0b01\n" + + " 0b00 0b01 0 0 0b01\n" + + " 0b00 0b01 1 0 0b10\n" + + " 0b00 0b10 0 0 0b10\n" + + " 0b00 0b10 1 0 0b11\n" + + " 0b00 0b11 0 0 0b11\n" + + " 0b00 0b11 1 1 0b00\n" + + " 0b01 0b00 0 0 0b01\n" + + " 0b01 0b00 1 0 0b10\n" + + " 0b01 0b01 0 0 0b10\n" + + " 0b01 0b01 1 0 0b11\n" + + " 0b01 0b10 0 0 0b11\n" + + " 0b01 0b10 1 1 0b00\n" + + " 0b01 0b11 0 1 0b00\n" + + " 0b01 0b11 1 1 0b01\n" + + " 0b10 0b00 0 0 0b10\n" + + " 0b10 0b00 1 0 0b11\n" + + " 0b10 0b01 0 0 0b11\n" + + " 0b10 0b01 1 1 0b00\n" + + " 0b10 0b10 0 1 0b00\n" + + " 0b10 0b10 1 1 0b01\n" + + " 0b10 0b11 0 1 0b01\n" + + " 0b10 0b11 1 1 0b10\n" + + " 0b11 0b00 0 0 0b11\n" + + " 0b11 0b00 1 1 0b00\n" + + " 0b11 0b01 0 1 0b00\n" + + " 0b11 0b01 1 1 0b01\n" + + " 0b11 0b10 0 1 0b01\n" + + " 0b11 0b10 1 1 0b10\n" + + " 0b11 0b11 0 1 0b10\n" + + " 0b11 0b11 1 1 0b11\n", new TruthTableFormatterTestCase(tt.getModelAnalyzerInfo()).format(tt)); + } + +} \ No newline at end of file diff --git a/src/test/resources/dig/analyze/testCaseCreation.dig b/src/test/resources/dig/analyze/testCaseCreation.dig new file mode 100644 index 000000000..fd84bbe91 --- /dev/null +++ b/src/test/resources/dig/analyze/testCaseCreation.dig @@ -0,0 +1,126 @@ + + + 1 + + + + Add + + + Bits + 2 + + + + + + Out + + + Label + C_o + + + + + + Out + + + Label + S + + + Bits + 2 + + + + + + In + + + Label + b + + + Bits + 2 + + + + + + In + + + Label + a + + + Bits + 2 + + + + + + In + + + Label + C_i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file