added a counter creator

This commit is contained in:
hneemann 2018-11-25 12:22:30 +01:00
parent 0938102cf7
commit 42d159f853
12 changed files with 344 additions and 55 deletions

1
.gitattributes vendored
View File

@ -1,5 +1,6 @@
*.java text eol=lf
*.xml text eol=lf
*.dig text eol=lf
*.fsm text eol=lf
*.tem text eol=lf
*.v text eol=lf

View File

@ -114,6 +114,13 @@
<include>*.dig</include>
</includes>
</fileSet>
<fileSet>
<directory>${basedir}/src/main/fsm</directory>
<outputDirectory>/examples/fsm/</outputDirectory>
<includes>
<include>*.fsm</include>
</includes>
</fileSet>
<fileSet>
<directory>${basedir}/target/docu</directory>
<outputDirectory>/docu/</outputDirectory>

View File

@ -0,0 +1,210 @@
<?xml version="1.0" encoding="utf-8"?>
<fsm>
<states>
<state>
<position x="0.0" y="-600.0"/>
<number>0</number>
<name>0</name>
<radius>90</radius>
<values>S=0111111</values>
</state>
<state>
<position x="360.0" y="-480.0"/>
<number>1</number>
<name>1</name>
<radius>90</radius>
<values>S=0000110</values>
</state>
<state>
<position x="540.0" y="-180.0"/>
<number>2</number>
<name>2</name>
<radius>90</radius>
<values>S=1011011</values>
</state>
<state>
<position x="540.0" y="180.0"/>
<number>3</number>
<name>3</name>
<radius>90</radius>
<values>S=1001111</values>
</state>
<state>
<position x="360.0" y="480.0"/>
<number>4</number>
<name>4</name>
<radius>90</radius>
<values>S=1100110</values>
</state>
<state>
<position x="0.0" y="600.0"/>
<number>5</number>
<name>5</name>
<radius>90</radius>
<values>S=1101101</values>
</state>
<state>
<position x="-360.0" y="480.0"/>
<number>6</number>
<name>6</name>
<radius>90</radius>
<values>S=1111101</values>
</state>
<state>
<position x="-540.0" y="180.0"/>
<number>7</number>
<name>7</name>
<radius>90</radius>
<values>S=0000111</values>
</state>
<state>
<position x="-540.0" y="-180.0"/>
<number>8</number>
<name>8</name>
<radius>90</radius>
<values>S=1111111</values>
</state>
<state>
<position x="-360.0" y="-480.0"/>
<number>9</number>
<name>9</name>
<radius>90</radius>
<values>S=1101111</values>
</state>
</states>
<transitions>
<transition>
<position x="212.46335" y="-637.39"/>
<fromState reference="../../../states/state"/>
<toState reference="../../../states/state[2]"/>
<condition>en=1 &amp; clr=0</condition>
<values></values>
</transition>
<transition>
<position x="514.7641" y="-368.85846"/>
<fromState reference="../../../states/state[2]"/>
<toState reference="../../../states/state[3]"/>
<condition>en=1 &amp; clr=0</condition>
<values></values>
</transition>
<transition>
<position x="602.36884" y="0.0"/>
<fromState reference="../../../states/state[3]"/>
<toState reference="../../../states/state[4]"/>
<condition>en=1 &amp; clr=0</condition>
<values></values>
</transition>
<transition>
<position x="504.7352" y="362.84113"/>
<fromState reference="../../../states/state[4]"/>
<toState reference="../../../states/state[5]"/>
<condition>en=1 &amp; clr=0</condition>
<values></values>
</transition>
<transition>
<position x="196.05003" y="588.1501"/>
<fromState reference="../../../states/state[5]"/>
<toState reference="../../../states/state[6]"/>
<condition>en=1 &amp; clr=0</condition>
<values></values>
</transition>
<transition>
<position x="-196.05022" y="588.15063"/>
<fromState reference="../../../states/state[6]"/>
<toState reference="../../../states/state[7]"/>
<condition>en=1 &amp; clr=0</condition>
<values></values>
</transition>
<transition>
<position x="-504.73566" y="362.8414"/>
<fromState reference="../../../states/state[7]"/>
<toState reference="../../../states/state[8]"/>
<condition>en=1 &amp; clr=0</condition>
<values></values>
</transition>
<transition>
<position x="-602.37085" y="0.0"/>
<fromState reference="../../../states/state[8]"/>
<toState reference="../../../states/state[9]"/>
<condition>en=1 &amp; clr=0</condition>
<values></values>
</transition>
<transition>
<position x="-514.77814" y="-368.86688"/>
<fromState reference="../../../states/state[9]"/>
<toState reference="../../../states/state[10]"/>
<condition>en=1 &amp; clr=0</condition>
<values></values>
</transition>
<transition>
<position x="-212.45769" y="-637.37305"/>
<fromState reference="../../../states/state[10]"/>
<toState reference="../../../states/state"/>
<condition>en=1 &amp; clr=0</condition>
<values>ov=1</values>
</transition>
<transition>
<position x="181.09329" y="-543.27985"/>
<fromState reference="../../../states/state[2]"/>
<toState reference="../../../states/state"/>
<condition>clr=1</condition>
<values></values>
</transition>
<transition>
<position x="241.62177" y="-353.5137"/>
<fromState reference="../../../states/state[3]"/>
<toState reference="../../../states/state"/>
<condition>clr=1</condition>
<values></values>
</transition>
<transition>
<position x="255.40965" y="-199.89899"/>
<fromState reference="../../../states/state[4]"/>
<toState reference="../../../states/state"/>
<condition>clr=1</condition>
<values></values>
</transition>
<transition>
<position x="171.23235" y="-57.07745"/>
<fromState reference="../../../states/state[5]"/>
<toState reference="../../../states/state"/>
<condition>clr=1</condition>
<values></values>
</transition>
<transition>
<position x="-0.0013983508" y="0.0"/>
<fromState reference="../../../states/state[6]"/>
<toState reference="../../../states/state"/>
<condition>clr=1</condition>
<values></values>
</transition>
<transition>
<position x="-171.24753" y="-57.082508"/>
<fromState reference="../../../states/state[7]"/>
<toState reference="../../../states/state"/>
<condition>clr=1</condition>
<values></values>
</transition>
<transition>
<position x="-255.4202" y="-199.9063"/>
<fromState reference="../../../states/state[8]"/>
<toState reference="../../../states/state"/>
<condition>clr=1</condition>
<values></values>
</transition>
<transition>
<position x="-241.6123" y="-353.50153"/>
<fromState reference="../../../states/state[9]"/>
<toState reference="../../../states/state"/>
<condition>clr=1</condition>
<values></values>
</transition>
<transition>
<position x="-181.08603" y="-543.25806"/>
<fromState reference="../../../states/state[10]"/>
<toState reference="../../../states/state"/>
<condition>clr=1</condition>
<values></values>
</transition>
</transitions>
</fsm>

View File

@ -302,12 +302,13 @@ public class FSM {
*/
public FSM circle() {
double delta = 2 * Math.PI / states.size();
double rad = 0;
double circumference = 0;
for (State s : states)
if (s.getVisualRadius() > rad)
rad = s.getVisualRadius();
circumference += s.getVisualRadius() * 2;
circumference += states.size() * State.DEFAULT_RAD * 2;
double rad = circumference / Math.PI / 2;
rad *= 4;
double phi = 0;
for (State s : states) {
s.setPosition(new VectorFloat((float) (Math.sin(phi) * rad), (float) (-Math.cos(phi) * rad)));

View File

@ -14,9 +14,12 @@ import java.util.TreeMap;
* Represents a state
*/
public class State extends Movable {
private static final int RASTER = 60;
/**
* The default state radius
*/
public static final int DEFAULT_RAD = 70;
private static final int RAD = 70;
private static final int RASTER = 60;
private static final float REACH = 2000;
private static final int INIT_RADIUS = 20;
@ -35,7 +38,7 @@ public class State extends Movable {
public State(String name) {
super();
this.name = name;
this.radius = RAD;
this.radius = DEFAULT_RAD;
}
/**
@ -151,7 +154,7 @@ public class State extends Movable {
/**
* @return the radius of the state
*/
float getVisualRadius() {
public int getVisualRadius() {
if (isInitialState())
return INIT_RADIUS;
else
@ -165,6 +168,15 @@ public class State extends Movable {
return radius;
}
/**
* Sets the radius of the state
*
* @param radius the radius
*/
public void setRadius(int radius) {
this.radius = radius;
}
/**
* Sets the number of the state
*

View File

@ -24,7 +24,7 @@ public class Transition extends Movable {
private final State fromState;
private final State toState;
private String condition = "";
private String condition;
private String values = "";
private transient Expression conditionExpression;
private transient TreeMap<String, Integer> valuesMap;
@ -41,7 +41,7 @@ public class Transition extends Movable {
super();
this.fromState = fromState;
this.toState = toState;
this.condition = condition;
this.condition = condition == null ? "" : condition;
initPos();
}
@ -168,7 +168,7 @@ public class Transition extends Movable {
this.condition = condition;
wasModified();
conditionExpression = null;
if (getFsm()!=null)
if (getFsm() != null)
getFsm().resetInitInitialization();
}
}

View File

@ -82,7 +82,7 @@ public class TransitionTableCreator {
}
}
// set all next state variables to "stay is state"
// set all next state results to "stay is state"
for (State s : states) {
int c = stateBits * 2;
int row = s.getNumber();
@ -137,7 +137,7 @@ public class TransitionTableCreator {
int col = stateBits * 2 + inVars.size();
int row = startRow + r;
checkRow(row, t);
checkRow(row, t); // allow only deterministic transitions
// fill in transition
int mask = t.getTargetState().getNumber();
@ -150,7 +150,7 @@ public class TransitionTableCreator {
// fill in output state, if any
final TreeMap<String, Integer> valueMap = t.getValueMap();
if (!valueMap.isEmpty()) {
col = stateBits * 2 + results.size();
col = stateBits * 2 + inVars.size();
for (String name : results) {
Integer val = valueMap.get(name);
if (val != null)
@ -163,11 +163,9 @@ public class TransitionTableCreator {
}
private void checkRow(int row, Transition t) throws FiniteStateMachineException {
if (transitionSet != null) {
if (transitionSet[row])
throw new FiniteStateMachineException(Lang.get("err_notDeterministic_N", t.toString()));
transitionSet[row] = true;
}
if (transitionSet[row])
throw new FiniteStateMachineException(Lang.get("err_notDeterministic_N", t.toString()));
transitionSet[row] = true;
}
private int getStateVarBits() throws FiniteStateMachineException {

View File

@ -35,6 +35,8 @@ public class FSMComponent extends JComponent {
private static final Key<Integer> KEY_NUMBER = new Key.KeyInteger("stateNum", 0);
private static final Key<String> KEY_VALUES = new Key<>("stateValues", "");
private static final Key<String> KEY_CONDITION = new Key<>("transCond", "");
private static final Key<Integer> KEY_RADIUS = new Key.KeyInteger("transRad", 70)
.setComboBoxValues(50, 70, 90);
private static final String DEL_ACTION = "myDelAction";
private Mouse mouse = Mouse.getMouse();
@ -198,14 +200,16 @@ public class FSMComponent extends JComponent {
ElementAttributes attr = new ElementAttributes()
.set(KEY_NUMBER, state.getNumber())
.set(KEY_VALUES, state.getValues())
.set(KEY_RADIUS, state.getVisualRadius())
.set(Keys.LABEL, state.getName());
SwingUtilities.convertPointToScreen(point, this);
AttributeDialog ad = new AttributeDialog(SwingUtilities.getWindowAncestor(this),
point, attr, Keys.LABEL, KEY_NUMBER, KEY_VALUES);
point, attr, Keys.LABEL, KEY_NUMBER, KEY_VALUES, KEY_RADIUS);
ElementAttributes newAttr = ad.showDialog();
if (newAttr != null) {
state.setNumber(newAttr.get(KEY_NUMBER));
state.setValues(newAttr.get(KEY_VALUES));
state.setRadius(newAttr.get(KEY_RADIUS));
state.setName(newAttr.get(Keys.LABEL));
repaint();
}

View File

@ -95,19 +95,7 @@ public class FSMFrame extends JFrame implements ClosingWindowListener.ConfirmSav
toolBar.addSeparator();
createViewMenu(bar, toolBar);
toolBar.addSeparator();
JMenu create = new JMenu(Lang.get("menu_fsm_create"));
bar.add(create);
create.add(new ToolTipAction(Lang.get("menu_fsm_create_table")) {
@Override
public void actionPerformed(ActionEvent actionEvent) {
try {
new TableDialog(FSMFrame.this, fsm.createTruthTable(), library, null).setVisible(true);
} catch (Exception e) {
new ErrorMessage(Lang.get("msg_fsmCantCreateTable")).addCause(e).show(FSMFrame.this);
}
}
}.createJMenuItem());
createCreateMenu(bar, library);
moveControl = new JComboBox<>(new String[]{
@ -280,6 +268,7 @@ public class FSMFrame extends JFrame implements ClosingWindowListener.ConfirmSav
private void saveFile(File file) {
try {
moveControl.setSelectedIndex(0);
fsm.save(file);
setFilename(file);
save.setEnabled(false);
@ -329,6 +318,36 @@ public class FSMFrame extends JFrame implements ClosingWindowListener.ConfirmSav
view.add(zoomIn.createJMenuItem());
}
private void createCreateMenu(JMenuBar bar, ElementLibrary library) {
JMenu create = new JMenu(Lang.get("menu_fsm_create"));
bar.add(create);
create.add(new ToolTipAction(Lang.get("menu_fsm_create_table")) {
@Override
public void actionPerformed(ActionEvent actionEvent) {
try {
new TableDialog(FSMFrame.this, fsm.createTruthTable(), library, null).setVisible(true);
} catch (Exception e) {
new ErrorMessage(Lang.get("msg_fsmCantCreateTable")).addCause(e).show(FSMFrame.this);
}
}
}.createJMenuItem());
JMenu counter = new JMenu(Lang.get("menu_fsm_create_counter"));
create.add(counter);
int[] counterValues = new int[]{4, 5, 6, 7, 8, 10, 16};
for (int n : counterValues) {
counter.add(new ToolTipAction(Lang.get("menu_fsm_create_counter_N", n)) {
@Override
public void actionPerformed(ActionEvent actionEvent) {
if (ClosingWindowListener.checkForSave(FSMFrame.this, FSMFrame.this)) {
setFSM(FSMDemos.counter(n).circle().setModified(false));
setFilename(null);
}
}
});
}
}
private class ExportAction extends ToolTipAction {
private final String name;
private final String suffix;

View File

@ -1755,11 +1755,26 @@ Daher steht auch das Signal 'D_out' zur Verfügung, um in diesem Fall den Wert z
</body></html>]]></string>
<string name="fsm_title">Endlicher Automat</string>
<string name="fsm_noMove">keine Bewegung</string>
<string name="fsm_moveTrans">Übergänge</string>
<string name="fsm_moveStates">Übergänge+Zustände</string>
<string name="menu_fsm">Endlicher Automat</string>
<string name="menu_fsm_tt">Dialog für die Erstellung endlicher Automaten.</string>
<string name="fsm_title">Endlicher Automat</string>
<string name="menu_fsm_create">Erzeugen</string>
<string name="menu_fsm_create_table">Zustandsübergangstabelle</string>
<string name="menu_fsm_create_counter">Zähler erzeugen</string>
<string name="menu_fsm_create_counter_N">{0} Zustände</string>
<string name="key_stateNum">Zustandsnummer</string>
<string name="key_stateNum_tt">Die Nummer welche diesen Zustand representiert.</string>
<string name="key_stateValues">Ausgänge</string>
<string name="key_stateValues_tt">Legt Ausgangswerte fest. Wird nichts angegeben, werden alle Werte auf Null gesetzt.
Mit einfachen Zuweisungen wie "A=1, B=0" können Ausgänge gesetzt werden.
</string>
<string name="key_transCond">Bedingung</string>
<string name="key_transCond_tt">Ein boolscher Ausdruck.</string>
<string name="key_transRad">Radius</string>
<string name="key_transRad_tt">Radius des Kreises in der Darstellung.</string>
<string name="err_notDeterministic_N">Der Automat ist nicht deterministisch: {0}</string>
<string name="err_fsmNumberUsedTwice_N">Zustandsnummer {0} ist nicht eindeutig.</string>
<string name="err_fsmNoInitialState">Es gibt keinen Initialzustand.</string>
@ -1768,18 +1783,6 @@ Daher steht auch das Signal 'D_out' zur Verfügung, um in diesem Fall den Wert z
<string name="err_fsmErrorInCondition_N">Fehler in Bedingung ''{0}''!</string>
<string name="msg_fsm_errorLoadingFile">Fehler beim Laden der Datei!</string>
<string name="msg_fsm_errorStoringFile">Fehler beim Speichern der Datei!</string>
<string name="key_stateNum">Zustandsnummer</string>
<string name="key_stateNum_tt">Die Nummer welche diesen Zustand representiert.</string>
<string name="key_stateValues">Ausgänge</string>
<string name="key_stateValues_tt">Legt Ausgangswerte fest. Wird nichts angegeben, werden alle Werte auf Null gesetzt.
Mit einfachen Zuweisungen wie "A=1, B=0" können Ausgänge gesetzt werden.
</string>
<string name="msg_fsmCantCreateTable">Zustandsübergangstabelle kann nicht erzeugt werden.</string>
<string name="key_transCond">Bedingung</string>
<string name="key_transCond_tt">Ein boolscher Ausdruck.</string>
<string name="msg_fsmNewState">Neuer Zustand</string>
<string name="fsm_noMove">keine Bewegung</string>
<string name="fsm_moveTrans">Übergänge</string>
<string name="fsm_moveStates">Übergänge+Zustände</string>
<string name="msg_fsmCantCreateTable">Zustandsübergangstabelle kann nicht erzeugt werden.</string>
</resources>

View File

@ -1734,32 +1734,35 @@ Therefore, the signal 'D_out' is also available to check the value in this case.
</body></html>]]></string>
<string name="fsm_title">Finite State Machine</string>
<string name="fsm_noMove">no movement</string>
<string name="fsm_moveTrans">Transitions</string>
<string name="fsm_moveStates">Transitions+States</string>
<string name="menu_fsm">Finite State Machine</string>
<string name="menu_fsm_tt">Opens a Dialog to Edit a Finite State Machine.</string>
<string name="fsm_title">Finite State Machine</string>
<string name="menu_fsm_create">Create</string>
<string name="menu_fsm_create_table">State Transition Table</string>
<string name="menu_fsm_create_counter">Create Counter</string>
<string name="menu_fsm_create_counter_N">{0} States</string>
<string name="err_notDeterministic_N">The FSM is not deterministic: {0}</string>
<string name="err_fsmNumberUsedTwice_N">State Number {0} used twice.</string>
<string name="err_fsmNoInitialState">There is no initial state (state number zero).</string>
<string name="err_fsmState_N_notFound">State ''{0}'' not found!</string>
<string name="err_fsmInvalidOutputAssignment_N">Wrong assignment to output (''{0}'')!</string>
<string name="err_fsmErrorInCondition_N">Error in condition ''{0}''!</string>
<string name="msg_fsm_errorLoadingFile">Error loading a file!</string>
<string name="msg_fsm_errorStoringFile">Error storing a file!</string>
<string name="key_stateNum">State Number</string>
<string name="key_stateNum_tt">The number which represents this state.</string>
<string name="key_stateValues">Outputs</string>
<string name="key_stateValues_tt">Defines the output values. If nothing is specified, all values are set to zero.
With simple assignments like "A=1, B=0" outputs can be set.
</string>
<string name="msg_fsmCantCreateTable">Can not create state transition table.</string>
<string name="key_transCond">Condition</string>
<string name="key_transCond_tt">A boolean expression.</string>
<string name="key_transRad">Radius</string>
<string name="key_transRad_tt">Radius of the circle in the diagram.</string>
<string name="msg_fsmCantCreateTable">Can not create state transition table.</string>
<string name="msg_fsmNewState">New State</string>
<string name="fsm_noMove">no movement</string>
<string name="fsm_moveTrans">Transitions</string>
<string name="fsm_moveStates">Transitions+States</string>
<string name="msg_fsm_errorLoadingFile">Error loading a file!</string>
<string name="msg_fsm_errorStoringFile">Error storing a file!</string>
</resources>

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018 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.fsm;
import de.neemann.digital.analyse.expression.ExpressionException;
import de.neemann.digital.integration.FileScanner;
import de.neemann.digital.integration.Resources;
import junit.framework.TestCase;
import java.io.File;
import java.io.IOException;
public class IntegrationTest extends TestCase {
public void testExamples() throws Exception {
File examples = new File(Resources.getRoot().getParentFile().getParentFile(), "/main/fsm");
assertEquals(7, new FileScanner(this::check).setSuffix("fsm").scan(examples));
}
/*
* For now, only create the truth table.
* Does not test if the truth table is correct!
*/
private void check(File file) throws IOException, ExpressionException, FiniteStateMachineException {
FSM.loadFSM(file).createTruthTable();
}
}