diff options
Diffstat (limited to 'common/nextpnr.h')
-rw-r--r-- | common/nextpnr.h | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/common/nextpnr.h b/common/nextpnr.h index 08c941a5..6d0dab86 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -275,6 +275,58 @@ struct Context : Arch bool verbose = false; Context(ArchArgs args) : Arch(args) {} + + // -------------------------------------------------------------- + + uint64_t rngstate = 0x3141592653589793; + + uint64_t rng64() + { + // xorshift64star + // https://arxiv.org/abs/1402.6246 + rngstate ^= rngstate >> 12; + rngstate ^= rngstate << 25; + rngstate ^= rngstate >> 27; + return rngstate * 0x2545F4914F6CDD1D; + } + + int rng() + { + return rng64() & 0x3fffffff; + } + + int rng(int n) + { + assert(n > 0); + + // round up to power of 2 + int m = n - 1; + m |= (m >> 1); + m |= (m >> 2); + m |= (m >> 4); + m |= (m >> 8); + m |= (m >> 16); + m += 1; + + while (1) { + int x = rng64() & (m-1); + if (x < n) return x; + } + } + + void rngseed(uint64_t seed) + { + rngstate = seed ? seed : 0x3141592653589793; + for (int i = 0; i < 5; i++) rng64(); + } + + template<typename T> + void shuffle(std::vector<T> &a) { + for (size_t i = 0; i != a.size(); i++) { + size_t j = i + rng(a.size() - i); + if (j > i) std::swap(a[i], a[j]); + } + } }; NEXTPNR_NAMESPACE_END |