3
\$\begingroup\$

I want to create a program(in Java) which simulates the functionality of Arithmetic Logistic Unit(ALU).

Here is my code. Please check is this correct. Can I implement it better?

    public class ALU {


    public static final int NOP = 0;

    public static final int SEQ = 1;
    public static final int SNE = 2;
    public static final int SGT = 3;
    public static final int SLE = 4;
    public static final int SLT = 5;

    public static final int ADD = 6;
    public static final int ADDU = 7;
    public static final int SUB = 8;
    public static final int SUBU = 9;
    public static final int MULT = 10;
    public static final int MULTU = 11;
    public static final int DIV = 12;
    public static final int DIVU = 13;


    public static final int AND = 14;
    public static final int OR = 15;
    public static final int XOR = 16;
    public static final int SLL = 17;
    public static final int SRL = 18;
    public static final int SRA = 19;


    public boolean[] getResult(boolean[] srcValue1, boolean[] srcValue2, int ope){
            boolean [] result = new boolean[32];
            int shift = 0; //ÒÆÎ»Êý
            long src1 = 0; 
            long src2 = 0;

            switch(ope){

            case NOP: break;

            case SEQ: 
                    if(toSigned(srcValue1,0,31) == toSigned(srcValue2,0,31))
                            result[31] = true;
                    break;
            case SNE: 
                    if(toSigned(srcValue1,0,31) != toSigned(srcValue2,0,31))
                            result[31] = true;
                    break;
            case SGT:
                    if(toSigned(srcValue1,0,31) > toSigned(srcValue2,0,31))
                            result[31] = true;
                    break;
            case SLE: 
                    if(toSigned(srcValue1,0,31) <= toSigned(srcValue2,0,31))
                            result[31] = true;
                    break;
            case SLT: 
                    if(toSigned(srcValue1,0,31) < toSigned(srcValue2,0,31))
                            result[31] = true;
                    break;

            case ADD: 
                    result = ADD(srcValue1,srcValue2);
                    break;

            case ADDU:
                    result = ADD(srcValue1,srcValue2);
                    break;
            case SUB: 
                    result = SUB(srcValue1,srcValue2);
                    break;
            case SUBU:
                    result = SUB(srcValue1,srcValue2);
                    break;
            case MULT: 
                    src1 = toSigned(srcValue1,0,31); 
                    src2 = toSigned(srcValue2,0,31);
                    result = long2Boolean(src1*src2);
                    break;
            case MULTU: 
                    src1 = toUnsigned(srcValue1,0,31); 
                    src2 = toUnsigned(srcValue2,0,31);
                    result = long2Boolean(src1*src2);
                    break;
            case DIV:
                    src1 = toSigned(srcValue1,0,31); 
                    src2 = toSigned(srcValue2,0,31);
                    result = long2Boolean(src1/src2);
                    break;
            case DIVU:
                    src1 = toUnsigned(srcValue1,0,31); 
                    src2 = toUnsigned(srcValue2,0,31);
                    result = long2Boolean(src1/src2);
                    break;

            case AND: 
                    for(int i=0;i<32;i++)
                            result[i] = srcValue1[i]&srcValue2[i];
                    break;
            case OR:
                    for(int i=0;i<32;i++)
                            result[i] = srcValue1[i]|srcValue2[i];
                    break;
            case XOR:
                    for(int i=0;i<32;i++){
                            result[i] = XOR(srcValue1[i],srcValue2[i]);
                    }
                    break;
            case SLL: 
                     shift = (int)toUnsigned(srcValue2,27,31);
                     for(int i=0;i<32-shift;i++)
                             result[i] = srcValue1[i+shift];
                     for(int i=32-shift;i<32;i++)
                             result[i] = false;
                    break;
            case SRL: 
                     shift = (int)toUnsigned(srcValue2,27,31);
                     for(int i=0;i<shift;i++)
                             result[i] = false;
                     for(int i=shift;i<32;i++)
                             result[i] = srcValue1[i-shift];
                    break;
            case SRA: 
                    shift = (int)toUnsigned(srcValue2,27,31);
                    boolean sign = srcValue1[0];
                    for(int i=0;i<shift;i++)
                             result[i] = sign;
                     for(int i=shift;i<32;i++)
                             result[i] = srcValue1[i-shift];
                    break;
            }
            return result;
    }

    private long toUnsigned(boolean[] data, int pos1, int pos2) {
            long number = 0;
            for (int i = pos1; i <= pos2; i++) {
                    if (data[i] == true)
                            number += (int) Math.pow(2, pos2 - i);
            }
            return number;
    }
    private long toSigned(boolean[] data, int pos1, int pos2) {
            long number = 0;
            for (int i = (pos1 + 1); i <= pos2; i++) {
                    if (data[i] == true)
                            number += (long) Math.pow(2, pos2 - i);
            }
            if (data[pos1] == true)
                    number = number - (long) Math.pow(2, pos2 - pos1);
            return number;
    }

    private boolean[] long2Boolean(long number){
            boolean[] result = new boolean[32];
            for(int i=0;i<32;i++){
                    int bit = (int) (number&1);
                    if(bit == 1)
                            result[31-i] = true;
                    number = number>>1;
            }
            return result;
    }
    private boolean XOR(boolean src1,boolean src2){
            boolean result = true;
                    if(src1 == src2 )
                            result = false;
            return result;
    }
    private boolean[] ADD(boolean[] srcValue1,boolean[] srcValue2){
            boolean Ci = false;
            boolean[]  result = new boolean[32];
            for(int i=31;i>=0;i--){
                    result[i] = XOR(XOR(srcValue1[i],srcValue2[i]),Ci);
                    Ci = (srcValue1[i]&srcValue2[i])|(XOR(srcValue1[i],srcValue2[i])&Ci);
            }
            return result;
    }

    private boolean[] SUB(boolean[] srcValue1,boolean[] srcValue2){
            boolean[]  result = new boolean[32];
            //¼ÆËãsrcValue2µÄ²¹Âë
            for(int i=0;i<32;i++)
                    srcValue2[i] = !srcValue2[i];
            boolean[] one = new boolean[32];
            one[31] = true;
            srcValue2 = ADD(srcValue1,srcValue2);
            result = ADD(srcValue1,srcValue2);
            return result;
    }
    public static void main(String[] args) {
            long a = (long)Math.pow(2, 33);
            boolean [] b = new ALU().long2Boolean(a);
            System.out.print(b.length+"\n");
            for(int i=0;i<32;i++)
                    System.out.println(b[i]);
    }


    }

Does this code satisfy all the functionality of Arithmetic Logistic Unit? . I just want to simulate the ALU functionality in my program. How to insert control bits in my program?

\$\endgroup\$
1
  • \$\begingroup\$ Please consider using a BitSet. It is provided by Java and you can abstract from all of this booleans. Then, you should only work with universal gates. For example, a NAND is universal. At the moment, you just do some more fancy looking way of the normal java arithmetic operations. And please, an ALU is a logic unit, it has nothing to do with logistic. Even if some electrons and bits are transported. This is just a comment, to make a complete answer would take days, or probably weeks, sorry. \$\endgroup\$
    – tb-
    Mar 5, 2013 at 12:35

3 Answers 3

4
\$\begingroup\$
  1. Enum might be the real solution to define the different possible operations.
  2. The implementation of the XOR method could be more concise : private boolean XOR(boolean src1,boolean src2){ return (src1 != src2 );} and you probably don't need it anyway because Java has a bitwise xor operator. Also, that would make your cases AND,OR and XOR more consistent.
  3. You should try to make your code a bit more consistent : sometimes you store toSigned(srcValue1,0,31) in a variable before using it, sometimes you don't. My feeling is that even though it's not great from a performance point of view because it makes you compute stuff you may not need, it might make things easier to do :

            long usrc1 = toUnsigned(srcvalue1,0,31);
            long usrc2 = toUnsigned(srcvalue2,0,31);
            long ssrc1 = toSigned(srcvalue1,0,31);
            long ssrc2 = toSigned(srcvalue2,0,31);
    

    to avoid the boring repetition in the rest of the method.

  4. On the other hand, shift could probably be declared and defined only when you need it : int shift = (int)toUnsigned(srcValue2,27,31);

  5. It might be worth pointing out that according to the Java specs, integers are 32 bits so you probably don't need to do everything with arrays of 32 booleans. My feeling is that it would make everything much easier and you'd be able to do things in a straighforward way. For instance, case SEQ: would become : `case SEQ: return (src1==src2);'. If you do so, I think most of the loops you write might not be useful anymore.

I don't have much time to go through the end of the code but I hope this is a good beginning.

\$\endgroup\$
2
  • \$\begingroup\$ Good stuff. About #5 I think the whole point of the exercise is to implement the bit-level operations without using Java's built-in arithmetic. \$\endgroup\$ Mar 2, 2013 at 19:53
  • \$\begingroup\$ David: You are right and your answer's much more relevant if this is a learning exercise :-) \$\endgroup\$
    – SylvainD
    Mar 2, 2013 at 23:49
3
\$\begingroup\$

Note: I would have reversed the bits in the array (sign bit in the last element) so the bit in position i represents 2 ^ i. The code below assumes this is the case.

Since you're writing this in Java, you should encapsulate it all into a new Int class. Assuming this is a learning exercise, you could even go so far as to model it as an array of thirty-two Bits.

class Int
{
    public static final int SIZE = 32;

    private Bit[] bits = new Bit[SIZE];

    public Int add(Int other) {
        Bit[] result = new Bit[SIZE];
        Bit carry = new Bit();
        for (int i = 0; i < SIZE; i++) {
            Bit bit1 = this.bits[i];
            Bit bit2 = other.bits[i];
            result[i] = bit1.xor(bit2).xor(carry);
            carry = bit1.and(bit2).or(bit1.xor(bit2)).and(carry);
        }
        return new Int(result);
    }
}

Here are some smaller tips:

  • You should use the boolean operators (&& and ||) with boolean values instead of the bitwise operators (& and |). Using the latter causes a lot of needless casting between int and boolean and depends on Java's turning true into 1 and false into 0.

  • Pre-calculate the thirty-two long bit positions using << up front and reuse them throughout instead of using Math.pow.

    public static final LONG_BITS = new long[32];
    static {
        for (int b = 0; b < 32; b++)
            LONG_BITS[b] = 1 << b;
    }
    
  • Testing a boolean value for truth can be shortened: if (data[i] == true) becomes if (data[i]).

  • The toSigned and toUnsigned methods are cheating a little by using += and -=. You should use the |=, &=, and ~ bit operators throughout. Of course, MUL and DIV are cheating a lot! ;)

  • Add overloaded versions of toSigned and toUnsigned for the most common case:

    public long toSigned(boolean[] data) { return toSigned(data, 0, 31); }
    public long toUnsigned(boolean[] data) { return toUnsigned(data, 0, 31); }
    
  • pos1 and pos2 are horrible names for these parameters. Is one the sign bit? Another the number of bits? Do they form a range of bits to convert to a long? Meaningful variable names will go a long way toward compensating for the lack of comments.

  • I would name the arrays (src1, data, etc.) for what they are: bits.

  • Do you need a NOT operand for taking the two's complement?

\$\endgroup\$
2
  • \$\begingroup\$ Do you need a NOT operand for taking the two's complement? Yes \$\endgroup\$
    – SuchZen
    Mar 3, 2013 at 6:52
  • \$\begingroup\$ @SuchZen - Actually, that should be NEG operator for the two's complement. A NOT operator would also be useful. Is there an official definition of what makes a complete ALU? \$\endgroup\$ Mar 3, 2013 at 9:00
1
\$\begingroup\$

Just a minor note (as far as I see nobody has mentioned it): 31, 32, 27 etc. are magic numbers here and the code uses them multiple times. They should be named constants. It would make the code easier to maintain (and you can easily switch to 64 or 16 bit).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.