# HG changeset patch # User Paul Boddie # Date 1695412554 -7200 # Node ID 80a1c6ce717bab95609da453810ce3530c11b760 # Parent e4d286a20f68dc483a201680f461ae7efc0dd72d Added a tool to model various clock dividers. diff -r e4d286a20f68 -r 80a1c6ce717b tools/dividers.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/dividers.py Fri Sep 22 21:55:54 2023 +0200 @@ -0,0 +1,97 @@ +#!/usr/bin/env python2 + +from math import ceil, floor +import sys + +def method2(f, s): + r = f / s + scale = getscale(r) + return scale * r, scale + +def is_integer(x): + target = round(x) * 1000 + #print x, target - 100, floor(x * 1000), target + 100 + return target - 100 < floor(x * 1000) < target + 100 + +def getscale(x): + scale = getscale_part(x) + if is_integer(scale): + return scale + return scale * getscale(scale) + +def getscale_part(x): + part = x - int(x) + if not part: + return 1 + elif part > 0.5: + return 1 / (1 - part) + else: + return 1 / part + +def reduce(m, n, m_limit, n_limit): + while m > m_limit and n > n_limit and m > 1 and n > 1: + m /= 2 + n /= 2 + return m, n + +def show(s, m, n, f_label="f"): + print "m =", m + print "n =", n + print "%s' =" % f_label, s * m / n + print "%s' ~=" % f_label, s * round(m) / round(n) + +if len(sys.argv) < 4: + f, s = map(float, sys.argv[1:3]) + m, n = method2(f, s) + m, n = reduce(m, n, 0x200, 0x100000) + show(s, m, n) + +else: + f, s, i_min, i_max = map(float, sys.argv[1:5]) + + # Constraints: + # + # i_min < s * m' / di < i_max + # i_min / s < m' / di < i_max / s + # + # f = s * m' / (di * do) + # f = (s * m' / di) / do + # f * do = s * m' / di + # + # i_min < f * do < i_max + # i_min / f < do < i_max / f + # + # f = s * m / n + # + # s * m' / (di * do) = s * m / n + # m' / (di * do) = m / n + # m' = (m / n) * (di * do) + # m' / di = (m / n) * do + + do_min = ceil(i_min / f) + do_max = floor(i_max / f) + + do = do_min + + print do_min, "<= do <=", do_max + + while do <= do_max: + do0 = int(do ** 0.5) + do1 = int(do / do0) + if do0 * do1 == int(do): + i = do * f + m, n = method2(i, s) + m, n = reduce(m, n, 0x3f, 0x3f) + if m <= 0x3f and n <= 0x3f: + show(i, m, n, "i") + print "do =", do + print "do0 =", do0 + print "do1 =", do1 + print "f' =", s * m / (n * do) + print "f' ~=", s * round(m) / (round(n) * round(do)) + break + else: + print "Ignored: m =", m, "n =", n, "do0 =", do0, "do1 =", do1 + do += 1 + +# vim: tabstop=4 expandtab shiftwidth=4