mirror of
https://github.com/seL4/seL4.git
synced 2026-03-27 10:29:57 +00:00
mcs: Add reciprocal.py
Used for calculating constants for reciprocal division.
This commit is contained in:
65
tools/reciprocal.py
Executable file
65
tools/reciprocal.py
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright 2019, Data61
|
||||
# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
||||
# ABN 41 687 119 230.
|
||||
#
|
||||
# This software may be distributed and modified according to the terms of
|
||||
# the GNU General Public License version 2. Note that NO WARRANTY is provided.
|
||||
# See "LICENSE_GPLv2.txt" for details.
|
||||
#
|
||||
# @TAG(DATA61_GPL)
|
||||
#
|
||||
|
||||
# this script can be used to calculate the reciprocal for
|
||||
# unsigned division of an unknown 64 bit value by a known 64bit
|
||||
# constant. It is used to calculate the correct magic numbers
|
||||
# for fixed cpu times on arm in order to do 64 bit division to calculate
|
||||
# ticks -> microseconds.
|
||||
|
||||
# for details on how this script works,
|
||||
# see Hacker's delight, Chapter 10, unsigned division.
|
||||
from math import floor, ceil
|
||||
import argparse
|
||||
import sys
|
||||
from past.builtins import xrange
|
||||
|
||||
# now unsigned
|
||||
|
||||
|
||||
def magicgu(nmax, d):
|
||||
nc = ((nmax + 1)//d)*d - 1
|
||||
nbits = len(bin(nmax)) - 2
|
||||
for p in range(0, 2*nbits + 1):
|
||||
if 2**p > nc*(d - 1 - (2**p - 1) % d):
|
||||
m = (2**p + d - 1 - (2**p - 1) % d)//d
|
||||
return (m, p)
|
||||
print("Can't find p, something is wrong.")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def do_div(n):
|
||||
return ((n + add_ind) * magic) >> shift_amt
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate magic numbers for emulating 64-bit division with multiplication by reciprocal using algorithm from Hacker's Delight, chapter 10.")
|
||||
parser.add_argument("--divisor", type=int, required=True,
|
||||
help="Devisor to calculate magic numbers for")
|
||||
args = parser.parse_args()
|
||||
|
||||
magic, shift_amt = magicgu(2**32 - 1, args.divisor)
|
||||
print("magic number is: %d, shift amount is %d" % (magic, shift_amt))
|
||||
add_ind = 0
|
||||
|
||||
print("Doing sanity check")
|
||||
# sanity check
|
||||
for i in xrange(2**32-1):
|
||||
q1, q2 = (i / args.divisor, do_div(i))
|
||||
if int(q1) != q2:
|
||||
print("Combination failed %d %d %d" % i, q1, q2)
|
||||
sys.exit(-1)
|
||||
|
||||
print("Success! Use (n * %d) >> %d to calculate n / %d" % (magic, shift_amt, args.divisor))
|
||||
print("magic number is: %d, shift amount is %d" % (magic, shift_amt))
|
||||
Reference in New Issue
Block a user