Hazard3/hdl/arith/muldiv_model.py

66 lines
1.8 KiB
Python
Executable File

#!/usr/bin/env python3
# Quick reference model for sequential unsigned multiply/divide/modulo
def div_step(w, accum, divisor):
sub_tmp = accum - (divisor << (w - 1))
underflow = sub_tmp < 0
if not underflow:
accum = sub_tmp
accum = (accum << 1) | (not underflow)
return accum
def divmod(w, dividend, divisor, debug=True):
accum = dividend
for i in range(w):
accum_prev = accum
accum = div_step(w, accum, divisor)
if debug:
print("Step {:02d}: accum {:0{}x} -> {:0{}x}".format(
i, accum_prev, int(w / 2), accum, int(w / 2)))
return (accum >> w, accum & ((1 << w) - 1))
def mul_step(w, accum, multiplicand):
add_en = accum & 1
accum = accum >> 1
if add_en:
accum += (multiplicand << (w - 1))
return accum
def mul(w, multiplicand, multiplier, debug=True):
accum = multiplier
for i in range(w):
accum_prev = accum
accum = mul_step(w, accum, multiplicand)
if debug:
print("Step {:02d}: accum {:0{}x} -> {:0{}x}".format(
i, accum_prev, int(w / 2), accum, int(w / 2)))
return (accum >> w, accum & ((1 << w) - 1))
def divtest(w=4):
for i in range(2 ** w):
for j in range(1, 2 ** w):
gatemod, gatediv = divmod(w, i, j, debug=False)
goldmod, golddiv = (i % j, i // j)
print("{:02d} % {:02d} = {:02d} (gold {:02d}); ./. = {:02d} (gold {:02d})"
.format(i, j, gatemod, goldmod, gatediv, golddiv))
assert(gatemod == goldmod)
assert(gatediv == golddiv)
def multest(w=4):
for i in range(2 ** w):
for j in range(2 ** w):
gateh, gatel = mul(w, i, j, debug=False)
gold = i * j
goldl, goldh = (gold & ((1 << w) - 1), gold >> w)
print("{:02d} * {:02d} = ({:02d} (gold {:02d}), {:02d} (gold {:02d})"
.format(i, j, gateh, goldh, gatel, goldl))
assert(gatel == goldl)
assert(gateh == goldh)
if __name__ == "__main__":
print("Test division:")
divtest()
print("Test multiplication:")
multest()