+++ /dev/null
-package era.mi.logic;\r
-\r
-import java.util.Arrays;\r
-\r
-/**\r
- * stdlogic according to IEEE 1164\r
- */\r
-public enum Bit\r
-{\r
- U, X, ZERO, ONE, Z;\r
-\r
- public static Bit and(Bit a, Bit b)\r
- {\r
- return a.and(b);\r
- }\r
-\r
- public Bit and(Bit other)\r
- {\r
- return fromTable(AND_TABLE, this, other);\r
- }\r
-\r
- public static Bit or(Bit a, Bit b)\r
- {\r
- return a.or(b);\r
- }\r
-\r
- public Bit or(Bit other)\r
- {\r
- return fromTable(OR_TABLE, this, other);\r
- }\r
-\r
- public static Bit xor(Bit a, Bit b)\r
- {\r
- return a.xor(b);\r
- }\r
-\r
- public Bit xor(Bit other)\r
- {\r
- return fromTable(XOR_TABLE, this, other);\r
- }\r
-\r
- public Bit not()\r
- {\r
- switch (this)\r
- {\r
- case U:\r
- return U;\r
- case ONE:\r
- return ZERO;\r
- case ZERO:\r
- return ONE;\r
- default:\r
- return X;\r
- }\r
- }\r
-\r
- public Bit[] makeArray(int length)\r
- {\r
- Bit[] bits = new Bit[length];\r
- Arrays.fill(bits, this);\r
- return bits;\r
- }\r
-\r
- public Bit combineWith(Bit other)\r
- {\r
- return fromTable(JOIN_TABLE, this, other);\r
- }\r
-\r
- public static Bit combine(Bit a, Bit b)\r
- {\r
- return a.combineWith(b);\r
- }\r
-\r
- private static Bit fromTable(Bit[][] table, Bit a, Bit b)\r
- {\r
- return table[a.ordinal()][b.ordinal()];\r
- }\r
-\r
- // @formatter:off\r
- private static Bit[][] JOIN_TABLE = \r
- { { U, U, U, U, U }, \r
- { U, X, X, X, X }, \r
- { U, X, ZERO, X, ZERO },\r
- { U, X, X, ONE, ONE }, \r
- { U, X, ZERO, ONE, Z } };\r
-\r
- private static Bit[][] AND_TABLE = \r
- { { U, U, ZERO, U, U }, \r
- { U, X, ZERO, X, X },\r
- { ZERO, ZERO, ZERO, ZERO, ZERO }, \r
- { U, X, ZERO, ONE, X }, \r
- { U, X, ZERO, X, X } };\r
-\r
- private static Bit[][] OR_TABLE =\r
- { { U, U, U, ONE, U }, \r
- { U, X, X, ONE, X }, \r
- { U, X, ZERO, ONE, X }, \r
- { ONE, ONE, ONE, ONE, ONE }, \r
- { U, X, X, ONE, X } };\r
- \r
- private static Bit[][] XOR_TABLE =\r
- { { U, U, U, U, U }, \r
- { U, X, X, X, X }, \r
- { U, X, ZERO, ONE, X }, \r
- { U, X, ONE, ZERO, X }, \r
- { U, X, X, X, X } }; \r
- // @formatter:on\r
-}
\ No newline at end of file
\r
import java.util.Arrays;\r
\r
+import era.mi.logic.types.Bit;\r
+\r
public final class Util\r
{\r
\r
\r
public static Bit[] and(Bit[] a, Bit[] b)\r
{\r
- return binBitOp(a, b, (bA, bB) -> Bit.and(bA, bB));\r
+ return binBitOp(a, b, Bit::and);\r
}\r
\r
public static Bit[] or(Bit[] a, Bit[] b)\r
{\r
- return binBitOp(a, b, (bA, bB) -> Bit.or(bA, bB));\r
+ return binBitOp(a, b, Bit::or);\r
}\r
\r
public static Bit[] xor(Bit[] a, Bit[] b)\r
{\r
- return binBitOp(a, b, (bA, bB) -> Bit.xor(bA, bB));\r
+ return binBitOp(a, b, Bit::xor);\r
}\r
\r
private static Bit[] binBitOp(Bit[] a, Bit[] b, BitOp op)\r
throw new IllegalArgumentException("Bit Arrays were not of equal length.");\r
for (int i = 0; i < addition.length; i++)\r
{\r
- dest[i] = dest[i].combineWith(addition[i]);\r
+ dest[i] = dest[i].join(addition[i]);\r
}\r
return dest;\r
}\r
package era.mi.logic.components;\r
\r
-import era.mi.logic.Bit;\r
import era.mi.logic.Simulation;\r
+import era.mi.logic.types.Bit;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.WireObserver;\r
\r
import java.util.Arrays;\r
import java.util.List;\r
\r
-import era.mi.logic.Bit;\r
+import era.mi.logic.types.Bit;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public class BitDisplay extends BasicComponent\r
\r
import java.util.List;\r
\r
-import era.mi.logic.Bit;\r
import era.mi.logic.Simulation;\r
import era.mi.logic.timeline.TimelineEvent;\r
import era.mi.logic.timeline.TimelineEventHandler;\r
+import era.mi.logic.types.Bit;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
import java.util.List;
-import era.mi.logic.Bit;
import era.mi.logic.Simulation;
+import era.mi.logic.types.Bit;
import era.mi.logic.wires.Wire;
import era.mi.logic.wires.Wire.WireEnd;
import era.mi.logic.wires.WireObserver;
\r
import java.util.List;\r
\r
-import era.mi.logic.Bit;\r
+import era.mi.logic.types.Bit;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
/**\r
\r
import java.util.List;\r
\r
-import era.mi.logic.Bit;\r
+import era.mi.logic.types.Bit;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.Wire.WireEnd;\r
import era.mi.logic.wires.WireObserver;\r
package era.mi.logic.components;\r
\r
-import era.mi.logic.Bit;\r
+import era.mi.logic.types.Bit;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.Wire.WireEnd;\r
import era.mi.logic.wires.WireObserver;\r
\r
import java.util.List;\r
\r
-import era.mi.logic.Bit;\r
+import era.mi.logic.types.Bit;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public class TriStateBuffer extends BasicComponent\r
\r
import java.util.List;\r
\r
-import era.mi.logic.Bit;\r
import era.mi.logic.components.BasicComponent;\r
+import era.mi.logic.types.Bit;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public abstract class MultiInputGate extends BasicComponent\r
package era.mi.logic.tests;\r
\r
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;\r
-import static org.junit.jupiter.api.Assertions.assertEquals;\r
-import static org.junit.jupiter.api.Assertions.assertTrue;\r
-import static org.junit.jupiter.api.Assertions.fail;\r
+import static org.junit.jupiter.api.Assertions.*;\r
\r
import java.util.Arrays;\r
import java.util.function.LongConsumer;\r
\r
import org.junit.jupiter.api.Test;\r
\r
-import era.mi.logic.Bit;\r
import era.mi.logic.Simulation;\r
import era.mi.logic.components.Connector;\r
import era.mi.logic.components.Demux;\r
import era.mi.logic.components.gates.NotGate;\r
import era.mi.logic.components.gates.OrGate;\r
import era.mi.logic.components.gates.XorGate;\r
+import era.mi.logic.types.Bit;\r
import era.mi.logic.wires.Wire;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
import java.util.Arrays;\r
import java.util.function.LongConsumer;\r
\r
-import era.mi.logic.Bit;\r
import era.mi.logic.Simulation;\r
import era.mi.logic.components.BitDisplay;\r
+import era.mi.logic.types.Bit;\r
import era.mi.logic.wires.Wire.WireEnd;\r
\r
public final class TestBitDisplay extends BitDisplay\r
--- /dev/null
+package era.mi.logic.types;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * stdlogic according to IEEE 1164
+ */
+public enum Bit implements StrictLogicType<Bit>
+{
+ U("U"), X("X"), ZERO("0"), ONE("1"), Z("Z");
+
+ private final String symbol;
+
+ private Bit(String symbol)
+ {
+ this.symbol = symbol;
+ }
+
+ @Override
+ public Bit and(Bit other)
+ {
+ return fromTable(AND_TABLE, this, other);
+ }
+
+ @Override
+ public Bit or(Bit other)
+ {
+ return fromTable(OR_TABLE, this, other);
+ }
+
+ @Override
+ public Bit xor(Bit other)
+ {
+ return fromTable(XOR_TABLE, this, other);
+ }
+
+ @Override
+ public Bit not()
+ {
+ switch (this)
+ {
+ case U:
+ return U;
+ case ONE:
+ return ZERO;
+ case ZERO:
+ return ONE;
+ default:
+ return X;
+ }
+ }
+
+ public Bit[] makeArray(int length)
+ {
+ Bit[] bits = new Bit[length];
+ Arrays.fill(bits, this);
+ return bits;
+ }
+
+ public BitVector toVector(int length)
+ {
+ return BitVector.of(this, length);
+ }
+
+ @Override
+ public Bit join(Bit other)
+ {
+ return fromTable(JOIN_TABLE, this, other);
+ }
+
+ @Override
+ public String toString()
+ {
+ return getSymbol();
+ }
+
+ public String getSymbol()
+ {
+ return symbol;
+ }
+
+ public static Bit parse(String s)
+ {
+ Bit bit = SYMBOL_MAP.get(s);
+ Objects.requireNonNull(bit, "No Bit found for symbol " + s);
+ return bit;
+ }
+
+ public static Bit parse(String s, int symbolPosition)
+ {
+ return parse(s.substring(symbolPosition, symbolPosition + 1));
+ }
+
+ private static Bit fromTable(Bit[][] table, Bit a, Bit b)
+ {
+ return table[a.ordinal()][b.ordinal()];
+ }
+
+ static final Map<String, Bit> SYMBOL_MAP = Map.of(U.symbol, U, X.symbol, X, ZERO.symbol, ZERO, ONE.symbol, ONE, Z.symbol, Z);
+
+ // @formatter:off
+ private static final Bit[][] JOIN_TABLE =
+ { { U, U, U, U, U },
+ { U, X, X, X, X },
+ { U, X, ZERO, X, ZERO },
+ { U, X, X, ONE, ONE },
+ { U, X, ZERO, ONE, Z } };
+
+ private static final Bit[][] AND_TABLE =
+ { { U, U, ZERO, U, U },
+ { U, X, ZERO, X, X },
+ { ZERO, ZERO, ZERO, ZERO, ZERO },
+ { U, X, ZERO, ONE, X },
+ { U, X, ZERO, X, X } };
+
+ private static final Bit[][] OR_TABLE =
+ { { U, U, U, ONE, U },
+ { U, X, X, ONE, X },
+ { U, X, ZERO, ONE, X },
+ { ONE, ONE, ONE, ONE, ONE },
+ { U, X, X, ONE, X } };
+
+ private static final Bit[][] XOR_TABLE =
+ { { U, U, U, U, U },
+ { U, X, X, X, X },
+ { U, X, ZERO, ONE, X },
+ { U, X, ONE, ZERO, X },
+ { U, X, X, X, X } };
+ // @formatter:on
+}
\ No newline at end of file
--- /dev/null
+package era.mi.logic.types;
+
+import static java.lang.String.format;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.RandomAccess;
+import java.util.function.BinaryOperator;
+import java.util.function.UnaryOperator;
+
+/**
+ * Immutable class representing a {@link Bit}Vector
+ *
+ *
+ * @author Christian Femers
+ *
+ */
+public final class BitVector implements StrictLogicType<BitVector>, Iterable<Bit>, RandomAccess
+{
+ private final Bit[] bits;
+
+ private BitVector(Bit[] bits)
+ {
+ this.bits = Objects.requireNonNull(bits);
+ }
+
+ public static BitVector of(Bit... bits)
+ {
+ return new BitVector(bits.clone());
+ }
+
+ public static BitVector of(Bit bit, int length)
+ {
+ return new BitVector(bit.makeArray(length));
+ }
+
+ public BitVectorMutator mutator()
+ {
+ return BitVectorMutator.of(this);
+ }
+
+ public Bit getBit(int bitIndex)
+ {
+ return bits[bitIndex];
+ }
+
+ public Bit[] getBits()
+ {
+ return bits.clone();
+ }
+
+ @Override
+ public BitVector join(BitVector t)
+ {
+ checkCompatibility(t);
+ return new BitVector(binOp(bits.clone(), t.bits, Bit::join));
+ }
+
+ @Override
+ public BitVector and(BitVector t)
+ {
+ checkCompatibility(t);
+ return new BitVector(binOp(bits.clone(), t.bits, Bit::and));
+ }
+
+ @Override
+ public BitVector or(BitVector t)
+ {
+ checkCompatibility(t);
+ return new BitVector(binOp(bits.clone(), t.bits, Bit::or));
+ }
+
+ @Override
+ public BitVector xor(BitVector t)
+ {
+ checkCompatibility(t);
+ return new BitVector(binOp(bits.clone(), t.bits, Bit::xor));
+ }
+
+ @Override
+ public BitVector not()
+ {
+ return new BitVector(unOp(bits.clone(), Bit::not));
+ }
+
+ public int length()
+ {
+ return bits.length;
+ }
+
+ public BitVector concat(BitVector other)
+ {
+ Bit[] newBits = Arrays.copyOf(bits, length() + other.length());
+ System.arraycopy(other.bits, 0, newBits, length(), other.length());
+ return new BitVector(newBits);
+ }
+
+ public BitVector subVector(int start)
+ {
+ return new BitVector(Arrays.copyOfRange(bits, start, length()));
+ }
+
+ public BitVector subVector(int start, int end)
+ {
+ return new BitVector(Arrays.copyOfRange(bits, start, end));
+ }
+
+ private void checkCompatibility(BitVector bv)
+ {
+ if (length() != bv.length())
+ throw new IllegalArgumentException(format("BitVector length does not match: %d and %d", length(), bv.length()));
+ }
+
+ static Bit[] binOp(Bit[] dest, Bit[] second, BinaryOperator<Bit> op)
+ {
+ if (dest == null)
+ return second.clone();
+ for (int i = 0; i < dest.length; i++)
+ {
+ dest[i] = op.apply(dest[i], second[i]);
+ }
+ return dest;
+ }
+
+ static Bit[] unOp(Bit[] dest, UnaryOperator<Bit> op)
+ {
+ if (dest == null)
+ return null;
+ for (int i = 0; i < dest.length; i++)
+ {
+ dest[i] = op.apply(dest[i]);
+ }
+ return dest;
+ }
+
+ /**
+ * Class for comfortable and efficient manipulation of {@link BitVector}s, similar to {@link StringBuilder}
+ *
+ * @author Christian Femers
+ */
+ @SuppressWarnings("synthetic-access")
+ public static final class BitVectorMutator implements LogicType<BitVectorMutator, BitVector>
+ {
+ private Bit[] bits;
+
+ private BitVectorMutator(Bit[] bits)
+ {
+ this.bits = bits;
+ }
+
+ static BitVectorMutator of(BitVector bv)
+ {
+ return new BitVectorMutator(bv.getBits());
+ }
+
+ /**
+ * Returns an empty mutator which has no bits set and will simply copy the values from the first binary operation performed.
+ *
+ */
+ public static BitVectorMutator empty()
+ {
+ return new BitVectorMutator(null);
+ }
+
+ /**
+ * Produces the resulting, immutable {@link BitVector}<br>
+ *
+ * @throws IllegalStateException if the mutator is (still) empty
+ */
+ public BitVector get()
+ {
+ if (bits == null)
+ throw new IllegalStateException("cannot create a BitVector from an empty mutator");
+ return new BitVector(bits);
+ }
+
+ @Override
+ public BitVectorMutator join(BitVector t)
+ {
+ checkCompatibility(t);
+ bits = binOp(bits, t.bits, Bit::join);
+ return this;
+ }
+
+ @Override
+ public BitVectorMutator and(BitVector t)
+ {
+ checkCompatibility(t);
+ bits = binOp(bits, t.bits, Bit::and);
+ return this;
+ }
+
+ @Override
+ public BitVectorMutator or(BitVector t)
+ {
+ checkCompatibility(t);
+ bits = binOp(bits, t.bits, Bit::or);
+ return this;
+ }
+
+ @Override
+ public BitVectorMutator xor(BitVector t)
+ {
+ checkCompatibility(t);
+ bits = binOp(bits, t.bits, Bit::xor);
+ return this;
+ }
+
+ @Override
+ public BitVectorMutator not()
+ {
+ unOp(bits, Bit::not);
+ return this;
+ }
+
+ private void checkCompatibility(BitVector bv)
+ {
+ if (bits != null && bits.length != bv.length())
+ throw new IllegalArgumentException(format("BitVector length does not match: %d and %d", bits.length, bv.length()));
+ }
+ }
+
+ /**
+ * @see Arrays#hashCode(Object[])
+ */
+ @Override
+ public int hashCode()
+ {
+ return Arrays.hashCode(bits);
+ }
+
+ /**
+ * Does test for equality of values/content
+ *
+ * @see Object#equals(Object)
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (!(obj instanceof BitVector))
+ return false;
+ BitVector other = (BitVector) obj;
+ return Arrays.equals(bits, other.bits);
+ }
+
+ /**
+ * Does test for equality of values/content, shifting the other BitVector by <code>offset</code> to the right.<br>
+ * Therefore <code>offset + other.length() <= this.length()</code> needs to be true.
+ *
+ * @throws ArrayIndexOutOfBoundsException if <code>offset + other.length() > this.length()</code>
+ *
+ * @see Object#equals(Object)
+ */
+ public boolean equals(BitVector other, int offset)
+ {
+ if (other == null)
+ return false;
+ return Arrays.equals(bits, offset, offset + other.length(), other.bits, 0, other.length());
+ }
+
+ /**
+ * All {@link Bit}s symbols concatenated together
+ *
+ * @see #parse(String)
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder(bits.length);
+ for (Bit bit : bits)
+ sb.append(bit);
+ return sb.toString();
+ }
+
+ /**
+ * Parses a String containing solely {@link Bit} symbols
+ *
+ * @see #toString()
+ */
+ public static BitVector parse(String s)
+ {
+ Bit[] values = new Bit[s.length()];
+ for (int i = 0; i < s.length(); i++)
+ {
+ values[i] = Bit.parse(s, i);
+ }
+ return new BitVector(values);
+ }
+
+ @Override
+ public Iterator<Bit> iterator()
+ {
+ return new Iterator<>()
+ {
+ private int pos = 0;
+
+ @Override
+ public Bit next()
+ {
+ if (!hasNext())
+ throw new NoSuchElementException();
+ return getBit(pos++);
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return pos != length();
+ }
+ };
+ }
+}
--- /dev/null
+package era.mi.logic.types;
+
+/**
+ * Interface for types that support the basic logic operations
+ *
+ * @author Christian Femers
+ *
+ * @param <T> the logic type itself, to make the operations closed in T
+ * @param <S> the operand type, may be the same as T, see {@link StrictLogicType}
+ */
+public interface LogicType<T extends LogicType<T, S>, S>
+{
+ /**
+ * Determines the result when two signals meet each other directly, also called resolution (IEEE 1164)
+ *
+ * For example:
+ *
+ * <pre>
+ * 0 joined 0 == 0
+ * 1 joined 0 == X
+ * 0 joined 1 == X
+ * 1 joined 1 == 1
+ * </pre>
+ *
+ * @param t the second logic signal
+ * @return the resulting value
+ * @author Christian Femers
+ */
+ T join(S t);
+
+ /**
+ * Classical logic AND
+ *
+ * For example:
+ *
+ * <pre>
+ * 0 AND 0 == 0
+ * 1 AND 0 == 0
+ * 0 AND 1 == 0
+ * 1 AND 1 == 1
+ * </pre>
+ *
+ * @param t the second logic signal
+ * @return the resulting value
+ * @author Christian Femers
+ */
+ T and(S t);
+
+ /**
+ * Classical logic OR
+ *
+ * For example:
+ *
+ * <pre>
+ * 0 OR 0 == 0
+ * 1 OR 0 == 1
+ * 0 OR 1 == 1
+ * 1 OR 1 == 1
+ * </pre>
+ *
+ * @param t the second logic signal
+ * @return the resulting value
+ * @author Christian Femers
+ */
+ T or(S t);
+
+ /**
+ * Classical logic XOR (exclusive OR)
+ *
+ * For example:
+ *
+ * <pre>
+ * 0 XOR 0 == 0
+ * 1 XOR 0 == 1
+ * 0 XOR 1 == 1
+ * 1 XOR 1 == 0
+ * </pre>
+ *
+ * @param t the second logic signal
+ * @return the resulting value
+ * @author Christian Femers
+ */
+ T xor(S t);
+
+ /**
+ * Classical logic NOT (logical negation)
+ *
+ * For example:
+ *
+ * <pre>
+ * NOT 0 == 1
+ * NOT 1 == 0
+ * </pre>
+ *
+ * @return the resulting value
+ * @author Christian Femers
+ */
+ T not();
+
+ /**
+ * {@link #and(Object) AND} and then {@link #not() NOT}
+ *
+ * @author Christian Femers
+ */
+ default T nand(S t)
+ {
+ return and(t).not();
+ }
+
+ /**
+ * {@link #or(Object) OR} and then {@link #not() NOT}
+ *
+ * @author Christian Femers
+ */
+ default T nor(S t)
+ {
+ return or(t).not();
+ }
+
+ /**
+ * {@link #xor(Object) XOR} and then {@link #not() NOT}<br>
+ * Used to determine equality (alias parity, consistency)
+ *
+ * @author Christian Femers
+ */
+ default T xnor(S t)
+ {
+ return xor(t).not();
+ }
+}
--- /dev/null
+package era.mi.logic.types;
+
+import java.util.function.BiFunction;
+
+import era.mi.logic.types.BitVector.BitVectorMutator;
+
+@FunctionalInterface
+public interface MutationOperation extends BiFunction<BitVectorMutator, BitVector, BitVectorMutator>
+{
+
+}
--- /dev/null
+package era.mi.logic.types;
+
+/**
+ * Interface for types that support the basic logic operations only among themselves, making it mathematically closed
+ *
+ * @author Christian Femers
+ * @see LogicType
+ *
+ * @param <T> the logic type itself to make the operations closed
+ */
+public interface StrictLogicType<T extends StrictLogicType<T>> extends LogicType<T, T>
+{
+ // this is just a matter of type parameters
+}
import java.util.Iterator;
import java.util.List;
-import era.mi.logic.Bit;
import era.mi.logic.Simulation;
import era.mi.logic.Util;
+import era.mi.logic.types.Bit;
/**
* Represents an array of wires that can store n bits of information.
Bit[] bits = input.getInputValues();
for (int i = 0; i < length; i++)
{
- newValues[i] = newValues[i].combineWith(bits[i]);
+ newValues[i] = newValues[i].join(bits[i]);
}
}
package era.mi.logic.wires;
-import era.mi.logic.Bit;
+import era.mi.logic.types.Bit;
public interface WireObserver
{