mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-17 08:55:05 -04:00
added possibility to create circuits with gates with only two inputs
This commit is contained in:
parent
82a7d20143
commit
4e4ec3e70e
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,7 @@ import de.neemann.digital.analyse.expression.modify.ExpressionModifier;
|
|||||||
public final class Not implements Expression {
|
public final class Not implements Expression {
|
||||||
|
|
||||||
private Expression expression;
|
private Expression expression;
|
||||||
|
private boolean protect = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a not expression.
|
* Creates a not expression.
|
||||||
@ -22,7 +23,7 @@ public final class Not implements Expression {
|
|||||||
if (a == Constant.ZERO)
|
if (a == Constant.ZERO)
|
||||||
return Constant.ONE;
|
return Constant.ONE;
|
||||||
|
|
||||||
if (a instanceof Not) {
|
if (a instanceof Not && !((Not) a).protect) {
|
||||||
return ((Not) a).expression;
|
return ((Not) a).expression;
|
||||||
} else
|
} else
|
||||||
return new Not(a);
|
return new Not(a);
|
||||||
@ -32,12 +33,22 @@ public final class Not implements Expression {
|
|||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
* In most cases it's better to use {@link Not#not(Expression)}.
|
* In most cases it's better to use {@link Not#not(Expression)}.
|
||||||
*
|
*
|
||||||
* @param expression
|
* @param expression the expression to invert
|
||||||
*/
|
*/
|
||||||
public Not(Expression expression) {
|
public Not(Expression expression) {
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protects this not against simplification
|
||||||
|
*
|
||||||
|
* @return this for call chaning
|
||||||
|
*/
|
||||||
|
public Not protect() {
|
||||||
|
protect = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean calculate(Context context) throws ExpressionException {
|
public boolean calculate(Context context) throws ExpressionException {
|
||||||
return !expression.calculate(context);
|
return !expression.calculate(context);
|
||||||
|
@ -26,7 +26,7 @@ public abstract class Operation implements Expression {
|
|||||||
* @return the created expression
|
* @return the created expression
|
||||||
*/
|
*/
|
||||||
public static Expression or(Iterable<Expression> exp) {
|
public static Expression or(Iterable<Expression> exp) {
|
||||||
return simplify(new Or(exp));
|
return simplify(new Or(exp, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,7 +36,17 @@ public abstract class Operation implements Expression {
|
|||||||
* @return the created expression
|
* @return the created expression
|
||||||
*/
|
*/
|
||||||
public static Expression or(Expression... exp) {
|
public static Expression or(Expression... exp) {
|
||||||
return simplify(new Or(Arrays.asList(exp)));
|
return simplify(new Or(Arrays.asList(exp), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new OR expression
|
||||||
|
*
|
||||||
|
* @param exp the expressions to OR
|
||||||
|
* @return the created expression
|
||||||
|
*/
|
||||||
|
public static Expression orNoMerge(Expression... exp) {
|
||||||
|
return simplify(new Or(Arrays.asList(exp), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,7 +56,7 @@ public abstract class Operation implements Expression {
|
|||||||
* @return the created expression
|
* @return the created expression
|
||||||
*/
|
*/
|
||||||
public static Expression and(Iterable<Expression> exp) {
|
public static Expression and(Iterable<Expression> exp) {
|
||||||
return simplify(new And(exp));
|
return simplify(new And(exp, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +66,17 @@ public abstract class Operation implements Expression {
|
|||||||
* @return the created expression
|
* @return the created expression
|
||||||
*/
|
*/
|
||||||
public static Expression and(Expression... exp) {
|
public static Expression and(Expression... exp) {
|
||||||
return simplify(new And(Arrays.asList(exp)));
|
return simplify(new And(Arrays.asList(exp), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new AND expression
|
||||||
|
*
|
||||||
|
* @param exp the expressions to AND
|
||||||
|
* @return the created expression
|
||||||
|
*/
|
||||||
|
public static Expression andNoMerge(Expression... exp) {
|
||||||
|
return simplify(new And(Arrays.asList(exp), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Expression simplify(Operation operation) {
|
private static Expression simplify(Operation operation) {
|
||||||
@ -72,11 +92,14 @@ public abstract class Operation implements Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Operation(Iterable<Expression> exp) {
|
private Operation(Iterable<Expression> exp, boolean merge) {
|
||||||
expr = new ArrayList<>();
|
expr = new ArrayList<>();
|
||||||
for (Expression e : exp)
|
for (Expression e : exp)
|
||||||
if (e != null)
|
if (e != null)
|
||||||
merge(e);
|
if (merge)
|
||||||
|
merge(e);
|
||||||
|
else
|
||||||
|
expr.add(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void merge(Expression e) {
|
private void merge(Expression e) {
|
||||||
@ -143,8 +166,8 @@ public abstract class Operation implements Expression {
|
|||||||
*/
|
*/
|
||||||
public static final class And extends Operation {
|
public static final class And extends Operation {
|
||||||
|
|
||||||
private And(Iterable<Expression> exp) {
|
private And(Iterable<Expression> exp, boolean merge) {
|
||||||
super(exp);
|
super(exp, merge);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -163,8 +186,8 @@ public abstract class Operation implements Expression {
|
|||||||
*/
|
*/
|
||||||
public static final class Or extends Operation {
|
public static final class Or extends Operation {
|
||||||
|
|
||||||
private Or(Iterable<Expression> exp) {
|
private Or(Iterable<Expression> exp, boolean merge) {
|
||||||
super(exp);
|
super(exp, merge);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,6 +25,19 @@ public interface ExpressionModifier {
|
|||||||
return modifier.modify(expression);
|
return modifier.modify(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies the given expression with the given modifiers
|
||||||
|
*
|
||||||
|
* @param expression the expression to modify
|
||||||
|
* @param modifiers the modifiers to use
|
||||||
|
* @return the modified expression
|
||||||
|
*/
|
||||||
|
static Expression modifyExpression(Expression expression, ExpressionModifier... modifiers) {
|
||||||
|
for (ExpressionModifier m : modifiers)
|
||||||
|
expression = modifyExpression(expression, m);
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modifies an expression.
|
* Modifies an expression.
|
||||||
* Don't recurse! Recursion is done by calling {@link Expression#modify(ExpressionModifier)}
|
* Don't recurse! Recursion is done by calling {@link Expression#modify(ExpressionModifier)}
|
||||||
|
@ -16,12 +16,12 @@ public class NAnd implements ExpressionModifier {
|
|||||||
@Override
|
@Override
|
||||||
public Expression modify(Expression expression) {
|
public Expression modify(Expression expression) {
|
||||||
if (expression instanceof Operation.And) {
|
if (expression instanceof Operation.And) {
|
||||||
return new Not(not(expression));
|
return not(new Not(expression).protect());
|
||||||
} else if (expression instanceof Operation.Or) {
|
} else if (expression instanceof Operation.Or) {
|
||||||
ArrayList<Expression> exp = new ArrayList<>();
|
ArrayList<Expression> exp = new ArrayList<>();
|
||||||
for (Expression e : ((Operation.Or) expression).getExpressions())
|
for (Expression e : ((Operation.Or) expression).getExpressions())
|
||||||
exp.add(not(e));
|
exp.add(not(e));
|
||||||
return not(Operation.and(exp));
|
return new Not(Operation.and(exp)).protect();
|
||||||
} else
|
} else
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,13 @@ public class NOr implements ExpressionModifier {
|
|||||||
@Override
|
@Override
|
||||||
public Expression modify(Expression expression) {
|
public Expression modify(Expression expression) {
|
||||||
if (expression instanceof Operation.Or) {
|
if (expression instanceof Operation.Or) {
|
||||||
return new Not(not(expression));
|
return not(new Not(expression).protect());
|
||||||
} else
|
} else
|
||||||
if (expression instanceof Operation.And) {
|
if (expression instanceof Operation.And) {
|
||||||
ArrayList<Expression> exp = new ArrayList<>();
|
ArrayList<Expression> exp = new ArrayList<>();
|
||||||
for (Expression e : ((Operation.And) expression).getExpressions())
|
for (Expression e : ((Operation.And) expression).getExpressions())
|
||||||
exp.add(not(e));
|
exp.add(not(e));
|
||||||
return not(Operation.or(exp));
|
return new Not(Operation.or(exp)).protect();
|
||||||
} else
|
} else
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
package de.neemann.digital.analyse.expression.modify;
|
||||||
|
|
||||||
|
import de.neemann.digital.analyse.expression.Expression;
|
||||||
|
import de.neemann.digital.analyse.expression.Operation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static de.neemann.digital.analyse.expression.Operation.andNoMerge;
|
||||||
|
import static de.neemann.digital.analyse.expression.Operation.orNoMerge;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hneemann
|
||||||
|
*/
|
||||||
|
public class TwoInputs implements ExpressionModifier {
|
||||||
|
@Override
|
||||||
|
public Expression modify(Expression expression) {
|
||||||
|
if (expression instanceof Operation) {
|
||||||
|
Operation op = (Operation) expression;
|
||||||
|
if (op.getExpressions().size() > 2) {
|
||||||
|
if (expression instanceof Operation.And)
|
||||||
|
return new Twoer(op.getExpressions(), (a, b) -> andNoMerge(a, b)).generate();
|
||||||
|
else if (expression instanceof Operation.Or)
|
||||||
|
return new Twoer(op.getExpressions(), (a, b) -> orNoMerge(a, b)).generate();
|
||||||
|
else
|
||||||
|
throw new RuntimeException("operation not supported: " + expression.getClass().getSimpleName());
|
||||||
|
} else
|
||||||
|
return expression;
|
||||||
|
} else
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface OpGen {
|
||||||
|
Expression op(Expression a, Expression b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class Twoer {
|
||||||
|
private final ArrayList<Expression> expressions;
|
||||||
|
private final OpGen opGen;
|
||||||
|
|
||||||
|
Twoer(ArrayList<Expression> expressions, OpGen opGen) {
|
||||||
|
this.expressions = expressions;
|
||||||
|
this.opGen = opGen;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression generate() {
|
||||||
|
return gen(0, expressions.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Expression gen(int a, int b) {
|
||||||
|
if (a == b)
|
||||||
|
return expressions.get(a);
|
||||||
|
else if (a == b - 1)
|
||||||
|
return opGen.op(expressions.get(a), expressions.get(b));
|
||||||
|
else {
|
||||||
|
int i = (a + b) / 2;
|
||||||
|
return opGen.op(gen(a, i), gen(i + 1, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,7 @@ import de.neemann.digital.analyse.expression.format.FormatterException;
|
|||||||
import de.neemann.digital.analyse.expression.modify.ExpressionModifier;
|
import de.neemann.digital.analyse.expression.modify.ExpressionModifier;
|
||||||
import de.neemann.digital.analyse.expression.modify.NAnd;
|
import de.neemann.digital.analyse.expression.modify.NAnd;
|
||||||
import de.neemann.digital.analyse.expression.modify.NOr;
|
import de.neemann.digital.analyse.expression.modify.NOr;
|
||||||
|
import de.neemann.digital.analyse.expression.modify.TwoInputs;
|
||||||
import de.neemann.digital.draw.builder.Builder;
|
import de.neemann.digital.draw.builder.Builder;
|
||||||
import de.neemann.digital.draw.builder.BuilderException;
|
import de.neemann.digital.draw.builder.BuilderException;
|
||||||
import de.neemann.digital.draw.elements.Circuit;
|
import de.neemann.digital.draw.elements.Circuit;
|
||||||
@ -128,19 +129,42 @@ public class TableFrame extends JFrame {
|
|||||||
createCircuit(ExpressionModifier.IDENTITY);
|
createCircuit(ExpressionModifier.IDENTITY);
|
||||||
}
|
}
|
||||||
}.setToolTip(Lang.get("menu_table_create_tt")).createJMenuItem());
|
}.setToolTip(Lang.get("menu_table_create_tt")).createJMenuItem());
|
||||||
|
|
||||||
if (Main.enableExperimental()) {
|
if (Main.enableExperimental()) {
|
||||||
|
createMenu.add(new ToolTipAction(Lang.get("menu_table_createTwo")) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
createCircuit(new TwoInputs());
|
||||||
|
}
|
||||||
|
}.setToolTip(Lang.get("menu_table_createTwo_tt")).createJMenuItem());
|
||||||
|
|
||||||
createMenu.add(new ToolTipAction(Lang.get("menu_table_createNAnd")) {
|
createMenu.add(new ToolTipAction(Lang.get("menu_table_createNAnd")) {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
createCircuit(new NAnd());
|
createCircuit(new NAnd());
|
||||||
}
|
}
|
||||||
}.setToolTip(Lang.get("menu_table_createNAnd_tt")).createJMenuItem());
|
}.setToolTip(Lang.get("menu_table_createNAnd_tt")).createJMenuItem());
|
||||||
|
|
||||||
|
createMenu.add(new ToolTipAction(Lang.get("menu_table_createNAndTwo")) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
createCircuit(new TwoInputs(), new NAnd());
|
||||||
|
}
|
||||||
|
}.setToolTip(Lang.get("menu_table_createNAndTwo_tt")).createJMenuItem());
|
||||||
|
|
||||||
createMenu.add(new ToolTipAction(Lang.get("menu_table_createNOr")) {
|
createMenu.add(new ToolTipAction(Lang.get("menu_table_createNOr")) {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
createCircuit(new NOr());
|
createCircuit(new NOr());
|
||||||
}
|
}
|
||||||
}.setToolTip(Lang.get("menu_table_createNOr_tt")).createJMenuItem());
|
}.setToolTip(Lang.get("menu_table_createNOr_tt")).createJMenuItem());
|
||||||
|
|
||||||
|
createMenu.add(new ToolTipAction(Lang.get("menu_table_createNOrTwo")) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
createCircuit(new TwoInputs(), new NOr());
|
||||||
|
}
|
||||||
|
}.setToolTip(Lang.get("menu_table_createNOrTwo_tt")).createJMenuItem());
|
||||||
}
|
}
|
||||||
bar.add(createMenu);
|
bar.add(createMenu);
|
||||||
|
|
||||||
@ -155,7 +179,7 @@ public class TableFrame extends JFrame {
|
|||||||
setLocationRelativeTo(parent);
|
setLocationRelativeTo(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createCircuit(ExpressionModifier modifier) {
|
private void createCircuit(ExpressionModifier... modifier) {
|
||||||
try {
|
try {
|
||||||
Builder builder = new Builder(shapeFactory);
|
Builder builder = new Builder(shapeFactory);
|
||||||
HashSet<String> contained = new HashSet<>();
|
HashSet<String> contained = new HashSet<>();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user