Refactoring of passing data from the model to the generators. See #108

This commit is contained in:
hneemann 2018-01-25 15:35:27 +01:00
parent 856f78bf88
commit 2080fe57b9
11 changed files with 154 additions and 113 deletions

View File

@ -34,6 +34,7 @@ public class ModelAnalyser {
private final ArrayList<Signal> inputs;
private final ArrayList<Signal> outputs;
private int uniqueIndex = 0;
private ModelAnalyserInfo modelAnalyzerInfo;
/**
* Creates a new instance
@ -96,6 +97,12 @@ public class ModelAnalyser {
throw new AnalyseException(Lang.get("err_analyseNoInputs"));
if (outputs.size() == 0)
throw new AnalyseException(Lang.get("err_analyseNoOutputs"));
modelAnalyzerInfo = new ModelAnalyserInfo(model, inputs, outputs);
}
private ModelAnalyserInfo getModelAnalyzerInfo() {
return modelAnalyzerInfo;
}
private String createUniqueName(FlipflopD ff) {
@ -332,17 +339,15 @@ public class ModelAnalyser {
public TruthTable analyse() throws NodeException, PinException, BacktrackException, AnalyseException {
LOGGER.debug("start to analyse the model...");
TruthTable tt = new TruthTable().setPinsWithoutNumber(model.getPinsWithoutNumber());
TruthTable tt = new TruthTable();
tt.setModelAnalyzerInfo(getModelAnalyzerInfo());
for (Signal s : inputs)
tt.addVariable(s.getName());
for (Signal s : inputs)
tt.addPinNumber(s);
getModelAnalyzerInfo().addPinNumber(s);
for (Signal s : outputs)
tt.addPinNumber(s);
if (model.getClocks().size() == 1)
tt.setClockPin(model.getClocks().get(0).getClockPin());
getModelAnalyzerInfo().addPinNumber(s);
DependencyAnalyser da = new DependencyAnalyser(this);
long steps = da.getRequiredSteps(this);

View File

@ -0,0 +1,93 @@
package de.neemann.digital.analyse;
import de.neemann.digital.core.Model;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.Signal;
import java.util.ArrayList;
import java.util.TreeMap;
/**
* Additional infos obtained from the model
*/
public class ModelAnalyserInfo {
private final String clockPin;
private final TreeMap<String, String> pins;
private final ArrayList<Signal> inputs;
private final ArrayList<Signal> outputs;
private ArrayList<String> pinsWithoutNumber;
/**
* creates a new instance
*
* @param model the model used
* @param inputs input singnales
* @param outputs output signals
*/
ModelAnalyserInfo(Model model, ArrayList<Signal> inputs, ArrayList<Signal> outputs) {
this.inputs = inputs;
this.outputs = outputs;
pins = new TreeMap<>();
if (model.getClocks().size() == 1)
clockPin = model.getClocks().get(0).getClockPin();
else
clockPin = null;
}
/**
* Adds the signals pin number to the table
*
* @param s the signal
* @throws NodeException NodeException
*/
public void addPinNumber(Signal s) throws NodeException {
String p = s.getPinNumber();
if (p != null && p.length() > 0) pins.put(s.getName(), p);
}
/**
* @return the assigned pins
*/
public TreeMap<String, String> getPins() {
return pins;
}
/**
* @return list of pins without a number. Never null, maybe a empty list
*/
public ArrayList<String> getPinsWithoutNumber() {
if (pinsWithoutNumber == null) {
pinsWithoutNumber = new ArrayList<>();
for (Signal s : inputs)
if (s.missingPinNumber())
pinsWithoutNumber.add((s.getName()));
for (Signal s : outputs)
if (s.missingPinNumber())
pinsWithoutNumber.add((s.getName()));
}
return pinsWithoutNumber;
}
/**
* @return the clock pin
*/
public String getClockPin() {
return clockPin;
}
/**
* @return the clock pin
*/
public int getClockPinInt() {
if (clockPin == null || clockPin.length() == 0)
return 0;
try {
return Integer.parseInt(clockPin);
} catch (NumberFormatException e) {
return 0;
}
}
}

View File

@ -10,13 +10,10 @@ import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.analyse.quinemc.BoolTable;
import de.neemann.digital.analyse.quinemc.BoolTableByteArray;
import de.neemann.digital.analyse.quinemc.ThreeStateValue;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.Signal;
import de.neemann.digital.lang.Lang;
import java.io.*;
import java.util.ArrayList;
import java.util.TreeMap;
/**
* The description of a truth table.
@ -27,10 +24,8 @@ public class TruthTable {
private final ArrayList<Variable> variables;
private final ArrayList<Result> results;
private final TreeMap<String, String> pins;
private transient BitSetter bitSetter;
private ArrayList<String> pinsWithoutNumber = null;
private String clockPin;
private transient ModelAnalyserInfo modelAnalyzerInfo;
/**
* Load the given file and returns a truth table instance
@ -134,7 +129,6 @@ public class TruthTable {
public TruthTable(ArrayList<Variable> vars) {
this.variables = vars;
results = new ArrayList<>();
pins = new TreeMap<>();
}
/**
@ -470,70 +464,21 @@ public class TruthTable {
}
/**
* Adds the signals pin number to the table
* Sets additional data obtained from the model
*
* @param s the signal
* @throws NodeException NodeException
* @param modelAnalyzerInfo the data obtained from the model
*/
public void addPinNumber(Signal s) throws NodeException {
String p = s.getPinNumber();
if (p != null && p.length() > 0) pins.put(s.getName(), p);
public void setModelAnalyzerInfo(ModelAnalyserInfo modelAnalyzerInfo) {
this.modelAnalyzerInfo = modelAnalyzerInfo;
}
/**
* @return the assigned pins
*/
public TreeMap<String, String> getPins() {
return pins;
}
/**
* Sets the missing pin number flag
* returns additional model infos
*
* @param pinsWithoutNumber list of pins without a number or null
* @return this for chained calls
* @return infos obtained from the analysed model, maybe null
*/
public TruthTable setPinsWithoutNumber(ArrayList<String> pinsWithoutNumber) {
this.pinsWithoutNumber = pinsWithoutNumber;
return this;
}
/**
* @return list of pins without a number or null
*/
public ArrayList<String> getPinsWithoutNumber() {
return pinsWithoutNumber;
}
/**
* Sets the clock pin
*
* @param clockPin the clock pin
*/
public void setClockPin(String clockPin) {
this.clockPin = clockPin;
}
/**
* @return the clock pin
*/
public String getClockPin() {
return clockPin;
}
/**
* @return the clock pin
*/
public int getClockPinInt() {
if (clockPin == null || clockPin.length() == 0)
return 0;
try {
return Integer.parseInt(clockPin);
} catch (NumberFormatException e) {
return 0;
}
public ModelAnalyserInfo getModelAnalyzerInfo() {
return modelAnalyzerInfo;
}
/**

View File

@ -1,6 +1,7 @@
package de.neemann.digital.builder.circuit;
import de.neemann.digital.analyse.DetermineJKStateMachine;
import de.neemann.digital.analyse.ModelAnalyserInfo;
import de.neemann.digital.analyse.expression.*;
import de.neemann.digital.analyse.expression.Not;
import de.neemann.digital.analyse.expression.format.FormatterException;
@ -410,13 +411,14 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
}
/**
* Sets the pin mapping
* Sets the infos obtained from the model
*
* @param pins the pin mapping
* @param modelAnalyserInfo the model analyzer infos
* @return this for chained calls
*/
public CircuitBuilder setPins(TreeMap<String, String> pins) {
this.pins = pins;
public CircuitBuilder setModelAnalyzerInfo(ModelAnalyserInfo modelAnalyserInfo) {
if (modelAnalyserInfo != null)
this.pins = modelAnalyserInfo.getPins();
return this;
}

View File

@ -621,19 +621,6 @@ public class Model implements Iterable<Node> {
return found;
}
/**
* @return list of pins without a number
*/
public ArrayList<String> getPinsWithoutNumber() {
ArrayList<String> sigWithoutPinNumber = null;
for (Signal s : signals)
if (s.missingPinNumber()) {
if (sigWithoutPinNumber == null) sigWithoutPinNumber = new ArrayList<>();
sigWithoutPinNumber.add(s.getName());
}
return sigWithoutPinNumber;
}
/**
* Adds a button which is to map to a keyboard key
*

View File

@ -22,9 +22,6 @@ import de.neemann.digital.builder.Gal16v8.Gal16v8JEDECExporter;
import de.neemann.digital.builder.Gal22v10.Gal22v10CuplExporter;
import de.neemann.digital.builder.Gal22v10.Gal22v10JEDECExporter;
import de.neemann.digital.builder.circuit.CircuitBuilder;
import de.neemann.digital.gui.components.table.hardware.GenerateCUPL;
import de.neemann.digital.gui.components.table.hardware.GenerateFile;
import de.neemann.digital.gui.components.table.hardware.HardwareDescriptionGenerator;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Key;
import de.neemann.digital.core.element.Keys;
@ -36,6 +33,9 @@ import de.neemann.digital.gui.SaveAsHelper;
import de.neemann.digital.gui.components.AttributeDialog;
import de.neemann.digital.gui.components.ElementOrderer;
import de.neemann.digital.gui.components.karnaugh.KarnaughMapDialog;
import de.neemann.digital.gui.components.table.hardware.GenerateCUPL;
import de.neemann.digital.gui.components.table.hardware.GenerateFile;
import de.neemann.digital.gui.components.table.hardware.HardwareDescriptionGenerator;
import de.neemann.digital.lang.Lang;
import de.neemann.gui.ErrorMessage;
import de.neemann.gui.MyFileChooser;
@ -53,8 +53,10 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;
import java.util.prefs.Preferences;
/**
@ -67,7 +69,6 @@ public class TableDialog extends JDialog {
static {
LIST.add(Keys.LABEL);
LIST.add(Keys.PINNUMBER);
}
private final JTextPane statusBar;
@ -248,17 +249,9 @@ public class TableDialog extends JDialog {
ElementAttributes attr = new ElementAttributes();
final String name = model.getColumnName(columnIndex);
attr.set(Keys.LABEL, name);
final TreeMap<String, String> pins = model.getTable().getPins();
if (pins.containsKey(name))
attr.set(Keys.PINNUMBER, pins.get(name));
ElementAttributes modified = new AttributeDialog(this, pos, LIST, attr).showDialog();
if (modified != null) {
pins.remove(name);
final String newName = modified.get(Keys.LABEL).trim().replace(' ', '_');
final String pinStr = modified.get(Keys.PINNUMBER).trim();
if (pinStr.length() > 0)
pins.put(newName, pinStr);
if (!newName.equals(name))
model.setColumnName(columnIndex, newName);
}
@ -493,7 +486,7 @@ public class TableDialog extends JDialog {
private void createCircuit(boolean useJKff, ExpressionModifier... modifier) {
try {
CircuitBuilder circuitBuilder = new CircuitBuilder(shapeFactory, useJKff, model.getTable().getVars())
.setPins(model.getTable().getPins());
.setModelAnalyzerInfo(model.getTable().getModelAnalyzerInfo());
new BuilderExpressionCreator(circuitBuilder, modifier)
.setUseJKOptimizer(useJKff)
.create(lastGeneratedExpressions);

View File

@ -1,5 +1,6 @@
package de.neemann.digital.gui.components.table.hardware;
import de.neemann.digital.analyse.ModelAnalyserInfo;
import de.neemann.digital.analyse.TruthTable;
import de.neemann.digital.analyse.expression.modify.ExpressionModifier;
import de.neemann.digital.builder.Gal16v8.CuplExporter;
@ -74,7 +75,9 @@ public class GenerateCUPL implements HardwareDescriptionGenerator {
File f = new File(cuplPath, "CUPL.PLD");
CuplExporter cuplExporter = cuplExporterFactory.create();
cuplExporter.setProjectName(circuitFile.getName());
cuplExporter.getPinMapping().addAll(table.getPins());
final ModelAnalyserInfo modelAnalyzerInfo = table.getModelAnalyzerInfo();
if (modelAnalyzerInfo != null)
cuplExporter.getPinMapping().addAll(modelAnalyzerInfo.getPins());
new BuilderExpressionCreator(cuplExporter.getBuilder(), ExpressionModifier.IDENTITY).create(expressions);
try (FileOutputStream out = new FileOutputStream(f)) {
cuplExporter.writeTo(out);

View File

@ -1,5 +1,6 @@
package de.neemann.digital.gui.components.table.hardware;
import de.neemann.digital.analyse.ModelAnalyserInfo;
import de.neemann.digital.analyse.TruthTable;
import de.neemann.digital.analyse.expression.modify.ExpressionModifier;
import de.neemann.digital.builder.ExpressionToFileExporter;
@ -52,16 +53,24 @@ public class GenerateFile implements HardwareDescriptionGenerator {
@Override
public void generate(JDialog parent, File circuitFile, TruthTable table, ExpressionListenerStore expressions) throws Exception {
ArrayList<String> pinsWithoutNumber = table.getPinsWithoutNumber();
if (pinsWithoutNumber != null) {
int res = JOptionPane.showConfirmDialog(parent,
new LineBreaker().toHTML().breakLines(Lang.get("msg_thereAreMissingPinNumbers", pinsWithoutNumber)),
ModelAnalyserInfo mai = table.getModelAnalyzerInfo();
if (mai == null) {
JOptionPane.showMessageDialog(parent,
new LineBreaker().toHTML().breakLines(Lang.get("msg_circuitIsRequired")),
Lang.get("msg_warning"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
if (res != JOptionPane.OK_OPTION)
return;
return;
} else {
ArrayList<String> pinsWithoutNumber = mai.getPinsWithoutNumber();
if (!pinsWithoutNumber.isEmpty()) {
int res = JOptionPane.showConfirmDialog(parent,
new LineBreaker().toHTML().breakLines(Lang.get("msg_thereAreMissingPinNumbers", pinsWithoutNumber)),
Lang.get("msg_warning"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
if (res != JOptionPane.OK_OPTION)
return;
}
}
if (circuitFile == null)
@ -74,8 +83,8 @@ public class GenerateFile implements HardwareDescriptionGenerator {
fileChooser.setSelectedFile(circuitFile);
if (fileChooser.showSaveDialog(parent) == JFileChooser.APPROVE_OPTION) {
ExpressionToFileExporter expressionExporter = factory.create();
expressionExporter.getPinMapping().addAll(table.getPins());
expressionExporter.getPinMapping().setClockPin(table.getClockPinInt());
expressionExporter.getPinMapping().addAll(mai.getPins());
expressionExporter.getPinMapping().setClockPin(mai.getClockPinInt());
new BuilderExpressionCreator(expressionExporter.getBuilder(), ExpressionModifier.IDENTITY).create(expressions);
expressionExporter.export(SaveAsHelper.checkSuffix(fileChooser.getSelectedFile(), suffix));
}

View File

@ -1285,6 +1285,8 @@ eine &lt;a href=&quot;https://github.com/hneemann/Digital/issues/new?labels=enha
<string name="msg_create CHNFile">Erzeugen der CHN-Datei</string>
<string name="msg_tableHasManyRowsConfirm">Die Tabelle ist sehr groß, der Export kann etwas dauern.
Soll dennoch exportiert werden?</string>
<string name="msg_circuitIsRequired">Um eine Hardwarebeschreibung zu erzeugen, muss zuvor eine Schaltung erstellt
und analysiert werden. Aus nur einer Wahrheitstabelle kann keine Hardwarebeschreibung erzeugt werden.</string>
<string name="ok">Ok</string>
<string name="rot_0"></string>

View File

@ -1272,6 +1272,8 @@ an &lt;a href=&quot;https://github.com/hneemann/Digital/issues/new?labels=enhanc
<string name="msg_create CHNFile">Creation of CHN file.</string>
<string name="msg_tableHasManyRowsConfirm">The table is very large, the export may take a while.
Start export anyway?</string>
<string name="msg_circuitIsRequired">To create a hardware description, a circuit must first be created and analyzed.
A standalone truth table can not be used to generate a hardware description.</string>
<string name="ok">Ok</string>
<string name="rot_0"></string>

View File

@ -128,7 +128,7 @@ public class ModelAnalyserTest extends TestCase {
TruthTable tt = new ModelAnalyser(model).analyse();
checkIdent(tt);
TreeMap<String, String> p = tt.getPins();
TreeMap<String, String> p = tt.getModelAnalyzerInfo().getPins();
assertEquals("i1",p.get("A0"));
assertEquals("i2",p.get("A1"));
assertEquals("o1",p.get("B0"));