From dfc2ffb9735cadb92a7cce9c2e95d2f02de42fe0 Mon Sep 17 00:00:00 2001 From: TheLastRar Date: Thu, 15 Aug 2024 14:30:18 +0100 Subject: [PATCH] Replace rand48 with std::linear_congruential_engine in simulator (#110) --- src/aarch64/logic-aarch64.cc | 7 ++++--- src/aarch64/simulator-aarch64.cc | 9 ++++----- src/aarch64/simulator-aarch64.h | 9 +++++++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/aarch64/logic-aarch64.cc b/src/aarch64/logic-aarch64.cc index 4d50568e..e1416ea6 100644 --- a/src/aarch64/logic-aarch64.cc +++ b/src/aarch64/logic-aarch64.cc @@ -168,11 +168,12 @@ SimFloat16 Simulator::UFixedToFloat16(uint64_t src, uint64_t Simulator::GenerateRandomTag(uint16_t exclude) { - uint64_t rtag = nrand48(rand_state_) >> 28; + // Generate a 4 bit integer from a 48bit random number + uint64_t rtag = rand_gen_() >> 44; VIXL_ASSERT(IsUint4(rtag)); if (exclude == 0) { - exclude = nrand48(rand_state_) >> 27; + exclude = rand_gen_() >> 44; } // TODO: implement this to better match the specification, which calls for a @@ -7487,7 +7488,7 @@ void Simulator::SVEFaultTolerantLoadHelper(VectorFormat vform, // Non-faulting loads are allowed to fail arbitrarily. To stress user // code, fail a random element in roughly one in eight full-vector loads. - uint32_t rnd = static_cast(jrand48(rand_state_)); + uint32_t rnd = static_cast(rand_gen_()); int fake_fault_at_lane = rnd % (LaneCountFromFormat(vform) * 8); for (int i = 0; i < LaneCountFromFormat(vform); i++) { diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc index 83d1649a..9f5c56de 100644 --- a/src/aarch64/simulator-aarch64.cc +++ b/src/aarch64/simulator-aarch64.cc @@ -594,9 +594,8 @@ Simulator::Simulator(Decoder* decoder, FILE* stream, SimStack::Allocated stack) guard_pages_ = false; // Initialize the common state of RNDR and RNDRRS. - uint16_t seed[3] = {11, 22, 33}; - VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rand_state_)); - memcpy(rand_state_, seed, sizeof(rand_state_)); + uint64_t seed = (11 + (22 << 16) + (static_cast(33) << 32)); + rand_gen_.seed(seed); // Initialize all bits of pseudo predicate register to true. LogicPRegister ones(pregister_all_true_); @@ -6947,8 +6946,8 @@ void Simulator::VisitSystem(const Instruction* instr) { break; case RNDR: case RNDRRS: { - uint64_t high = jrand48(rand_state_); - uint64_t low = jrand48(rand_state_); + uint64_t high = rand_gen_(); + uint64_t low = rand_gen_(); uint64_t rand_num = (high << 32) | (low & 0xffffffff); WriteXRegister(instr->GetRt(), rand_num); // Simulate successful random number generation. diff --git a/src/aarch64/simulator-aarch64.h b/src/aarch64/simulator-aarch64.h index 6e36246d..0a8d2fe4 100644 --- a/src/aarch64/simulator-aarch64.h +++ b/src/aarch64/simulator-aarch64.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -5431,11 +5432,15 @@ class Simulator : public DecoderVisitor { CPUFeaturesAuditor cpu_features_auditor_; std::vector saved_cpu_features_; - // State for *rand48 functions, used to simulate randomness with repeatable + // linear_congruential_engine, used to simulate randomness with repeatable // behaviour (so that tests are deterministic). This is used to simulate RNDR // and RNDRRS, as well as to simulate a source of entropy for architecturally // undefined behaviour. - uint16_t rand_state_[3]; + std::linear_congruential_engine(1) << 48> + rand_gen_; // A configurable size of SVE vector registers. unsigned vector_length_;