initial commit

This commit is contained in:
hneemann 2016-03-11 23:16:40 +01:00
commit 49ea08144e
20 changed files with 897 additions and 0 deletions

72
.gitignore vendored Normal file
View File

@ -0,0 +1,72 @@
# Created by .ignore support plugin (hsz.mobi)
### Java template
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Maven template
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties

211
pom.xml Normal file
View File

@ -0,0 +1,211 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.neemann.digital</groupId>
<artifactId>digital</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.org.slf4j>1.7.12</version.org.slf4j>
</properties>
<distributionManagement>
<site>
<id></id>
<url>file://${pom.basedir}/_stage</url>
</site>
</distributionManagement>
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.15</version>
<configuration>
<configLocation>sun_checks_neemann.xml</configLocation>
</configuration>
<reportSets>
<reportSet>
<reports>
<report>checkstyle</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.2</version>
<configuration>
<doclet>org.umlgraph.doclet.UmlGraphDoc</doclet>
<docletArtifact>
<groupId>org.umlgraph</groupId>
<artifactId>umlgraph</artifactId>
<version>5.6</version>
</docletArtifact>
<additionalparam>-views -all</additionalparam>
<useStandardDocletOptions>true</useStandardDocletOptions>
</configuration>
</plugin>
</plugins>
</reporting>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!--plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>de.neemann.assembler.gui.Main</mainClass>
</manifest>
<manifestEntries>
<Build-SCM-Revision>${buildNumber}</Build-SCM-Revision>
<Build-Time>${maven.build.timestamp}</Build-Time>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>true</doCheck>
<doUpdate>false</doUpdate>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>digital</finalName>
<appendAssemblyId>false</appendAssemblyId>
<attach>false</attach>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>de.neemann.assembler.gui.Main</mainClass>
</manifest>
<manifestEntries>
<Build-SCM-Revision>${buildNumber}</Build-SCM-Revision>
<Build-Time>${maven.build.timestamp}</Build-Time>
</manifestEntries>
</archive>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>install</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.2</version>
<executions>
<execution>
<id>script-chmod</id>
<phase>install</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>chmod</executable>
<arguments>
<argument>+x</argument>
<argument>target/digital.jar</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>script-cp</id>
<phase>install</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>cp</executable>
<arguments>
<argument>target/digital.jar</argument>
<argument>/home/hneemann/Dokumente/DHBW/Software/</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin-->
</plugins>
</build>
<dependencies>
<!--dependency>
<groupId>de.neemann.process</groupId>
<artifactId>utils</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<scm>
<connection>scm:git:file://localhost/${pom.basedir}</connection>
</scm>
</project>

View File

@ -0,0 +1,10 @@
package de.neemann.digital;
/**
* @author hneemann
*/
public class BitsException extends Exception {
public BitsException(String message) {
super(message);
}
}

View File

@ -0,0 +1,8 @@
package de.neemann.digital;
/**
* @author hneemann
*/
public interface Listener {
void needsUpdate() throws NodeException;
}

View File

@ -0,0 +1,80 @@
package de.neemann.digital;
import java.util.ArrayList;
import java.util.Collections;
/**
* @author hneemann
*/
public class Model {
private ArrayList<Node> nodes;
private ArrayList<Node> nodesToUpdateAct;
private ArrayList<Node> nodesToUpdateNext;
private int version;
private int maxCounter = 1000;
public Model() {
this.nodes = new ArrayList<>();
this.nodesToUpdateAct = new ArrayList<>();
this.nodesToUpdateNext = new ArrayList<>();
}
public int getVersion() {
return version;
}
public <T extends Node> T add(T node) {
nodes.add(node);
node.setModel(this);
return node;
}
public void addToUpdateList(Node node) {
nodesToUpdateNext.add(node);
}
public void doStep() throws NodeException {
doStep(false);
}
public void doStep(boolean noise) throws NodeException {
int counter = 0;
while (!nodesToUpdateNext.isEmpty()) {
version++;
// swap lists
ArrayList<Node> nl = nodesToUpdateNext;
nodesToUpdateNext = nodesToUpdateAct;
nodesToUpdateAct = nl;
nodesToUpdateNext.clear();
if (noise) {
Collections.shuffle(nodesToUpdateAct);
for (Node n : nodesToUpdateAct) {
n.readInputs();
n.writeOutputs();
}
} else {
for (Node n : nodesToUpdateAct) {
n.readInputs();
}
for (Node n : nodesToUpdateAct) {
n.writeOutputs();
}
}
if (counter++ > maxCounter) {
throw new NodeException("seemsToOscillate");
}
}
}
public void init() throws NodeException {
init(false);
}
public void init(boolean noise) throws NodeException {
nodesToUpdateNext.addAll(nodes);
doStep(noise);
}
}

View File

@ -0,0 +1,42 @@
package de.neemann.digital;
/**
* @author hneemann
*/
public abstract class Node implements Listener {
private Model model;
private int version;
public void setModel(Model model) {
this.model = model;
}
@Override
public void needsUpdate() throws NodeException {
if (model == null)
throw new NodeException("no model set");
if (model.getVersion() != version) {
model.addToUpdateList(this);
version = model.getVersion();
}
}
/**
* Only read the input!
* It is not allowed to write to the outputs!!!
*
* @throws NodeException
*/
public abstract void readInputs() throws NodeException;
/**
* Only write to the output!
* It is not allowed to read from the inputs!!!
*
* @throws NodeException
*/
public abstract void writeOutputs() throws NodeException;
}

View File

@ -0,0 +1,10 @@
package de.neemann.digital;
/**
* @author hneemann
*/
public class NodeException extends Exception {
public NodeException(String message) {
super(message);
}
}

View File

@ -0,0 +1,69 @@
package de.neemann.digital;
import java.util.ArrayList;
/**
* @author hneemann
*/
public class ObservableValue {
private final int bits;
private int value;
private ArrayList<Listener> listeners;
public ObservableValue(int bits) {
this.bits = bits;
listeners = new ArrayList<>();
}
public void addListener(Listener listener) throws NodeException {
listeners.add(listener);
}
public void removeListener(Listener listener) {
listeners.remove(listener);
}
public void hasChanged() throws NodeException {
for (Listener l : listeners) {
l.needsUpdate();
}
}
public int getValue() {
return value;
}
public void setValue(int value) throws NodeException {
if (this.value != value) {
this.value = value;
hasChanged();
}
}
public int getBits() {
return bits;
}
public int getValueBits() {
return getValueBits(value);
}
public int getValueBits(int value) {
return value & (1 << bits) - 1;
}
public void checkBits(ObservableValue value) throws BitsException {
if (value.getBits() != bits) {
throw new BitsException("needs " + bits + " bits, found " + value.getBits());
}
}
@Override
public String toString() {
return "ObservableValue{" +
"value=" + value +
", bits=" + bits +
'}';
}
}

View File

@ -0,0 +1,24 @@
package de.neemann.digital.basic;
import de.neemann.digital.ObservableValue;
import java.util.ArrayList;
/**
* @author hneemann
*/
public class And extends Function {
public And(int bits) {
super(bits);
}
@Override
protected int calculate(ArrayList<ObservableValue> inputs) {
int f = -1;
for (ObservableValue i : inputs) {
f &= i.getValue();
}
return f;
}
}

View File

@ -0,0 +1,52 @@
package de.neemann.digital.basic;
import de.neemann.digital.BitsException;
import de.neemann.digital.Node;
import de.neemann.digital.NodeException;
import de.neemann.digital.ObservableValue;
import java.util.ArrayList;
/**
* @author hneemann
*/
public abstract class Function extends Node {
private final ArrayList<ObservableValue> inputs;
private final ObservableValue output;
private int value;
public Function(int bits) {
output = new ObservableValue(bits);
inputs = new ArrayList<>();
}
public Function addInput(ObservableValue value) throws BitsException, NodeException {
output.checkBits(value);
inputs.add(value);
value.addListener(this);
return this;
}
public void removeInput(ObservableValue value) {
inputs.remove(value);
value.removeListener(this);
}
public ObservableValue getOutput() {
return output;
}
@Override
public void readInputs() throws NodeException {
value = calculate(inputs);
}
@Override
public void writeOutputs() throws NodeException {
output.setValue(value);
}
protected abstract int calculate(ArrayList<ObservableValue> inputs);
}

View File

@ -0,0 +1,24 @@
package de.neemann.digital.basic;
import de.neemann.digital.ObservableValue;
import java.util.ArrayList;
/**
* @author hneemann
*/
public class NAnd extends Function {
public NAnd(int bits) {
super(bits);
}
@Override
protected int calculate(ArrayList<ObservableValue> inputs) {
int f = -1;
for (ObservableValue i : inputs) {
f &= i.getValue();
}
return ~f;
}
}

View File

@ -0,0 +1,23 @@
package de.neemann.digital.basic;
import de.neemann.digital.ObservableValue;
import java.util.ArrayList;
/**
* @author hneemann
*/
public class NOr extends Function {
public NOr(int bits) {
super(bits);
}
@Override
protected int calculate(ArrayList<ObservableValue> inputs) {
int f = 0;
for (ObservableValue i : inputs) {
f |= i.getValue();
}
return ~f;
}
}

View File

@ -0,0 +1,31 @@
package de.neemann.digital.basic;
import de.neemann.digital.Node;
import de.neemann.digital.NodeException;
import de.neemann.digital.ObservableValue;
/**
* @author hneemann
*/
public class Not extends Node {
private final ObservableValue input;
private final ObservableValue output;
private int value;
public Not(ObservableValue input) throws NodeException {
this.input = input;
output = new ObservableValue(input.getBits());
input.addListener(this);
}
@Override
public void readInputs() throws NodeException {
value = input.getValue();
}
@Override
public void writeOutputs() throws NodeException {
output.setValue(~value);
}
}

View File

@ -0,0 +1,24 @@
package de.neemann.digital.basic;
import de.neemann.digital.ObservableValue;
import java.util.ArrayList;
/**
* @author hneemann
*/
public class Or extends Function {
public Or(int bits) {
super(bits);
}
@Override
protected int calculate(ArrayList<ObservableValue> inputs) {
int f = 0;
for (ObservableValue i : inputs) {
f |= i.getValue();
}
return f;
}
}

View File

@ -0,0 +1,58 @@
package de.neemann.digital;
import de.neemann.digital.basic.Function;
import de.neemann.digital.basic.NAnd;
import de.neemann.digital.basic.NOr;
import junit.framework.TestCase;
/**
* @author hneemann
*/
public class FlipFlops extends TestCase {
public void testFlipFlopNOr() throws Exception {
ObservableValue r = new ObservableValue(1);
ObservableValue s = new ObservableValue(1);
Model model = new Model();
Function a1 = model.add(new NOr(1)).addInput(r);
Function a2 = model.add(new NOr(1)).addInput(s);
a1.addInput(a2.getOutput());
a2.addInput(a1.getOutput());
TestExecuter sc = new TestExecuter(model, true).setInputs(r, s).setOutputs(a1.getOutput(), a2.getOutput());
sc.check(0, 1, 1, 0);
sc.check(0, 0, 1, 0);
sc.check(1, 0, 0, 1);
sc.check(0, 0, 0, 1);
sc.check(0, 1, 1, 0);
sc.check(1, 1, 0, 0); // verbotener Zustand!!
r.setValue(0); // gehe aus verbotenem Zustand raus!!!
s.setValue(0);
model.doStep(true); // geht nur mit noise!
assertTrue((a1.getOutput().getValueBits() == 1 && a2.getOutput().getValueBits() == 0) || // endzustand ist undefiniert!
(a1.getOutput().getValueBits() == 0 && a2.getOutput().getValueBits() == 1));
}
public void testFlipFlopNAnd() throws Exception {
ObservableValue r = new ObservableValue(1);
ObservableValue s = new ObservableValue(1);
Model model = new Model();
Function a1 = model.add(new NAnd(1)).addInput(r);
Function a2 = model.add(new NAnd(1)).addInput(s);
a1.addInput(a2.getOutput());
a2.addInput(a1.getOutput());
TestExecuter sc = new TestExecuter(model).setInputs(r, s).setOutputs(a1.getOutput(), a2.getOutput());
sc.check(1, 0, 0, 1);
sc.check(1, 1, 0, 1);
sc.check(0, 1, 1, 0);
sc.check(1, 1, 1, 0);
sc.check(1, 0, 0, 1);
}
}

View File

@ -0,0 +1,44 @@
package de.neemann.digital;
import static org.junit.Assert.assertEquals;
/**
* @author hneemann
*/
public class TestExecuter {
private final Model model;
private ObservableValue[] inputs;
private ObservableValue[] outputs;
public TestExecuter(Model model) throws NodeException {
this(model, false);
}
public TestExecuter(Model model, boolean noise) throws NodeException {
this.model = model;
model.init(noise);
}
public TestExecuter setInputs(ObservableValue... values) {
inputs = values;
return this;
}
public TestExecuter setOutputs(ObservableValue... values) {
outputs = values;
return this;
}
public void check(int... val) throws NodeException {
for (int i = 0; i < inputs.length; i++) {
inputs[i].setValue(val[i]);
}
model.doStep();
for (int i = 0; i < outputs.length; i++) {
assertEquals("Value " + i, outputs[i].getValueBits(val[i + inputs.length]), outputs[i].getValueBits());
}
}
}

View File

@ -0,0 +1,29 @@
package de.neemann.digital.basic;
import de.neemann.digital.Model;
import de.neemann.digital.ObservableValue;
import de.neemann.digital.TestExecuter;
import junit.framework.TestCase;
/**
* @author hneemann
*/
public class AndTest extends TestCase {
public void testAnd() throws Exception {
ObservableValue a = new ObservableValue(1);
ObservableValue b = new ObservableValue(1);
Model model = new Model();
Function and = model.add(new And(1)).addInput(a).addInput(b);
TestExecuter sc = new TestExecuter(model).setInputs(a, b).setOutputs(and.getOutput());
sc.check(0, 0, 0);
sc.check(1, 0, 0);
sc.check(0, 1, 0);
sc.check(1, 1, 1);
sc.check(1, 0, 0);
sc.check(0, 1, 0);
}
}

View File

@ -0,0 +1,28 @@
package de.neemann.digital.basic;
import de.neemann.digital.Model;
import de.neemann.digital.ObservableValue;
import de.neemann.digital.TestExecuter;
import junit.framework.TestCase;
/**
* @author hneemann
*/
public class NAndTest extends TestCase {
public void testAnd() throws Exception {
ObservableValue a = new ObservableValue(1);
ObservableValue b = new ObservableValue(1);
Model model = new Model();
Function nand = model.add(new NAnd(1)).addInput(a).addInput(b);
TestExecuter sc = new TestExecuter(model).setInputs(a, b).setOutputs(nand.getOutput());
sc.check(0, 0, 1);
sc.check(1, 0, 1);
sc.check(0, 1, 1);
sc.check(1, 1, 0);
sc.check(1, 0, 1);
sc.check(0, 1, 1);
}
}

View File

@ -0,0 +1,29 @@
package de.neemann.digital.basic;
import de.neemann.digital.Model;
import de.neemann.digital.ObservableValue;
import de.neemann.digital.TestExecuter;
import junit.framework.TestCase;
/**
* @author hneemann
*/
public class NOrTest extends TestCase {
public void testNOr() throws Exception {
ObservableValue a = new ObservableValue(1);
ObservableValue b = new ObservableValue(1);
Model model = new Model();
Function nor = model.add(new NOr(1)).addInput(a).addInput(b);
TestExecuter sc = new TestExecuter(model).setInputs(a, b).setOutputs(nor.getOutput());
sc.check(0, 0, 1);
sc.check(1, 0, 0);
sc.check(0, 1, 0);
sc.check(1, 1, 0);
sc.check(1, 0, 0);
sc.check(0, 1, 0);
sc.check(0, 0, 1);
}
}

View File

@ -0,0 +1,29 @@
package de.neemann.digital.basic;
import de.neemann.digital.Model;
import de.neemann.digital.ObservableValue;
import de.neemann.digital.TestExecuter;
import junit.framework.TestCase;
/**
* @author hneemann
*/
public class OrTest extends TestCase {
public void testOr() throws Exception {
ObservableValue a = new ObservableValue(1);
ObservableValue b = new ObservableValue(1);
Model model = new Model();
Function and = model.add(new Or(1)).addInput(a).addInput(b);
TestExecuter sc = new TestExecuter(model).setInputs(a, b).setOutputs(and.getOutput());
sc.check(0, 0, 0);
sc.check(1, 0, 1);
sc.check(0, 1, 1);
sc.check(1, 1, 1);
sc.check(1, 0, 1);
sc.check(0, 1, 1);
sc.check(0, 0, 0);
}
}