mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-15 15:58:41 -04:00
improved the LUT circuit builder
This commit is contained in:
parent
1bd11674c7
commit
b57e79b99f
@ -8,6 +8,7 @@ package de.neemann.digital.analyse.expression;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Represents a variable as part of an expression.
|
||||||
*/
|
*/
|
||||||
public class Variable implements Comparable<Variable>, Expression {
|
public class Variable implements Comparable<Variable>, Expression {
|
||||||
|
|
||||||
@ -49,6 +50,26 @@ public class Variable implements Comparable<Variable>, Expression {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given expression is a variable.
|
||||||
|
*
|
||||||
|
* @param e the expression
|
||||||
|
* @return true if the given expression is a variable.
|
||||||
|
*/
|
||||||
|
public static boolean isVar(Expression e) {
|
||||||
|
return e instanceof Variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given expression is a variable or a inverted variable.
|
||||||
|
*
|
||||||
|
* @param e the expression
|
||||||
|
* @return true if the given expression is a variable or a inverted variable.
|
||||||
|
*/
|
||||||
|
public static boolean isVarOrNotVar(Expression e) {
|
||||||
|
return isVar(e) || (e instanceof Not && isVar(((Not) e).getExpression()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new intsnce
|
* Creates a new intsnce
|
||||||
*
|
*
|
||||||
|
@ -37,6 +37,8 @@ import de.neemann.digital.lang.Lang;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static de.neemann.digital.analyse.expression.Variable.isVar;
|
||||||
|
import static de.neemann.digital.analyse.expression.Variable.isVarOrNotVar;
|
||||||
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
|
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -207,16 +209,13 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
|
|||||||
|
|
||||||
private Fragment createFragment(Expression expression) throws BuilderException {
|
private Fragment createFragment(Expression expression) throws BuilderException {
|
||||||
if (useLUT) {
|
if (useLUT) {
|
||||||
if (expression instanceof Variable)
|
if (isVarOrNotVar(expression) || expression instanceof Constant)
|
||||||
return createBasicFragment(expression);
|
|
||||||
|
|
||||||
if (expression instanceof Not && ((Not) expression).getExpression() instanceof Variable)
|
|
||||||
return createBasicFragment(expression);
|
return createBasicFragment(expression);
|
||||||
|
|
||||||
if (expression instanceof Operation) {
|
if (expression instanceof Operation) {
|
||||||
boolean allVars = true;
|
boolean allVars = true;
|
||||||
for (Expression ex : ((Operation) expression).getExpressions()) {
|
for (Expression ex : ((Operation) expression).getExpressions()) {
|
||||||
if (!(ex instanceof Variable || (ex instanceof Not && ((Not) ex).getExpression() instanceof Variable)))
|
if (!isVarOrNotVar(ex))
|
||||||
allVars = false;
|
allVars = false;
|
||||||
}
|
}
|
||||||
if (allVars)
|
if (allVars)
|
||||||
@ -251,6 +250,11 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isXor(data.getData()))
|
||||||
|
return new FragmentExpression(frags, new FragmentVisualElement(XOr.DESCRIPTION, frags.size(), shapeFactory));
|
||||||
|
else if (isXNor(data.getData()))
|
||||||
|
return new FragmentExpression(frags, new FragmentVisualElement(XNOr.DESCRIPTION, frags.size(), shapeFactory));
|
||||||
|
else {
|
||||||
lutNumber++;
|
lutNumber++;
|
||||||
return new FragmentExpression(frags, new FragmentVisualElement(LookUpTable.DESCRIPTION, frags.size(), shapeFactory)
|
return new FragmentExpression(frags, new FragmentVisualElement(LookUpTable.DESCRIPTION, frags.size(), shapeFactory)
|
||||||
.setAttr(Keys.LABEL, "L" + lutNumber)
|
.setAttr(Keys.LABEL, "L" + lutNumber)
|
||||||
@ -258,6 +262,21 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
|
|||||||
.setAttr(Keys.DATA, data)
|
.setAttr(Keys.DATA, data)
|
||||||
.setAttr(Keys.BITS, 1));
|
.setAttr(Keys.BITS, 1));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isXNor(long[] data) {
|
||||||
|
for (int i = 0; i < data.length; i++)
|
||||||
|
if ((Integer.bitCount(i) & 1) == data[i])
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isXor(long[] data) {
|
||||||
|
for (int i = 0; i < data.length; i++)
|
||||||
|
if (!((Integer.bitCount(i) & 1) == data[i]))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private Fragment createBasicFragment(Expression expression) throws BuilderException {
|
private Fragment createBasicFragment(Expression expression) throws BuilderException {
|
||||||
if (expression instanceof Operation) {
|
if (expression instanceof Operation) {
|
||||||
@ -273,7 +292,7 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
|
|||||||
throw new BuilderException(Lang.get("err_builder_operationNotSupported", op.getClass().getSimpleName()));
|
throw new BuilderException(Lang.get("err_builder_operationNotSupported", op.getClass().getSimpleName()));
|
||||||
} else if (expression instanceof Not) {
|
} else if (expression instanceof Not) {
|
||||||
Not n = (Not) expression;
|
Not n = (Not) expression;
|
||||||
if (n.getExpression() instanceof Variable) {
|
if (isVar(n.getExpression())) {
|
||||||
FragmentVariable fragmentVariable = new FragmentVariable((Variable) n.getExpression(), true);
|
FragmentVariable fragmentVariable = new FragmentVariable((Variable) n.getExpression(), true);
|
||||||
fragmentVariables.add(fragmentVariable);
|
fragmentVariables.add(fragmentVariable);
|
||||||
return fragmentVariable;
|
return fragmentVariable;
|
||||||
@ -288,7 +307,7 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
|
|||||||
return new FragmentExpression(frags, new FragmentVisualElement(XNOr.DESCRIPTION, frags.size(), shapeFactory));
|
return new FragmentExpression(frags, new FragmentVisualElement(XNOr.DESCRIPTION, frags.size(), shapeFactory));
|
||||||
}
|
}
|
||||||
return new FragmentExpression(createBasicFragment(n.getExpression()), new FragmentVisualElement(de.neemann.digital.core.basic.Not.DESCRIPTION, shapeFactory));
|
return new FragmentExpression(createBasicFragment(n.getExpression()), new FragmentVisualElement(de.neemann.digital.core.basic.Not.DESCRIPTION, shapeFactory));
|
||||||
} else if (expression instanceof Variable) {
|
} else if (isVar(expression)) {
|
||||||
FragmentVariable fragmentVariable = new FragmentVariable((Variable) expression, false);
|
FragmentVariable fragmentVariable = new FragmentVariable((Variable) expression, false);
|
||||||
fragmentVariables.add(fragmentVariable);
|
fragmentVariables.add(fragmentVariable);
|
||||||
return fragmentVariable;
|
return fragmentVariable;
|
||||||
@ -367,10 +386,11 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
|
|||||||
fr.setPos(new Vector(0, 0));
|
fr.setPos(new Vector(0, 0));
|
||||||
Box b = fr.doLayout();
|
Box b = fr.doLayout();
|
||||||
|
|
||||||
|
if (fr.traverse(new FindLUTVisitor()).containsLUT())
|
||||||
|
pos += SIZE * 2;
|
||||||
|
|
||||||
fr.addToCircuit(new Vector(0, pos), circuit);
|
fr.addToCircuit(new Vector(0, pos), circuit);
|
||||||
pos += b.getHeight() + SIZE * 2;
|
pos += b.getHeight() + SIZE * 2;
|
||||||
if (useLUT)
|
|
||||||
pos += SIZE * 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -682,4 +702,20 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
|
|||||||
mai = modelAnalyserInfo;
|
mai = modelAnalyserInfo;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class FindLUTVisitor implements FragmentVisitor {
|
||||||
|
private boolean hasLUT = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Fragment fr) {
|
||||||
|
if (fr instanceof FragmentVisualElement) {
|
||||||
|
if (((FragmentVisualElement) fr).getVisualElement().equalsDescription(LookUpTable.DESCRIPTION))
|
||||||
|
hasLUT = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsLUT() {
|
||||||
|
return hasLUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,4 +48,12 @@ public interface Fragment {
|
|||||||
*/
|
*/
|
||||||
List<Vector> getOutputs();
|
List<Vector> getOutputs();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits all fragments
|
||||||
|
*
|
||||||
|
* @param v the visitor
|
||||||
|
* @param <V> the type of the visitor
|
||||||
|
* @return the visitor
|
||||||
|
*/
|
||||||
|
<V extends FragmentVisitor> V traverse(V v);
|
||||||
}
|
}
|
||||||
|
@ -237,4 +237,13 @@ public class FragmentExpression implements Fragment {
|
|||||||
fragment.setPos(new Vector(xPos - SIZE, height));
|
fragment.setPos(new Vector(xPos - SIZE, height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <V extends FragmentVisitor> V traverse(V v) {
|
||||||
|
v.visit(this);
|
||||||
|
for (FragmentHolder f : fragments)
|
||||||
|
f.fragment.traverse(v);
|
||||||
|
merger.traverse(v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,4 +69,11 @@ public class FragmentSameInValue implements Fragment {
|
|||||||
public List<Vector> getOutputs() {
|
public List<Vector> getOutputs() {
|
||||||
return Vector.add(fragment.getOutputs(), pos);
|
return Vector.add(fragment.getOutputs(), pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <V extends FragmentVisitor> V traverse(V v) {
|
||||||
|
v.visit(this);
|
||||||
|
fragment.traverse(v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,4 +79,10 @@ public class FragmentVariable implements Fragment {
|
|||||||
public Variable getVariable() {
|
public Variable getVariable() {
|
||||||
return variable;
|
return variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <V extends FragmentVisitor> V traverse(V v) {
|
||||||
|
v.visit(this);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 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.builder.circuit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visitor used to visit all fragments
|
||||||
|
*/
|
||||||
|
public interface FragmentVisitor {
|
||||||
|
/**
|
||||||
|
* Is called with all the fragments
|
||||||
|
*
|
||||||
|
* @param fr the fragment to visit
|
||||||
|
*/
|
||||||
|
void visit(Fragment fr);
|
||||||
|
}
|
@ -141,4 +141,10 @@ public class FragmentVisualElement implements Fragment {
|
|||||||
public void setVisualElement(VisualElement visualElement) {
|
public void setVisualElement(VisualElement visualElement) {
|
||||||
this.visualElement = visualElement;
|
this.visualElement = visualElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <V extends FragmentVisitor> V traverse(V v) {
|
||||||
|
v.visit(this);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import static de.neemann.digital.analyse.expression.Operation.and;
|
|||||||
import static de.neemann.digital.analyse.expression.Operation.or;
|
import static de.neemann.digital.analyse.expression.Operation.or;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class CircuitBuilderTest extends TestCase {
|
public class CircuitBuilderTest extends TestCase {
|
||||||
|
|
||||||
@ -87,29 +88,36 @@ public class CircuitBuilderTest extends TestCase {
|
|||||||
public void testBuilderSequentialLUT() throws Exception {
|
public void testBuilderSequentialLUT() throws Exception {
|
||||||
Variable y0 = new Variable("Y_0");
|
Variable y0 = new Variable("Y_0");
|
||||||
Variable y1 = new Variable("Y_1");
|
Variable y1 = new Variable("Y_1");
|
||||||
|
Variable y2 = new Variable("Y_2");
|
||||||
|
|
||||||
// counter
|
// counter
|
||||||
Expression y0s = not(y0);
|
Expression y0s = not(y0);
|
||||||
Expression y1s = or(and(not(y0), y1), and(y0, not(y1)));
|
Expression y1s = or(and(not(y0), y1), and(y0, not(y1)));
|
||||||
|
Expression y2s = or(and(y0, y1, not(y2)), and(not(y0), y2), and(not(y1), y2));
|
||||||
|
|
||||||
ElementLibrary library = new ElementLibrary();
|
ElementLibrary library = new ElementLibrary();
|
||||||
Circuit circuit = new CircuitBuilder(new ShapeFactory(library))
|
Circuit circuit = new CircuitBuilder(new ShapeFactory(library))
|
||||||
.setUseLUTs(true)
|
.setUseLUTs(true)
|
||||||
.addSequential("Y_0", y0s)
|
.addSequential("Y_0", y0s)
|
||||||
.addSequential("Y_1", y1s)
|
.addSequential("Y_1", y1s)
|
||||||
|
.addSequential("Y_2", y2s)
|
||||||
.createCircuit();
|
.createCircuit();
|
||||||
|
|
||||||
final ArrayList<VisualElement> el = circuit.getElements();
|
final ArrayList<VisualElement> el = circuit.getElements();
|
||||||
assertEquals(13, el.size());
|
assertEquals(19, el.size());
|
||||||
assertEquals(1, el.stream().filter(visualElement -> visualElement.equalsDescription(LookUpTable.DESCRIPTION)).count());
|
assertEquals(1, el.stream().filter(visualElement -> visualElement.equalsDescription(LookUpTable.DESCRIPTION)).count());
|
||||||
|
|
||||||
ModelCreator m = new ModelCreator(circuit, library);
|
ModelCreator m = new ModelCreator(circuit, library);
|
||||||
TestExecuter te = new TestExecuter(m.createModel(false)).setUp(m);
|
TestExecuter te = new TestExecuter(m.createModel(false)).setUp(m);
|
||||||
te.check(0, 0);
|
te.check(0, 0, 0);
|
||||||
te.checkC(1, 0);
|
te.checkC(1, 0, 0);
|
||||||
te.checkC(0, 1);
|
te.checkC(0, 1, 0);
|
||||||
te.checkC(1, 1);
|
te.checkC(1, 1, 0);
|
||||||
te.checkC(0, 0);
|
te.checkC(0, 0, 1);
|
||||||
|
te.checkC(1, 0, 1);
|
||||||
|
te.checkC(0, 1, 1);
|
||||||
|
te.checkC(1, 1, 1);
|
||||||
|
te.checkC(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBuilderSequentialJK_JequalsK() throws Exception {
|
public void testBuilderSequentialJK_JequalsK() throws Exception {
|
||||||
@ -224,4 +232,63 @@ public class CircuitBuilderTest extends TestCase {
|
|||||||
assertEquals(4, e.getElementAttributes().getBits());
|
assertEquals(4, e.getElementAttributes().getBits());
|
||||||
assertEquals(pins, e.getElementAttributes().get(Keys.PINNUMBER));
|
assertEquals(pins, e.getElementAttributes().get(Keys.PINNUMBER));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testIsXor() {
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 0, 0, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 0, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 0, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 0, 1, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 0, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 0, 1}));
|
||||||
|
assertTrue(CircuitBuilder.isXor(new long[]{0, 1, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{1, 0, 0, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{1, 0, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{1, 0, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{1, 0, 1, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{1, 1, 0, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{1, 1, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{1, 1, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{1, 1, 1, 1}));
|
||||||
|
|
||||||
|
assertTrue(CircuitBuilder.isXor(new long[]{0, 1, 1, 0, 1, 0, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{1, 1, 1, 0, 1, 0, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 0, 1, 0, 1, 0, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 0, 0, 1, 0, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 1, 1, 0, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 0, 0, 0, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 0, 1, 1, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 0, 1, 0, 1, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXor(new long[]{0, 1, 1, 0, 1, 0, 0, 0}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsXNor() {
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{0, 0, 0, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{0, 0, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{0, 0, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{0, 0, 1, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{0, 1, 0, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{0, 1, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{0, 1, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{0, 1, 1, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 0}));
|
||||||
|
assertTrue(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 1, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 1, 0, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 1, 0, 1}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 1, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 1, 1, 1}));
|
||||||
|
|
||||||
|
assertTrue(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1, 0, 1, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{0, 0, 0, 1, 0, 1, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 1, 0, 1, 0, 1, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 1, 1, 0, 1, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 0, 0, 1, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1, 1, 1, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1, 0, 0, 1, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1, 0, 1, 0, 0}));
|
||||||
|
assertFalse(CircuitBuilder.isXNor(new long[]{1, 0, 0, 1, 0, 1, 1, 1}));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user