From ec1511258d6859efbad14db6fcfb4cc5e5ba24a8 Mon Sep 17 00:00:00 2001 From: hneemann Date: Thu, 22 Nov 2018 12:44:28 +0100 Subject: [PATCH] added truth table generation --- src/main/java/de/neemann/digital/fsm/FSM.java | 124 +++++++++++++++++- .../java/de/neemann/digital/fsm/State.java | 7 + .../de/neemann/digital/fsm/Transition.java | 21 +++ .../de/neemann/digital/fsm/gui/FSMDialog.java | 46 +++---- 4 files changed, 172 insertions(+), 26 deletions(-) diff --git a/src/main/java/de/neemann/digital/fsm/FSM.java b/src/main/java/de/neemann/digital/fsm/FSM.java index 770f5d9ad..00203b144 100644 --- a/src/main/java/de/neemann/digital/fsm/FSM.java +++ b/src/main/java/de/neemann/digital/fsm/FSM.java @@ -5,11 +5,15 @@ */ 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.VectorFloat; +import de.neemann.digital.lang.Lang; import java.util.ArrayList; +import java.util.HashSet; +import java.util.TreeSet; /** * A simple finite state machine @@ -165,4 +169,122 @@ public class FSM { for (Transition t : transitions) 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 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 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 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 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; + } } diff --git a/src/main/java/de/neemann/digital/fsm/State.java b/src/main/java/de/neemann/digital/fsm/State.java index fd9192216..15228dfe7 100644 --- a/src/main/java/de/neemann/digital/fsm/State.java +++ b/src/main/java/de/neemann/digital/fsm/State.java @@ -124,4 +124,11 @@ public class State extends Movable { public int getNumber() { return number; } + + /** + * @return the state value map + */ + public TreeMap getValues() { + return values; + } } diff --git a/src/main/java/de/neemann/digital/fsm/Transition.java b/src/main/java/de/neemann/digital/fsm/Transition.java index af8a9bcda..3e7408f51 100644 --- a/src/main/java/de/neemann/digital/fsm/Transition.java +++ b/src/main/java/de/neemann/digital/fsm/Transition.java @@ -121,4 +121,25 @@ public class Transition extends Movable { setPos(fromState.getPos().add(toState.getPos()).mul(0.5f) .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; + } } diff --git a/src/main/java/de/neemann/digital/fsm/gui/FSMDialog.java b/src/main/java/de/neemann/digital/fsm/gui/FSMDialog.java index bbcc1283f..7c81f8cc7 100644 --- a/src/main/java/de/neemann/digital/fsm/gui/FSMDialog.java +++ b/src/main/java/de/neemann/digital/fsm/gui/FSMDialog.java @@ -8,8 +8,11 @@ package de.neemann.digital.fsm.gui; import de.neemann.digital.analyse.expression.Expression; import de.neemann.digital.analyse.parser.ParseException; 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.State; +import de.neemann.digital.gui.components.table.TableDialog; import javax.swing.*; import java.awt.*; @@ -38,7 +41,6 @@ public class FSMDialog extends JDialog { setDefaultCloseOperation(DISPOSE_ON_CLOSE); this.fsm = fsm; - fsmComponent = new FSMComponent(fsm); getContentPane().add(fsmComponent); pack(); @@ -72,49 +74,43 @@ public class FSMDialog extends JDialog { * @throws Exception 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 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 leftB = new State("leftB"); 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 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, rightA, e("!A & B")) - .transition(topSet, top, null) + .transition(topSetLeft, top, null) + .transition(topSetRight, top, null) .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(leftB, topSet, e("!A & !B")) + .transition(leftB, topSetLeft, e("!A & !B")) .transition(bottom, leftB, 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(rightA, bottomSet, e("A & B")) + .transition(rightA, bottomSetRight, 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); }