mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-16 16:34:47 -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 {
|
||||
|
||||
private Expression expression;
|
||||
private boolean protect = false;
|
||||
|
||||
/**
|
||||
* Creates a not expression.
|
||||
@ -22,7 +23,7 @@ public final class Not implements Expression {
|
||||
if (a == Constant.ZERO)
|
||||
return Constant.ONE;
|
||||
|
||||
if (a instanceof Not) {
|
||||
if (a instanceof Not && !((Not) a).protect) {
|
||||
return ((Not) a).expression;
|
||||
} else
|
||||
return new Not(a);
|
||||
@ -32,12 +33,22 @@ public final class Not implements Expression {
|
||||
* Creates a new instance.
|
||||
* In most cases it's better to use {@link Not#not(Expression)}.
|
||||
*
|
||||
* @param expression
|
||||
* @param expression the expression to invert
|
||||
*/
|
||||
public Not(Expression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protects this not against simplification
|
||||
*
|
||||
* @return this for call chaning
|
||||
*/
|
||||
public Not protect() {
|
||||
protect = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean calculate(Context context) throws ExpressionException {
|
||||
return !expression.calculate(context);
|
||||
|
@ -26,7 +26,7 @@ public abstract class Operation implements Expression {
|
||||
* @return the created expression
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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) {
|
||||
@ -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<>();
|
||||
for (Expression e : exp)
|
||||
if (e != null)
|
||||
merge(e);
|
||||
if (merge)
|
||||
merge(e);
|
||||
else
|
||||
expr.add(e);
|
||||
}
|
||||
|
||||
private void merge(Expression e) {
|
||||
@ -143,8 +166,8 @@ public abstract class Operation implements Expression {
|
||||
*/
|
||||
public static final class And extends Operation {
|
||||
|
||||
private And(Iterable<Expression> exp) {
|
||||
super(exp);
|
||||
private And(Iterable<Expression> exp, boolean merge) {
|
||||
super(exp, merge);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -163,8 +186,8 @@ public abstract class Operation implements Expression {
|
||||
*/
|
||||
public static final class Or extends Operation {
|
||||
|
||||
private Or(Iterable<Expression> exp) {
|
||||
super(exp);
|
||||
private Or(Iterable<Expression> exp, boolean merge) {
|
||||
super(exp, merge);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,6 +25,19 @@ public interface ExpressionModifier {
|
||||
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.
|
||||
* Don't recurse! Recursion is done by calling {@link Expression#modify(ExpressionModifier)}
|
||||
|
@ -16,12 +16,12 @@ public class NAnd implements ExpressionModifier {
|
||||
@Override
|
||||
public Expression modify(Expression expression) {
|
||||
if (expression instanceof Operation.And) {
|
||||
return new Not(not(expression));
|
||||
return not(new Not(expression).protect());
|
||||
} else if (expression instanceof Operation.Or) {
|
||||
ArrayList<Expression> exp = new ArrayList<>();
|
||||
for (Expression e : ((Operation.Or) expression).getExpressions())
|
||||
exp.add(not(e));
|
||||
return not(Operation.and(exp));
|
||||
return new Not(Operation.and(exp)).protect();
|
||||
} else
|
||||
return expression;
|
||||
}
|
||||
|
@ -16,13 +16,13 @@ public class NOr implements ExpressionModifier {
|
||||
@Override
|
||||
public Expression modify(Expression expression) {
|
||||
if (expression instanceof Operation.Or) {
|
||||
return new Not(not(expression));
|
||||
return not(new Not(expression).protect());
|
||||
} else
|
||||
if (expression instanceof Operation.And) {
|
||||
ArrayList<Expression> exp = new ArrayList<>();
|
||||
for (Expression e : ((Operation.And) expression).getExpressions())
|
||||
exp.add(not(e));
|
||||
return not(Operation.or(exp));
|
||||
return new Not(Operation.or(exp)).protect();
|
||||
} else
|
||||
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.NAnd;
|
||||
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.BuilderException;
|
||||
import de.neemann.digital.draw.elements.Circuit;
|
||||
@ -128,19 +129,42 @@ public class TableFrame extends JFrame {
|
||||
createCircuit(ExpressionModifier.IDENTITY);
|
||||
}
|
||||
}.setToolTip(Lang.get("menu_table_create_tt")).createJMenuItem());
|
||||
|
||||
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")) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
createCircuit(new NAnd());
|
||||
}
|
||||
}.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")) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
createCircuit(new NOr());
|
||||
}
|
||||
}.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);
|
||||
|
||||
@ -155,7 +179,7 @@ public class TableFrame extends JFrame {
|
||||
setLocationRelativeTo(parent);
|
||||
}
|
||||
|
||||
private void createCircuit(ExpressionModifier modifier) {
|
||||
private void createCircuit(ExpressionModifier... modifier) {
|
||||
try {
|
||||
Builder builder = new Builder(shapeFactory);
|
||||
HashSet<String> contained = new HashSet<>();
|
||||
|
Loading…
x
Reference in New Issue
Block a user