|
def intToBool(Number: int, bitlength: int = 8): |
|
Number = bin(Number)[2:].zfill(bitlength) |
|
numArr = [] |
|
|
|
if len(Number) > bitlength: |
|
raise ValueError( |
|
f"bit length allowed: {bitlength}, number bit count: {len(Number)} " |
|
) |
|
|
|
for i in range(bitlength): |
|
if Number[i] == "0": |
|
numArr.append(False) |
|
elif Number[i] == "1": |
|
numArr.append(True) |
|
|
|
return numArr |
|
|
|
|
|
debug = False |
|
|
|
|
|
def alu( |
|
A: int, |
|
B: int, |
|
invA: bool = False, |
|
invB: bool = False, |
|
enableOr: bool = False, |
|
floodCarry: bool = False, |
|
carryIn: bool = False, |
|
bitlength: int = 8, |
|
): |
|
""" |
|
returns: (result, carryOut) |
|
""" |
|
if A < 0: |
|
A = bin(A)[3:].zfill(bitlength) |
|
print(A) if debug else None |
|
A = int("".join(["1" if bit == "0" else "0" for bit in A]), 2) + 1 |
|
if B < 0: |
|
B = bin(B)[3:].zfill(bitlength) |
|
print(B) if debug else None |
|
B = int("".join(["1" if bit == "0" else "0" for bit in B]), 2) + 1 |
|
|
|
A = intToBool(A, bitlength) |
|
B = intToBool(B, bitlength) |
|
result = [] |
|
|
|
if invA: |
|
A = [not i for i in A] |
|
if invB: |
|
B = [not i for i in B] |
|
|
|
print(A) if debug else None |
|
print(B) if debug else None |
|
|
|
for i in range(bitlength - 1, -1, -1): # from lsb to msb, instead of msb to lsb |
|
print("i:", i) if debug else None |
|
print("carry in:", carryIn) if debug else None |
|
print("A: ", A[i]) if debug else None |
|
print("B: ", B[i]) if debug else None |
|
|
|
# DeprecationWarning: Bitwise inversion '~' on bool is deprecated. (this means ill use "and not" instead of "& !") |
|
# Shoutout to mr_nano for clearing things up for me, huge thanks to him |
|
result.insert(0, carryIn ^ (A[i] | B[i] if enableOr else A[i] ^ B[i])) |
|
|
|
if floodCarry: |
|
carryIn = True |
|
elif enableOr: |
|
carryIn = False |
|
else: |
|
carryIn = (A[i] & B[i]) | (A[i] & carryIn) | (B[i] & carryIn) |
|
|
|
print(A, B, carryIn) if debug else None |
|
print(result) if debug else None |
|
|
|
negativeFlag = result[0] |
|
parityFlag = sum(result) % 2 == 0 |
|
overflowFlag = A[0] == B[0] and A[0] != result[0] |
|
|
|
result = int("".join(["1" if i else "0" for i in result]), 2) |
|
|
|
zeroFlag = result == 0 |
|
|
|
return { |
|
"result": result, |
|
"flags": { |
|
"carry": carryIn, |
|
"zero": zeroFlag, |
|
"negative": negativeFlag, |
|
"parity": parityFlag, |
|
"overflow": overflowFlag, |
|
}, |
|
} |
|
|
|
|
|
def compute(mode: str, a: int, b: int): |
|
mode.lower() |
|
|
|
match mode: |
|
case "add": |
|
return alu( |
|
a, |
|
b, |
|
invA=False, |
|
invB=False, |
|
enableOr=False, |
|
floodCarry=False, |
|
carryIn=False, |
|
) |
|
case "subtract": |
|
return alu( |
|
a, |
|
b, |
|
invA=False, |
|
invB=True, |
|
enableOr=False, |
|
floodCarry=False, |
|
carryIn=True, |
|
) |
|
case "or": |
|
return alu( |
|
a, |
|
b, |
|
invA=False, |
|
invB=False, |
|
enableOr=True, |
|
floodCarry=False, |
|
carryIn=False, |
|
) |
|
case "nor": |
|
return alu( |
|
a, |
|
b, |
|
invA=False, |
|
invB=False, |
|
enableOr=True, |
|
floodCarry=True, |
|
carryIn=True, |
|
) |
|
case "and": |
|
return alu( |
|
a, |
|
b, |
|
invA=True, |
|
invB=True, |
|
enableOr=True, |
|
floodCarry=True, |
|
carryIn=True, |
|
) |
|
case "nand": |
|
return alu( |
|
a, |
|
b, |
|
invA=True, |
|
invB=True, |
|
enableOr=True, |
|
floodCarry=False, |
|
carryIn=False, |
|
) |
|
case "xor": |
|
return alu( |
|
a, |
|
b, |
|
invA=False, |
|
invB=True, |
|
enableOr=False, |
|
floodCarry=True, |
|
carryIn=True, |
|
) |
|
case "xnor": |
|
return alu( |
|
a, |
|
b, |
|
invA=False, |
|
invB=False, |
|
enableOr=False, |
|
floodCarry=True, |
|
carryIn=True, |
|
) |
|
case _: |
|
return alu( |
|
a, |
|
b, |
|
invA=False, |
|
invB=False, |
|
enableOr=False, |
|
floodCarry=False, |
|
carryIn=False, |
|
) |
|
|
|
|
|
output = compute("xnor", 0b1100, 0b1010) |
|
|
|
import json |
|
|
|
print(json.dumps(output, indent=2)) |
|
print(f"result in binary: {bin(output["result"])[2:].zfill(8)}") |