mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-16 00:15:01 -04:00
added truth table generation
This commit is contained in:
parent
a0c134b01d
commit
ec1511258d
@ -5,11 +5,15 @@
|
|||||||
*/
|
*/
|
||||||
package de.neemann.digital.fsm;
|
package de.neemann.digital.fsm;
|
||||||
|
|
||||||
import de.neemann.digital.analyse.expression.Expression;
|
import de.neemann.digital.analyse.TruthTable;
|
||||||
|
import de.neemann.digital.analyse.expression.*;
|
||||||
import de.neemann.digital.draw.graphics.Graphic;
|
import de.neemann.digital.draw.graphics.Graphic;
|
||||||
import de.neemann.digital.draw.graphics.VectorFloat;
|
import de.neemann.digital.draw.graphics.VectorFloat;
|
||||||
|
import de.neemann.digital.lang.Lang;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple finite state machine
|
* A simple finite state machine
|
||||||
@ -165,4 +169,122 @@ public class FSM {
|
|||||||
for (Transition t : transitions)
|
for (Transition t : transitions)
|
||||||
t.initPos();
|
t.initPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the truth table which is defined by this finite state machine
|
||||||
|
*
|
||||||
|
* @return the truth table
|
||||||
|
* @throws ExpressionException ExpressionException
|
||||||
|
* @throws FinitStateMachineException FinitStateMachineException
|
||||||
|
*/
|
||||||
|
public TruthTable createTruthTable() throws ExpressionException, FinitStateMachineException {
|
||||||
|
int stateBits = getStateVarBits();
|
||||||
|
|
||||||
|
// create state variables
|
||||||
|
ArrayList<Variable> vars = new ArrayList<>();
|
||||||
|
for (int i = stateBits - 1; i >= 0; i--)
|
||||||
|
vars.add(new Variable("Q^" + i + "_n"));
|
||||||
|
|
||||||
|
TruthTable truthTable = new TruthTable(vars);
|
||||||
|
|
||||||
|
// create the next state result variables
|
||||||
|
for (int i = stateBits - 1; i >= 0; i--)
|
||||||
|
truthTable.addResult("Q^" + i + "_n+1");
|
||||||
|
|
||||||
|
// add the output variables
|
||||||
|
TreeSet<String> results = new TreeSet<>();
|
||||||
|
for (State s : states)
|
||||||
|
results.addAll(s.getValues().keySet());
|
||||||
|
|
||||||
|
for (String name : results)
|
||||||
|
truthTable.addResult(name);
|
||||||
|
|
||||||
|
// set all to dc
|
||||||
|
truthTable.setAllTo(2);
|
||||||
|
|
||||||
|
// set output variables
|
||||||
|
for (State s : states) {
|
||||||
|
int row = s.getNumber();
|
||||||
|
int col = stateBits * 2;
|
||||||
|
for (String name : results) {
|
||||||
|
Long val = s.getValues().get(name);
|
||||||
|
long v = val == null ? 0 : val;
|
||||||
|
truthTable.setValue(row, col, (int) v);
|
||||||
|
col++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set all next state variables to "stay is state"
|
||||||
|
for (State s : states) {
|
||||||
|
int c = stateBits * 2;
|
||||||
|
int row = s.getNumber();
|
||||||
|
int m = row;
|
||||||
|
for (int j = 0; j < stateBits; j++) {
|
||||||
|
c--;
|
||||||
|
truthTable.setValue(row, c, m & 1);
|
||||||
|
m >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the additional input variables
|
||||||
|
VariableVisitor vv = new VariableVisitor();
|
||||||
|
for (Transition t : transitions)
|
||||||
|
if (t.getCondition() != null)
|
||||||
|
t.getCondition().traverse(vv);
|
||||||
|
ArrayList<Variable> inVars = new ArrayList<>(vv.getVariables());
|
||||||
|
|
||||||
|
for (Variable v : inVars)
|
||||||
|
truthTable.addVariable(v);
|
||||||
|
|
||||||
|
int rowsPerState = 1 << inVars.size();
|
||||||
|
|
||||||
|
// fill in the transitions
|
||||||
|
for (Transition t : transitions) {
|
||||||
|
int startState = t.getStartState().getNumber();
|
||||||
|
int startRow = startState * rowsPerState;
|
||||||
|
ContextMap c = new ContextMap();
|
||||||
|
for (int r = 0; r < rowsPerState; r++) {
|
||||||
|
int m = 1 << (inVars.size() - 1);
|
||||||
|
for (Variable v : inVars) {
|
||||||
|
c.set(v, (r & m) != 0);
|
||||||
|
m >>= 1;
|
||||||
|
}
|
||||||
|
if (t.getCondition() == null || t.getCondition().calculate(c)) {
|
||||||
|
int col = stateBits * 2 + inVars.size();
|
||||||
|
int row = startRow + r;
|
||||||
|
int mask = t.getTargetState().getNumber();
|
||||||
|
for (int j = 0; j < stateBits; j++) {
|
||||||
|
col--;
|
||||||
|
truthTable.setValue(row, col, mask & 1);
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return truthTable;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getStateVarBits() throws FinitStateMachineException {
|
||||||
|
HashSet<Integer> numbers = new HashSet<>();
|
||||||
|
int maxNumber = 0;
|
||||||
|
for (State s : states) {
|
||||||
|
final int n = s.getNumber();
|
||||||
|
if (n > maxNumber)
|
||||||
|
maxNumber = n;
|
||||||
|
|
||||||
|
if (numbers.contains(n))
|
||||||
|
throw new FinitStateMachineException(Lang.get("err_fsmNumberUsedTwice_N", n));
|
||||||
|
numbers.add(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!numbers.contains(0))
|
||||||
|
throw new FinitStateMachineException(Lang.get("err_fsmNoInitialState"));
|
||||||
|
|
||||||
|
int n = 1;
|
||||||
|
while ((1 << n) <= maxNumber) n++;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,4 +124,11 @@ public class State extends Movable {
|
|||||||
public int getNumber() {
|
public int getNumber() {
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the state value map
|
||||||
|
*/
|
||||||
|
public TreeMap<String, Long> getValues() {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,4 +121,25 @@ public class Transition extends Movable {
|
|||||||
setPos(fromState.getPos().add(toState.getPos()).mul(0.5f)
|
setPos(fromState.getPos().add(toState.getPos()).mul(0.5f)
|
||||||
.add(new VectorFloat((float) Math.random() - 0.5f, (float) Math.random() - 0.5f).mul(30)));
|
.add(new VectorFloat((float) Math.random() - 0.5f, (float) Math.random() - 0.5f).mul(30)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the condition
|
||||||
|
*/
|
||||||
|
public Expression getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the starting state
|
||||||
|
*/
|
||||||
|
public State getStartState() {
|
||||||
|
return fromState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the target state
|
||||||
|
*/
|
||||||
|
public State getTargetState() {
|
||||||
|
return toState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,11 @@ package de.neemann.digital.fsm.gui;
|
|||||||
import de.neemann.digital.analyse.expression.Expression;
|
import de.neemann.digital.analyse.expression.Expression;
|
||||||
import de.neemann.digital.analyse.parser.ParseException;
|
import de.neemann.digital.analyse.parser.ParseException;
|
||||||
import de.neemann.digital.analyse.parser.Parser;
|
import de.neemann.digital.analyse.parser.Parser;
|
||||||
|
import de.neemann.digital.draw.library.ElementLibrary;
|
||||||
|
import de.neemann.digital.draw.shapes.ShapeFactory;
|
||||||
import de.neemann.digital.fsm.FSM;
|
import de.neemann.digital.fsm.FSM;
|
||||||
import de.neemann.digital.fsm.State;
|
import de.neemann.digital.fsm.State;
|
||||||
|
import de.neemann.digital.gui.components.table.TableDialog;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@ -38,7 +41,6 @@ public class FSMDialog extends JDialog {
|
|||||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||||
this.fsm = fsm;
|
this.fsm = fsm;
|
||||||
|
|
||||||
|
|
||||||
fsmComponent = new FSMComponent(fsm);
|
fsmComponent = new FSMComponent(fsm);
|
||||||
getContentPane().add(fsmComponent);
|
getContentPane().add(fsmComponent);
|
||||||
pack();
|
pack();
|
||||||
@ -72,49 +74,43 @@ public class FSMDialog extends JDialog {
|
|||||||
* @throws Exception Exception
|
* @throws Exception Exception
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
/*
|
|
||||||
FSM fsm = new FSM()
|
|
||||||
.add(new State("initial").val("Y", 0))
|
|
||||||
.add(new State("1 match").val("Y", 0))
|
|
||||||
.add(new State("2 matches").val("Y", 0))
|
|
||||||
.add(new State("found").val("Y", 1))
|
|
||||||
.transition(0, 1, new Parser("!E").parse().get(0))
|
|
||||||
.transition(1, 2, new Parser("!E").parse().get(0))
|
|
||||||
.transition(2, 3, new Parser("E").parse().get(0))
|
|
||||||
|
|
||||||
.transition(1, 0, new Parser("E").parse().get(0))
|
|
||||||
.transition(3, 0, new Parser("E").parse().get(0))
|
|
||||||
.transition(3, 1, new Parser("!E").parse().get(0));*/
|
|
||||||
|
|
||||||
State top = new State("top");
|
State top = new State("top");
|
||||||
State topSet = new State("topSet").val("Y", 1);
|
State topSetLeft = new State("topSetLeft").val("L", 1);
|
||||||
|
State topSetRight = new State("topSetRight").val("R", 1);
|
||||||
State leftA = new State("leftA");
|
State leftA = new State("leftA");
|
||||||
State leftB = new State("leftB");
|
State leftB = new State("leftB");
|
||||||
State bottom = new State("bottom");
|
State bottom = new State("bottom");
|
||||||
State bottomSet = new State("bottomSet").val("Y", 1);
|
State bottomSetLeft = new State("bottomSetRight").val("R", 1);
|
||||||
|
State bottomSetRight = new State("bottomSetLeft").val("L", 1);
|
||||||
State rightA = new State("rightA");
|
State rightA = new State("rightA");
|
||||||
State rightB = new State("rightB");
|
State rightB = new State("rightB");
|
||||||
FSM fsm = new FSM(top, topSet, leftA, leftB, bottom, bottomSet, rightA, rightB)
|
FSM fsm = new FSM(top, topSetLeft, leftA, leftB, bottomSetLeft, bottom, bottomSetRight, rightB, rightA, topSetRight)
|
||||||
.transition(top, leftA, e("A & !B"))
|
.transition(top, leftA, e("A & !B"))
|
||||||
.transition(top, rightA, e("!A & B"))
|
.transition(top, rightA, e("!A & B"))
|
||||||
.transition(topSet, top, null)
|
.transition(topSetLeft, top, null)
|
||||||
|
.transition(topSetRight, top, null)
|
||||||
|
|
||||||
.transition(rightA, top, e("!A & !B"))
|
.transition(rightA, top, e("!A & !B"))
|
||||||
.transition(rightB, topSet, e("!A & !B"))
|
.transition(rightB, topSetRight, e("!A & !B"))
|
||||||
.transition(leftA, top, e("!A & !B"))
|
.transition(leftA, top, e("!A & !B"))
|
||||||
.transition(leftB, topSet, e("!A & !B"))
|
.transition(leftB, topSetLeft, e("!A & !B"))
|
||||||
|
|
||||||
.transition(bottom, leftB, e("A & !B"))
|
.transition(bottom, leftB, e("A & !B"))
|
||||||
.transition(bottom, rightB, e("!A & B"))
|
.transition(bottom, rightB, e("!A & B"))
|
||||||
.transition(bottomSet, bottom, null)
|
.transition(bottomSetLeft, bottom, null)
|
||||||
|
.transition(bottomSetRight, bottom, null)
|
||||||
|
|
||||||
.transition(rightB, bottom, e("A & B"))
|
.transition(rightB, bottom, e("A & B"))
|
||||||
.transition(rightA, bottomSet, e("A & B"))
|
.transition(rightA, bottomSetRight, e("A & B"))
|
||||||
.transition(leftB, bottom, e("A & B"))
|
.transition(leftB, bottom, e("A & B"))
|
||||||
.transition(leftA, bottomSet, e("A & B"));
|
.transition(leftA, bottomSetLeft, e("A & B"));
|
||||||
|
|
||||||
|
|
||||||
new FSMDialog(null, fsm).setVisible(true);
|
ElementLibrary lib = new ElementLibrary();
|
||||||
|
ShapeFactory shapeFactory = new ShapeFactory(lib);
|
||||||
|
new TableDialog(null, fsm.createTruthTable(), lib, shapeFactory, null).setVisible(true);
|
||||||
|
|
||||||
|
//new FSMDialog(null, fsm).setVisible(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user