104 lines
3.5 KiB
Python
Executable File
104 lines
3.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
from tabulate import tabulate
|
|
|
|
with open('input.txt') as f:
|
|
input_string = f.read().split('\n')
|
|
|
|
def twos_comp(num, length):
|
|
if num == 0:
|
|
return 0
|
|
return abs((num ^ ((1 << length) - 1)) + 1)
|
|
|
|
def logical_shiftr(num, length, times):
|
|
#print("SHIFT START___")
|
|
#print(bin(num))
|
|
for t in range(times):
|
|
num = (num >> 1) | ((1 << length) & num)
|
|
#print(bin(num))
|
|
#print("SHIFT END___")
|
|
return num
|
|
|
|
def convert_if_twoscomp(num, length):
|
|
if num & (1 << length - 1):
|
|
return (-1 * twos_comp(num, length))
|
|
return num & (1 << length) - 1
|
|
|
|
def debug(results):
|
|
headers = ['multiplicand bin', 'multiplier bin', 'multiplicand dec', 'multiplier dec', 'expected bin', 'expected dec', 'booth if correct', 'booth mod if correct']
|
|
table = []
|
|
for [multiplicand_bin, multiplier_bin, result_booth, result_booth_mod, length] in results:
|
|
multiplicand = convert_if_twoscomp(multiplicand_bin, length)
|
|
multiplier = convert_if_twoscomp(multiplier_bin, length)
|
|
expected = multiplicand * multiplier
|
|
expected_bin = (twos_comp(expected, length * 2), expected) [expected > 0]
|
|
success_b = [bin(result_booth), "PASS"] [result_booth == expected_bin]
|
|
success_bm = [bin(result_booth_mod), "PASS"] [result_booth_mod == expected_bin]
|
|
|
|
table.append([bin(multiplicand_bin), bin(multiplier_bin), multiplicand, multiplier, bin(expected_bin), expected, success_b, success_bm])
|
|
print("\nCHECKS: \n", tabulate(table, headers), "\n")
|
|
|
|
|
|
|
|
def booth(multiplier, multiplicand, length):
|
|
multiplicand_twos_comp = twos_comp(multiplicand, length)
|
|
result = multiplier << 1 # extended bit
|
|
for i in range(length):
|
|
op = result & 0b11
|
|
if op == 0b01:
|
|
result += multiplicand << (length + 1)
|
|
if op == 0b10:
|
|
result += multiplicand_twos_comp << (length + 1)
|
|
result &= (1 << (length * 2) + 1) - 1 # get rid of any overflows
|
|
result = logical_shiftr(result, length * 2, 1)
|
|
result = result >> 1
|
|
return result
|
|
|
|
def booth_mod(multiplier, multiplicand, length):
|
|
multiplicand_twos_comp = twos_comp(multiplicand, length)
|
|
result = multiplier << 1 # extended bit
|
|
operations = 0
|
|
for i in range(int(length / 2)):
|
|
match result & 0b111:
|
|
case 0b010 | 0b001: # add
|
|
result += multiplicand << (length + 1)
|
|
case 0b011: # add * 2
|
|
result += multiplicand << (length + 2) # extra shift is multiplying multiplicand by 2
|
|
case 0b100: # sub * 2
|
|
result += multiplicand_twos_comp << (length + 2)
|
|
case 0b101 | 0b110: # sub
|
|
result += multiplicand_twos_comp << (length + 1)
|
|
if result & (1 << length):
|
|
print("{}: overflow".format(bin(multiplicand)))
|
|
result &= (1 << ((length * 2) + 1)) - 1 # get rid of any overflows
|
|
result = logical_shiftr(result, length * 2, 2)
|
|
result = result >> 1
|
|
return result
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
headers = ['multiplicand', 'multiplier', 'result (bin)', 'result (hex)']
|
|
table = []
|
|
|
|
debug_results = []
|
|
|
|
for operation in input_string:
|
|
if operation == '' or operation[0] == '#':
|
|
continue
|
|
length = len(operation.split(" ")[0])
|
|
multiplicand = int(operation.split(" ")[0], 2)
|
|
multiplier = int(operation.split(" ")[1], 2)
|
|
|
|
|
|
result_booth = booth(multiplier, multiplicand, length)
|
|
result_mod_booth = booth_mod(multiplier, multiplicand, length)
|
|
table.append([bin(multiplicand), bin(multiplier), bin(result_booth), hex(result_booth)])
|
|
debug_results.append([multiplicand, multiplier, result_booth, result_mod_booth, length])
|
|
debug(debug_results)
|
|
print(tabulate(table, headers))
|
|
|
|
#generate table
|
|
|
|
|