X-Git-Url: https://mograsim.net/gitweb/?a=blobdiff_plain;f=net.mograsim.logic.core%2Fsrc%2Fnet%2Fmograsim%2Flogic%2Fcore%2Ftypes%2FBitVector.java;h=6a36403475c1ef7a2f5d5296b98d9a5268f046b8;hb=add92039f433cd315f2087da9c1a0de899927d96;hp=1e87f9a43cba1c5ec9c4d181571843987b0d599b;hpb=67c1d352795802dae0c045cedeed82c883819d4e;p=Mograsim.git diff --git a/net.mograsim.logic.core/src/net/mograsim/logic/core/types/BitVector.java b/net.mograsim.logic.core/src/net/mograsim/logic/core/types/BitVector.java index 1e87f9a4..6a364034 100644 --- a/net.mograsim.logic.core/src/net/mograsim/logic/core/types/BitVector.java +++ b/net.mograsim.logic.core/src/net/mograsim/logic/core/types/BitVector.java @@ -2,6 +2,7 @@ package net.mograsim.logic.core.types; import static java.lang.String.format; +import java.math.BigInteger; import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; @@ -13,48 +14,137 @@ import java.util.function.UnaryOperator; /** * Immutable class representing a {@link Bit}Vector * - * * @author Christian Femers * */ public final class BitVector implements StrictLogicType, Iterable, RandomAccess { + public static final BitVector SINGLE_U = new BitVector(Bit.U); + public static final BitVector SINGLE_X = new BitVector(Bit.X); + public static final BitVector SINGLE_0 = new BitVector(Bit.ZERO); + public static final BitVector SINGLE_1 = new BitVector(Bit.ONE); + public static final BitVector SINGLE_Z = new BitVector(Bit.Z); + + private static final BitVector[] SINGLE_BIT_MAPPING = { SINGLE_U, SINGLE_X, SINGLE_0, SINGLE_1, SINGLE_Z }; + private final Bit[] bits; + private BitVector(Bit single) + { + Objects.requireNonNull(single); + bits = new Bit[] { single }; + } + private BitVector(Bit[] bits) { - this.bits = Objects.requireNonNull(bits); + this.bits = Objects.requireNonNull(bits); // do this first to "catch" bits==null before the foreach loop + for (Bit bit : bits) + if (bit == null) + throw new NullPointerException(); } public static BitVector of(Bit... bits) { + if (bits.length == 1) + return SINGLE_BIT_MAPPING[bits[0].ordinal()]; return new BitVector(bits.clone()); } public static BitVector of(Bit bit, int length) { + if (length == 1) + return SINGLE_BIT_MAPPING[bit.ordinal()]; return new BitVector(bit.makeArray(length)); } + public BigInteger getUnsignedValue() + { + if (!isBinary()) + throw new NumberFormatException("BitVector is non binary: " + toString()); + byte[] bytes = new byte[(bits.length / 8) + 1]; + for (int i = 0; i < bits.length; i++) + { + if (Bit.ONE == bits[i]) + { + bytes[i / 8] |= 1 << (i % 8); + } + } + return new BigInteger(bytes); + } + + public static BitVector from(BigInteger b, int length) + { + int bitLength = b.bitLength(); + int actualLength = Integer.min(bitLength, length); + Bit[] bits = new Bit[length]; + for (int i = 0; i < actualLength; i++) + bits[i] = b.testBit(i) ? Bit.ONE : Bit.ZERO; + if (b.signum() < 0) + for (int i = actualLength; i < length; i++) + bits[i] = Bit.ONE; + else + for (int i = actualLength; i < length; i++) + bits[i] = Bit.ZERO; + return BitVector.of(bits); + } + + public static BitVector of(long value, int bits) + { + return of(BigInteger.valueOf(value), bits); + } + + public static BitVector of(BigInteger value, int bits) + { + Bit[] values = new Bit[bits]; + for (int i = 0; i < bits; i++) + { + values[bits - i - 1] = Bit.of(value.testBit(i)); + } + return new BitVector(values); + } + public BitVectorMutator mutator() { return BitVectorMutator.of(this); } - public Bit getBit(int bitIndex) + /** + * Returns the most significant bit at bitIndex. (leftmost bit of a binary number at the given index) + */ + public Bit getMSBit(int bitIndex) { return bits[bitIndex]; } + /** + * Returns the least significant bit at bitIndex. (rightmost bit of a binary number at the given index) + */ + public Bit getLSBit(int bitIndex) + { + return bits[bits.length - bitIndex - 1]; + } + public Bit[] getBits() { return bits.clone(); } + public boolean isBinary() + { + for (int i = 0; i < bits.length; i++) + { + if (!bits[i].isBinary()) + return false; + } + return true; + } + @Override public BitVector join(BitVector t) { checkCompatibility(t); + if (bits.length == 1) + return SINGLE_BIT_MAPPING[bits[0].join(t.bits[0]).ordinal()]; return new BitVector(binOp(bits.clone(), t.bits, Bit::join)); } @@ -62,6 +152,8 @@ public final class BitVector implements StrictLogicType, Iterable, Iterable, Iterable, Iterable { private Bit[] bits; @@ -155,21 +252,39 @@ public final class BitVector implements StrictLogicType, Iterablewith all bits set to null. Use with care! + */ + public static BitVectorMutator ofLength(int length) + { + return new BitVectorMutator(new Bit[length]); + } + /** * Returns an empty mutator which has no bits set and will simply copy the values from the first binary operation performed. - * + *

+ * An empty BitVectorMutator must not be converted to BitVector or used to manipulate single bits until at least one two + * operand logic operation is performed. */ public static BitVectorMutator empty() { return new BitVectorMutator(null); } + /** + * @see #empty() + */ + public boolean isEmpty() + { + return bits == null; + } + /** * Produces the resulting, immutable {@link BitVector}
* * @throws IllegalStateException if the mutator is (still) empty */ - public BitVector get() + public BitVector toBitVector() { if (bits == null) throw new IllegalStateException("cannot create a BitVector from an empty mutator"); @@ -215,6 +330,53 @@ public final class BitVector implements StrictLogicType, IterablebitIndex. (leftmost bit of a binary number at the given index) + */ + public void setMSBit(int bitIndex, Bit bit) + { + if (bits == null) + throw new IllegalStateException("cannot set a bit of an empty mutator"); + bits[bitIndex] = bit; + } + + /** + * Set the least significant bit at bitIndex. (rightmost bit of a binary number at the given index) + */ + public void setLSBit(int bitIndex, Bit bit) + { + if (bits == null) + throw new IllegalStateException("cannot set a bit of an empty mutator"); + bits[bits.length - bitIndex - 1] = bit; + } + + /** + * Returns the most significant bit at bitIndex. (leftmost bit of a binary number at the given index) + */ + public Bit getMSBit(int bitIndex) + { + if (bits == null) + throw new IllegalStateException("cannot get a bit of an empty mutator"); + return bits[bitIndex]; + } + + /** + * Returns the least significant bit at bitIndex. (rightmost bit of a binary number at the given index) + */ + public Bit getLSBit(int bitIndex) + { + if (bits == null) + throw new IllegalStateException("cannot get a bit of an empty mutator"); + return bits[bits.length - bitIndex - 1]; + } + + public int length() + { + if (bits == null) + throw new IllegalStateException("cannot obtain a length of an empty mutator"); + return bits.length; + } + private void checkCompatibility(BitVector bv) { if (bits != null && bits.length != bv.length()) @@ -263,7 +425,7 @@ public final class BitVector implements StrictLogicType, Iterable, Iterable, Iterablefrom MSB to LSB (left to right). + */ @Override public Iterator iterator() { @@ -303,7 +485,7 @@ public final class BitVector implements StrictLogicType, Iterable