diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index d60995df7f..5ed908e396 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -632,7 +632,7 @@ ISA::readMiscReg(RegIndex idx) tc->setReg(cc_reg::Nz, (RegVal)0); tc->setReg(cc_reg::C, (RegVal)0); tc->setReg(cc_reg::V, (RegVal)0); - return random_mt.random(); + return rng->random(); case MISCREG_RNDRRS: tc->setReg(cc_reg::Nz, (RegVal)0); tc->setReg(cc_reg::C, (RegVal)0); @@ -641,7 +641,7 @@ ISA::readMiscReg(RegIndex idx) // The random number generator already has an hardcoded // seed for the sake of determinism. There is no point // in simulating non-determinism here - return random_mt.random(); + return rng->random(); // Generic Timer registers case MISCREG_CNTFRQ ... MISCREG_CNTVOFF: diff --git a/src/arch/arm/isa.hh b/src/arch/arm/isa.hh index f60bd2c1d7..d3a6c6da00 100644 --- a/src/arch/arm/isa.hh +++ b/src/arch/arm/isa.hh @@ -53,6 +53,7 @@ #include "arch/arm/types.hh" #include "arch/arm/utility.hh" #include "arch/generic/isa.hh" +#include "base/random.hh" #include "debug/Checkpoint.hh" #include "enums/DecoderFlavor.hh" #include "sim/sim_object.hh" @@ -111,6 +112,8 @@ namespace ArmISA SelfDebug * selfDebug; + Random::RandomPtr rng = Random::genRandom(); + const MiscRegLUTEntryInitializer InitReg(uint32_t reg) { diff --git a/src/arch/riscv/process.cc b/src/arch/riscv/process.cc index a9ad7b1d32..0a3d6a6c35 100644 --- a/src/arch/riscv/process.cc +++ b/src/arch/riscv/process.cc @@ -44,7 +44,6 @@ #include "base/loader/elf_object.hh" #include "base/loader/object_file.hh" #include "base/logging.hh" -#include "base/random.hh" #include "cpu/thread_context.hh" #include "debug/Stack.hh" #include "mem/page_table.hh" @@ -172,7 +171,7 @@ RiscvProcess::argsInit(int pageSize) memState->setStackMin(memState->getStackMin() - RandomBytes); uint8_t at_random[RandomBytes]; std::generate(std::begin(at_random), std::end(at_random), - [&]{ return random_mt.random(0, 0xFF); }); + [&]{ return rng->random(0, 0xFF); }); initVirtMem->writeBlob(memState->getStackMin(), at_random, RandomBytes); // Copy argv to stack diff --git a/src/arch/riscv/process.hh b/src/arch/riscv/process.hh index 64b9593965..1372f8e153 100644 --- a/src/arch/riscv/process.hh +++ b/src/arch/riscv/process.hh @@ -33,6 +33,7 @@ #include #include +#include "base/random.hh" #include "mem/page_table.hh" #include "sim/process.hh" #include "sim/syscall_abi.hh" @@ -56,6 +57,9 @@ class RiscvProcess : public Process public: virtual bool mmapGrowsDown() const override { return false; } + + protected: + Random::RandomPtr rng = Random::genRandom(); }; class RiscvProcess64 : public RiscvProcess diff --git a/src/base/random.cc b/src/base/random.cc index e861767c1e..19815e4009 100644 --- a/src/base/random.cc +++ b/src/base/random.cc @@ -45,12 +45,6 @@ namespace gem5 { -Random::Random() -{ - // default random seed - init(5489); -} - Random::Random(uint32_t s) { init(s); @@ -58,6 +52,26 @@ Random::Random(uint32_t s) Random::~Random() { + assert(instances); + + int removed = 0; + + instances->erase(std::remove_if(instances->begin(), instances->end(), + [&](const auto& s_ptr) + { + removed += s_ptr.expired(); + return s_ptr.expired(); + })); + + // Can only remove one pointer + // since we are destroying one + // object + assert(removed == 1); + + if (instances->empty()) { + delete instances; + instances = nullptr; + } } void @@ -66,6 +80,7 @@ Random::init(uint32_t s) gen.seed(s); } -Random random_mt; +uint64_t Random::globalSeed = 5489; +Random::Instances* Random::instances = nullptr; } // namespace gem5 diff --git a/src/base/random.hh b/src/base/random.hh index 0d58e62fef..0b287f9505 100644 --- a/src/base/random.hh +++ b/src/base/random.hh @@ -48,6 +48,7 @@ #include #include #include +#include #include "base/compiler.hh" #include "base/logging.hh" @@ -58,25 +59,91 @@ namespace gem5 class Random { + friend class RandomTest; public: + using RandomPtr = std::shared_ptr; + using Instances = std::vector>; + + static RandomPtr genRandom() + { + if (!instances) + instances = new Instances(); + + auto ptr = std::shared_ptr(new Random(globalSeed)); + instances->emplace_back(ptr); + return ptr; + } + + static RandomPtr genRandom(uint32_t s) + { + if (!instances) + instances = new Instances(); + + auto ptr = std::shared_ptr(new Random(s)); + instances->emplace_back(ptr); + return ptr; + } + + static uint64_t globalSeed; /** * @ingroup api_base_utils */ std::mt19937_64 gen; + private: + /** + * Collection of all live instances + * of Random to enable global + * reseeding. We use a pointer + * because the loader will initialize + * it to 0x0 (it is in .bss), allowing us to avoid + * Static Initialization Order Fiasco + * if static Random instances are inialized + * before the vector by having the constructors + * of Random allocate memory for the pointer. + * This requires that nullptr matches how + * the loader initializes memory + */ + static_assert(nullptr == 0x0, "nullptr is not 0x0, Random instance tracking will fail"); + static Instances* instances; + /** * @ingroup api_base_utils * @{ */ - Random(); + Random() = delete; Random(uint32_t s); + + Random(const Random& rng) = delete; + Random& operator=(const Random& rng) = delete; + + Random(Random&& rng) = delete; + Random& operator=(Random&& rng) = delete; + + public: /** @} */ // end of api_base_utils ~Random(); void init(uint32_t s); + /** + * Facility to reseed all live instances + * and ensure future default constructed + * instances also use the new see + */ + static void reseedAll(uint64_t seed) + { + globalSeed = seed; + + if (instances == nullptr) + return; + + for (auto rng_ptr : *instances) + rng_ptr.lock()->init(seed); + } + /** * Use the SFINAE idiom to choose an implementation based on * whether the type is integral or floating point. @@ -118,11 +185,6 @@ class Random } }; -/** - * @ingroup api_base_utils - */ -extern Random random_mt; - } // namespace gem5 #endif // __BASE_RANDOM_HH__ diff --git a/src/base/random.test.cc b/src/base/random.test.cc index 3b23f20aab..4c9eeff34b 100644 --- a/src/base/random.test.cc +++ b/src/base/random.test.cc @@ -30,11 +30,38 @@ #include #include +#include +#include +#include #include "base/gtest/logging.hh" #include "base/random.hh" +namespace gem5 +{ + +/** + * Helper class to access private members of + * Random + */ +class RandomTest : public ::testing::Test +{ + public: + static Random::Instances* getInstances() + { + return Random::instances; + } + + static uint64_t getGlobalSeed() + { + return Random::globalSeed; + } +}; + +} + using namespace gem5; +using RandomPtr = gem5::Random::RandomPtr; /** * Checking that default construction uses the default @@ -42,40 +69,41 @@ using namespace gem5; */ TEST(RandomCtor, UInt64DefaultConstruct) { + ASSERT_EQ(RandomTest::getGlobalSeed(), std::mt19937_64::default_seed); // Init seed was default seed 5489 - Random dut; + RandomPtr dut = Random::genRandom(); + ASSERT_EQ(RandomTest::getGlobalSeed(), std::mt19937_64::default_seed); // First uint64_t corresponds to the default seed - ASSERT_EQ(dut.random(), 14514284786278117030llu); + ASSERT_EQ(dut->random(), 14514284786278117030llu); } TEST(RandomCtor, DoubleDefaultConstruct) { // Init seed was default seed 5489 - Random dut; + RandomPtr dut = Random::genRandom(); // First double corresponds to the default seed // 14514284786278117030llu / std::numeric_limits::max() - ASSERT_EQ(dut.random(), + ASSERT_EQ(dut->random(), 0.7868209548678020137657540544751100242137908935546875d); } TEST(RandomCtor, FloatDefaultConstruct) { // Init seed was default seed 5489 - Random dut; + RandomPtr dut = Random::genRandom(); // First float corresponds to the default seed // 14514284786278117030llu / std::numeric_limits::max() - ASSERT_EQ(dut.random(), 0.786820948123931884765625f); + ASSERT_EQ(dut->random(), 0.786820948123931884765625f); } - /** * Checking that default construction uses the default * see as specified by the standard */ TEST(RandomCtor, ConstructUserSpecifiedSeed) { - Random dut{42}; - ASSERT_EQ(dut.random(), 13930160852258120406llu); + RandomPtr dut = Random::genRandom(42); + ASSERT_EQ(dut->random(), 13930160852258120406llu); } /** @@ -84,10 +112,10 @@ TEST(RandomCtor, ConstructUserSpecifiedSeed) */ TEST(RandomCtor, ConstructThenReseed) { - Random dut{}; - ASSERT_EQ(dut.random(), 14514284786278117030llu); - dut.init(42); - ASSERT_EQ(dut.random(), 13930160852258120406llu); + RandomPtr dut = Random::genRandom(); + ASSERT_EQ(dut->random(), 14514284786278117030llu); + dut->init(42); + ASSERT_EQ(dut->random(), 13930160852258120406llu); } /** @@ -96,12 +124,12 @@ TEST(RandomCtor, ConstructThenReseed) */ TEST(RandomRange, MinEqualsMax) { - Random dut; + RandomPtr dut = Random::genRandom(); for (int i = 0; i < 10; i++) { - ASSERT_EQ(dut.random(0, 0), 0); - ASSERT_EQ(dut.random(1, 1), 1); - ASSERT_EQ(dut.random(-1, -1), -1); + ASSERT_EQ(dut->random(0, 0), 0); + ASSERT_EQ(dut->random(1, 1), 1); + ASSERT_EQ(dut->random(-1, -1), -1); } } @@ -127,14 +155,14 @@ bool withinFreqRange(int count) */ TEST(RandomRange, Coverage) { - Random dut; + RandomPtr dut = Random::genRandom(); // Count occurences if we want to check // frequencies in the future std::unordered_map values; for (int i = 0; i < loopCount; i++) { - values[dut.random(4,6)]++; + values[dut->random(4,6)]++; } ASSERT_EQ(values.count(4), 1); @@ -147,7 +175,7 @@ TEST(RandomRange, Coverage) values.clear(); for (int i = 0; i < loopCount; i++) { - values[dut.random(-1,1)]++; + values[dut->random(-1,1)]++; } ASSERT_EQ(values.count(-1), 1); @@ -161,7 +189,7 @@ TEST(RandomRange, Coverage) values.clear(); for (int i = 0; i < loopCount; i++) { - values[dut.random(-6,-4)]++; + values[dut->random(-6,-4)]++; } ASSERT_EQ(values.count(-6), 1); @@ -173,6 +201,88 @@ TEST(RandomRange, Coverage) ASSERT_EQ(withinFreqRange(values[-4]), true); } + + +/** + * Test that all constructed objects get + * added to the live instance list + */ +TEST(RandomConstruct, LiveInstancesAdd) +{ + RandomPtr base_rng = Random::genRandom(); + RandomPtr my_rng = Random::genRandom(); + + // All pointers have been added + ASSERT_EQ(RandomTest::getInstances()->size(), 2); + + std::set ptrs = { base_rng.get(), my_rng.get() }; + + // The correct pointers have been added + ASSERT_EQ(std::count_if( + RandomTest::getInstances()->begin(), + RandomTest::getInstances()->end(), + [&](const auto & rng) { return ptrs.count(rng.lock().get()) != 0;}), 2); +} + +/** + * Test that all destructed objects get + * removed from the live instance list + */ +TEST(RandomConstruct, LiveInstancesRemove) +{ + { + RandomPtr base_rng = Random::genRandom(); + { + RandomPtr my_rng = Random::genRandom(42); + ASSERT_EQ(RandomTest::getInstances()->size(), 2); + } + ASSERT_EQ(RandomTest::getInstances()->size(), 1); + } + ASSERT_EQ(RandomTest::getInstances(), nullptr); +} + +/** + * Test that reseeding after construction with + * an explicit seed works + */ +TEST(RandomReseed, ConstructThenReseed) +{ + RandomPtr rng = Random::genRandom(); + ASSERT_EQ(rng->random(), 14514284786278117030llu); + rng->init(42); + ASSERT_EQ(rng->random(), 13930160852258120406llu); + ASSERT_EQ(RandomTest::getGlobalSeed(), std::mt19937_64::default_seed); +} + +/** + * Test if global reseeding updates seed + * of live instances + */ +TEST(RandomReseed, GlobalReseedLive) +{ + RandomPtr base_rng = Random::genRandom(); + RandomPtr my_rng = Random::genRandom(1337); + + ASSERT_EQ(base_rng->random(), 14514284786278117030llu); + ASSERT_EQ(my_rng->random(), 12913197394697896830llu); + + Random::reseedAll(42); + + ASSERT_EQ(base_rng->random(), 13930160852258120406llu); + ASSERT_EQ(my_rng->random(), 13930160852258120406llu); +} + +/** + * Test if global reseeding updates seed + * of future instances + */ +TEST(RandomReseed, GlobalReseedFuture) +{ + Random::reseedAll(42); + RandomPtr base_rng = Random::genRandom(); + ASSERT_EQ(base_rng->random(), 13930160852258120406llu); +} + /** Test that the range provided for random * number generation is valid */ @@ -182,6 +292,6 @@ TEST(RandomDeathTest, InvalidRange) GTEST_SKIP() << "Skipping as assertions are " "stripped out of fast builds"; #endif - Random dut; - ASSERT_DEATH(dut.random(4, 2), ""); + RandomPtr dut = Random::genRandom(); + ASSERT_DEATH(dut->random(4, 2), ""); } diff --git a/src/cpu/minor/cpu.hh b/src/cpu/minor/cpu.hh index a966519c56..2d31dbbb11 100644 --- a/src/cpu/minor/cpu.hh +++ b/src/cpu/minor/cpu.hh @@ -88,6 +88,8 @@ class MinorCPU : public BaseCPU * Elements of pipeline call TheISA to implement the model. */ minor::Pipeline *pipeline; + Random::RandomPtr rng = Random::genRandom(); + public: /** Activity recording for pipeline. This belongs to Pipeline but * stages will access it through the CPU as the MinorCPU object @@ -186,7 +188,7 @@ class MinorCPU : public BaseCPU } std::shuffle(prio_list.begin(), prio_list.end(), - random_mt.gen); + rng->gen); return prio_list; } diff --git a/src/cpu/o3/fetch.cc b/src/cpu/o3/fetch.cc index 452545e871..b0bea842f5 100644 --- a/src/cpu/o3/fetch.cc +++ b/src/cpu/o3/fetch.cc @@ -48,7 +48,6 @@ #include #include "arch/generic/tlb.hh" -#include "base/random.hh" #include "base/types.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" @@ -881,7 +880,7 @@ Fetch::tick() // Pick a random thread to start trying to grab instructions from auto tid_itr = activeThreads->begin(); std::advance(tid_itr, - random_mt.random(0, activeThreads->size() - 1)); + rng->random(0, activeThreads->size() - 1)); while (available_insts != 0 && insts_to_decode < decodeWidth) { ThreadID tid = *tid_itr; diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 2c6da6708a..a6957a660a 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -43,6 +43,7 @@ #include "arch/generic/decoder.hh" #include "arch/generic/mmu.hh" +#include "base/random.hh" #include "base/statistics.hh" #include "cpu/o3/comm.hh" #include "cpu/o3/dyn_inst_ptr.hh" @@ -200,6 +201,8 @@ class Fetch /** To probe when a fetch request is successfully sent. */ ProbePointArg *ppFetchRequestSent; + Random::RandomPtr rng = Random::genRandom(); + public: /** Fetch constructor. */ Fetch(CPU *_cpu, const BaseO3CPUParams ¶ms); diff --git a/src/cpu/pred/loop_predictor.cc b/src/cpu/pred/loop_predictor.cc index 9e34e5141a..7ef3107738 100644 --- a/src/cpu/pred/loop_predictor.cc +++ b/src/cpu/pred/loop_predictor.cc @@ -45,7 +45,6 @@ #include "cpu/pred/loop_predictor.hh" -#include "base/random.hh" #include "base/trace.hh" #include "debug/LTage.hh" #include "params/LoopPredictor.hh" @@ -256,9 +255,9 @@ LoopPredictor::loopUpdate(Addr pc, bool taken, BranchInfo* bi, bool tage_pred) } } else if (useDirectionBit ? (bi->predTaken != taken) : taken) { - if ((random_mt.random() & 3) == 0 || !restrictAllocation) { + if ((rng->random() & 3) == 0 || !restrictAllocation) { //try to allocate an entry on taken branch - int nrand = random_mt.random(); + int nrand = rng->random(); for (int i = 0; i < (1 << logLoopTableAssoc); i++) { int loop_hit = (nrand + i) & ((1 << logLoopTableAssoc) - 1); idx = finallindex(bi->loopIndex, bi->loopIndexB, loop_hit); diff --git a/src/cpu/pred/loop_predictor.hh b/src/cpu/pred/loop_predictor.hh index 333cb3b34e..c92c2e78f4 100644 --- a/src/cpu/pred/loop_predictor.hh +++ b/src/cpu/pred/loop_predictor.hh @@ -44,6 +44,7 @@ #ifndef __CPU_PRED_LOOP_PREDICTOR_HH__ #define __CPU_PRED_LOOP_PREDICTOR_HH__ +#include "base/random.hh" #include "base/statistics.hh" #include "base/types.hh" #include "sim/sim_object.hh" @@ -70,6 +71,8 @@ class LoopPredictor : public SimObject const uint16_t loopNumIterMask; const int loopSetMask; + mutable Random::RandomPtr rng = Random::genRandom(); + // Prediction Structures // Loop Predictor Entry struct LoopEntry diff --git a/src/cpu/pred/ltage.cc b/src/cpu/pred/ltage.cc index 3da443d20d..4c0063f615 100644 --- a/src/cpu/pred/ltage.cc +++ b/src/cpu/pred/ltage.cc @@ -51,7 +51,6 @@ #include "base/intmath.hh" #include "base/logging.hh" -#include "base/random.hh" #include "base/trace.hh" #include "debug/Fetch.hh" #include "debug/LTage.hh" @@ -126,7 +125,7 @@ LTAGE::update(ThreadID tid, Addr pc, bool taken, void * &bp_history, return; } - int nrand = random_mt.random() & 3; + int nrand = rng->random() & 3; if (bi->tageBranchInfo->condBranch) { DPRINTF(LTage, "Updating tables for branch:%lx; taken?:%d\n", pc, taken); diff --git a/src/cpu/pred/multiperspective_perceptron.cc b/src/cpu/pred/multiperspective_perceptron.cc index fd54ec8163..b6909178c4 100644 --- a/src/cpu/pred/multiperspective_perceptron.cc +++ b/src/cpu/pred/multiperspective_perceptron.cc @@ -50,7 +50,6 @@ #include "cpu/pred/multiperspective_perceptron.hh" -#include "base/random.hh" #include "debug/Branch.hh" namespace gem5 @@ -513,7 +512,7 @@ MultiperspectivePerceptron::train(ThreadID tid, MPPBranchInfo &bi, bool taken) do { // udpate a random weight int besti = -1; - int nrand = random_mt.random() % specs.size(); + int nrand = rng->random() % specs.size(); int pout; found = false; for (int j = 0; j < specs.size(); j += 1) { @@ -685,7 +684,7 @@ MultiperspectivePerceptron::update(ThreadID tid, Addr pc, bool taken, // filter, blow a random filter entry away if (decay && transition && ((threadData[tid]->occupancy > decay) || (decay == 1))) { - int rnd = random_mt.random() % + int rnd = rng->random() % threadData[tid]->filterTable.size(); FilterEntry &frand = threadData[tid]->filterTable[rnd]; if (frand.seenTaken && frand.seenUntaken) { diff --git a/src/cpu/pred/multiperspective_perceptron.hh b/src/cpu/pred/multiperspective_perceptron.hh index f761607a29..85711feb29 100644 --- a/src/cpu/pred/multiperspective_perceptron.hh +++ b/src/cpu/pred/multiperspective_perceptron.hh @@ -54,6 +54,7 @@ #include #include +#include "base/random.hh" #include "cpu/pred/bpred_unit.hh" #include "params/MultiperspectivePerceptron.hh" @@ -306,6 +307,8 @@ class MultiperspectivePerceptron : public BPredUnit /** Transfer function for 5-width tables */ static int xlat4[]; + Random::RandomPtr rng = Random::genRandom(); + /** History data is kept for each thread */ struct ThreadData { diff --git a/src/cpu/pred/multiperspective_perceptron_tage.cc b/src/cpu/pred/multiperspective_perceptron_tage.cc index 1075f9d04f..5980ac3801 100644 --- a/src/cpu/pred/multiperspective_perceptron_tage.cc +++ b/src/cpu/pred/multiperspective_perceptron_tage.cc @@ -113,7 +113,7 @@ MPP_TAGE::handleAllocAndUReset(bool alloc, bool taken, int a = 1; - if ((random_mt.random() & 127) < 32) { + if ((rng->random() & 127) < 32) { a = 2; } int dep = bi->hitBank + a; @@ -195,7 +195,7 @@ void MPP_TAGE::adjustAlloc(bool & alloc, bool taken, bool pred_taken) { // Do not allocate too often if the prediction is ok - if ((taken == pred_taken) && ((random_mt.random() & 31) != 0)) { + if ((taken == pred_taken) && ((rng->random() & 31) != 0)) { alloc = false; } } @@ -269,7 +269,7 @@ MPP_LoopPredictor::calcConf(int index) const bool MPP_LoopPredictor::optionalAgeInc() const { - return ((random_mt.random() & 7) == 0); + return ((rng->random() & 7) == 0); } MPP_StatisticalCorrector::MPP_StatisticalCorrector( @@ -644,7 +644,7 @@ MultiperspectivePerceptronTAGE::update(ThreadID tid, Addr pc, bool taken, tage->getPathHist(tid)); tage->condBranchUpdate(tid, pc, taken, bi->tageBranchInfo, - random_mt.random(), target, + rng->random(), target, bi->predictedTaken, true); updateHistories(tid, *bi, taken); diff --git a/src/cpu/pred/multiperspective_perceptron_tage.hh b/src/cpu/pred/multiperspective_perceptron_tage.hh index 9c7ee3556f..e16bdfef32 100644 --- a/src/cpu/pred/multiperspective_perceptron_tage.hh +++ b/src/cpu/pred/multiperspective_perceptron_tage.hh @@ -51,6 +51,7 @@ #ifndef __CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_TAGE_HH__ #define __CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_TAGE_HH__ +#include "base/random.hh" #include "cpu/pred/loop_predictor.hh" #include "cpu/pred/multiperspective_perceptron.hh" #include "cpu/pred/statistical_corrector.hh" @@ -69,6 +70,9 @@ namespace branch_prediction class MPP_TAGE : public TAGEBase { std::vector tunedHistoryLengths; + + Random::RandomPtr rng = Random::genRandom(); + public: struct BranchInfo : public TAGEBase::BranchInfo { diff --git a/src/cpu/pred/tage.cc b/src/cpu/pred/tage.cc index 35c0d75352..9afb4868f8 100644 --- a/src/cpu/pred/tage.cc +++ b/src/cpu/pred/tage.cc @@ -83,7 +83,7 @@ TAGE::update(ThreadID tid, Addr pc, bool taken, void * &bp_history, return; } - int nrand = random_mt.random() & 3; + int nrand = rng->random() & 3; if (bi->tageBranchInfo->condBranch) { DPRINTF(Tage, "Updating tables for branch:%lx; taken?:%d\n", pc, taken); diff --git a/src/cpu/pred/tage.hh b/src/cpu/pred/tage.hh index 6d4151cb11..0bfee5e06a 100644 --- a/src/cpu/pred/tage.hh +++ b/src/cpu/pred/tage.hh @@ -62,6 +62,7 @@ #include +#include "base/random.hh" #include "base/types.hh" #include "cpu/pred/bpred_unit.hh" #include "cpu/pred/tage_base.hh" @@ -78,6 +79,8 @@ class TAGE: public BPredUnit protected: TAGEBase *tage; + Random::RandomPtr rng = Random::genRandom(); + struct TageBranchInfo { TAGEBase::BranchInfo *tageBranchInfo; diff --git a/src/cpu/pred/tage_sc_l.cc b/src/cpu/pred/tage_sc_l.cc index a178ba6fc6..73bddeccf2 100644 --- a/src/cpu/pred/tage_sc_l.cc +++ b/src/cpu/pred/tage_sc_l.cc @@ -54,7 +54,6 @@ #include "cpu/pred/tage_sc_l.hh" -#include "base/random.hh" #include "debug/TageSCL.hh" namespace gem5 @@ -73,7 +72,7 @@ TAGE_SC_L_LoopPredictor::calcConf(int index) const bool TAGE_SC_L_LoopPredictor::optionalAgeInc() const { - return (random_mt.random() & 7) == 0; + return (rng->random() & 7) == 0; } TAGE_SC_L::TAGE_SC_L(const TAGE_SC_LParams &p) @@ -308,7 +307,7 @@ void TAGE_SC_L_TAGE::adjustAlloc(bool & alloc, bool taken, bool pred_taken) { // Do not allocate too often if the prediction is ok - if ((taken == pred_taken) && ((random_mt.random() & 31) != 0)) { + if ((taken == pred_taken) && ((rng->random() & 31) != 0)) { alloc = false; } } @@ -317,11 +316,11 @@ int TAGE_SC_L_TAGE::calcDep(TAGEBase::BranchInfo* bi) { int a = 1; - if ((random_mt.random() & 127) < 32) { + if ((rng->random() & 127) < 32) { a = 2; } return ((((bi->hitBank - 1 + 2 * a) & 0xffe)) ^ - (random_mt.random() & 1)); + (rng->random() & 1)); } void @@ -443,7 +442,7 @@ TAGE_SC_L::update(ThreadID tid, Addr pc, bool taken, void *&bp_history, return; } - int nrand = random_mt.random() & 3; + int nrand = rng->random() & 3; if (tage_bi->condBranch) { DPRINTF(TageSCL, "Updating tables for branch:%lx; taken?:%d\n", pc, taken); diff --git a/src/cpu/pred/tage_sc_l.hh b/src/cpu/pred/tage_sc_l.hh index 6c56e69982..96edd8973c 100644 --- a/src/cpu/pred/tage_sc_l.hh +++ b/src/cpu/pred/tage_sc_l.hh @@ -55,6 +55,7 @@ #ifndef __CPU_PRED_TAGE_SC_L_HH__ #define __CPU_PRED_TAGE_SC_L_HH__ +#include "base/random.hh" #include "cpu/pred/ltage.hh" #include "cpu/pred/statistical_corrector.hh" #include "params/TAGE_SC_L.hh" @@ -80,6 +81,9 @@ class TAGE_SC_L_TAGE : public TAGEBase const bool truncatePathHist; + protected: + Random::RandomPtr rng = Random::genRandom(); + public: struct BranchInfo : public TAGEBase::BranchInfo { diff --git a/src/cpu/pred/tage_sc_l_8KB.cc b/src/cpu/pred/tage_sc_l_8KB.cc index 04b9588289..9b34d5d92c 100644 --- a/src/cpu/pred/tage_sc_l_8KB.cc +++ b/src/cpu/pred/tage_sc_l_8KB.cc @@ -208,7 +208,7 @@ TAGE_SC_L_TAGE_8KB::handleAllocAndUReset( if (noSkip[i]) { if (gtable[i][bi->tableIndices[i]].u == 0) { gtable[i][bi->tableIndices[i]].u = - ((random_mt.random() & 31) == 0); + ((rng->random() & 31) == 0); // protect randomly from fast replacement gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i]; gtable[i][bi->tableIndices[i]].ctr = taken ? 0 : -1; @@ -223,7 +223,7 @@ TAGE_SC_L_TAGE_8KB::handleAllocAndUReset( int8_t ctr = gtable[i][bi->tableIndices[i]].ctr; if ((gtable[i][bi->tableIndices[i]].u == 1) & (abs (2 * ctr + 1) == 1)) { - if ((random_mt.random() & 7) == 0) { + if ((rng->random() & 7) == 0) { gtable[i][bi->tableIndices[i]].u = 0; } } else { diff --git a/src/cpu/testers/directedtest/SeriesRequestGenerator.cc b/src/cpu/testers/directedtest/SeriesRequestGenerator.cc index 0d1afea7e5..886f391214 100644 --- a/src/cpu/testers/directedtest/SeriesRequestGenerator.cc +++ b/src/cpu/testers/directedtest/SeriesRequestGenerator.cc @@ -29,7 +29,6 @@ #include "cpu/testers/directedtest/SeriesRequestGenerator.hh" -#include "base/random.hh" #include "base/trace.hh" #include "cpu/testers/directedtest/DirectedGenerator.hh" #include "cpu/testers/directedtest/RubyDirectedTester.hh" @@ -67,7 +66,7 @@ SeriesRequestGenerator::initiate() requestorId); Packet::Command cmd; - bool do_write = (random_mt.random(0, 100) < m_percent_writes); + bool do_write = (rng->random(0, 100) < m_percent_writes); if (do_write) { cmd = MemCmd::WriteReq; } else { diff --git a/src/cpu/testers/directedtest/SeriesRequestGenerator.hh b/src/cpu/testers/directedtest/SeriesRequestGenerator.hh index a273d4012e..edebdbdde7 100644 --- a/src/cpu/testers/directedtest/SeriesRequestGenerator.hh +++ b/src/cpu/testers/directedtest/SeriesRequestGenerator.hh @@ -35,6 +35,7 @@ #ifndef __CPU_DIRECTEDTEST_SERIESREQUESTGENERATOR_HH__ #define __CPU_DIRECTEDTEST_SERIESREQUESTGENERATOR_HH__ +#include "base/random.hh" #include "cpu/testers/directedtest/DirectedGenerator.hh" #include "cpu/testers/directedtest/RubyDirectedTester.hh" #include "mem/ruby/protocol/SeriesRequestGeneratorStatus.hh" @@ -60,6 +61,7 @@ class SeriesRequestGenerator : public DirectedGenerator uint32_t m_active_node; uint32_t m_addr_increment_size; uint32_t m_percent_writes; + Random::RandomPtr rng = Random::genRandom(); }; } // namespace gem5 diff --git a/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.cc b/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.cc index fc3d620414..1a32c04883 100644 --- a/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.cc +++ b/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.cc @@ -35,7 +35,6 @@ #include #include "base/logging.hh" -#include "base/random.hh" #include "base/statistics.hh" #include "debug/GarnetSyntheticTraffic.hh" #include "mem/packet.hh" @@ -151,7 +150,7 @@ GarnetSyntheticTraffic::tick() // - send pkt if this number is < injRate*(10^precision) bool sendAllowedThisCycle; double injRange = pow((double) 10, (double) precision); - unsigned trySending = random_mt.random(0, (int) injRange); + unsigned trySending = rng->random(0, (int) injRange); if (trySending < injRate*injRange) sendAllowedThisCycle = true; else @@ -196,7 +195,7 @@ GarnetSyntheticTraffic::generatePkt() { destination = singleDest; } else if (traffic == UNIFORM_RANDOM_) { - destination = random_mt.random(0, num_destinations - 1); + destination = rng->random(0, num_destinations - 1); } else if (traffic == BIT_COMPLEMENT_) { dest_x = radix - src_x - 1; dest_y = radix - src_y - 1; @@ -285,7 +284,7 @@ GarnetSyntheticTraffic::generatePkt() if (injReqType < 0 || injReqType > 2) { // randomly inject in any vnet - injReqType = random_mt.random(0, 2); + injReqType = rng->random(0, 2); } if (injReqType == 0) { diff --git a/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.hh b/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.hh index def3ed29a2..4db7cacef8 100644 --- a/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.hh +++ b/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.hh @@ -31,6 +31,7 @@ #include +#include "base/random.hh" #include "base/statistics.hh" #include "mem/port.hh" #include "params/GarnetSyntheticTraffic.hh" @@ -135,6 +136,8 @@ class GarnetSyntheticTraffic : public ClockedObject RequestorID requestorId; + Random::RandomPtr rng = Random::genRandom(); + void completeRequest(PacketPtr pkt); void generatePkt(); diff --git a/src/cpu/testers/gpu_ruby_test/address_manager.cc b/src/cpu/testers/gpu_ruby_test/address_manager.cc index 83d8a1a277..ad49049351 100644 --- a/src/cpu/testers/gpu_ruby_test/address_manager.cc +++ b/src/cpu/testers/gpu_ruby_test/address_manager.cc @@ -36,7 +36,6 @@ #include "base/intmath.hh" #include "base/logging.hh" -#include "base/random.hh" #include "base/trace.hh" namespace gem5 @@ -59,14 +58,15 @@ AddressManager::AddressManager(int n_atomic_locs, int n_normal_locs_per_atomic) randAddressMap[i] = (Addr)((i + 128) << floorLog2(sizeof(Value))); } - // randomly shuffle randAddressMap. The seed is determined by the random_mt - // gem5 rng. This allows for deterministic randomization. + // randomly shuffle randAddressMap. The seed is determined by the rng + // internal to the object to avoid interactions with other components std::shuffle( randAddressMap.begin(), randAddressMap.end(), + // TODO: This is a bug unrelated to this draft PR but the GPU tester is // useful for testing this PR. - std::default_random_engine(random_mt.random(0,UINT_MAX-1)) + std::default_random_engine(rng->random(0,UINT_MAX)) ); // initialize atomic locations @@ -103,7 +103,7 @@ AddressManager::Location AddressManager::getAtomicLoc() { Location ret_atomic_loc = \ - random_mt.random() % numAtomicLocs; + rng->random() % numAtomicLocs; atomicStructs[ret_atomic_loc]->startLocSelection(); return ret_atomic_loc; } @@ -209,7 +209,7 @@ AddressManager::AtomicStruct::getLoadLoc() // locArray [firstMark : arraySize-1] int range_size = arraySize - firstMark; Location ret_loc = locArray[ - firstMark + random_mt.random() % range_size + firstMark + rng->random() % range_size ]; // update loadStoreMap @@ -243,7 +243,7 @@ AddressManager::AtomicStruct::getStoreLoc() // we can pick any location btw [firstMark : secondMark-1] int range_size = secondMark - firstMark; Location ret_loc = locArray[ - firstMark + random_mt.random() % range_size + firstMark + rng->random() % range_size ]; // update loadStoreMap diff --git a/src/cpu/testers/gpu_ruby_test/address_manager.hh b/src/cpu/testers/gpu_ruby_test/address_manager.hh index 3a76365062..3392c5324f 100644 --- a/src/cpu/testers/gpu_ruby_test/address_manager.hh +++ b/src/cpu/testers/gpu_ruby_test/address_manager.hh @@ -37,6 +37,7 @@ #include #include +#include "base/random.hh" #include "base/types.hh" #include "sim/eventq.hh" @@ -235,6 +236,8 @@ class AddressManager typedef std::unordered_set ExpectedValueSet; ExpectedValueSet expectedValues; + Random::RandomPtr rng = Random::genRandom(); + // swap two locations in locArray void swap(LocProperty& prop_1, LocProperty& prop_2); @@ -270,6 +273,8 @@ class AddressManager // internal log table typedef std::vector LogTable; LogTable logTable; + + Random::RandomPtr rng = Random::genRandom(); }; } // namespace gem5 diff --git a/src/cpu/testers/gpu_ruby_test/episode.cc b/src/cpu/testers/gpu_ruby_test/episode.cc index 7e16b0ef07..feacbb338a 100644 --- a/src/cpu/testers/gpu_ruby_test/episode.cc +++ b/src/cpu/testers/gpu_ruby_test/episode.cc @@ -34,7 +34,6 @@ #include #include -#include "base/random.hh" #include "cpu/testers/gpu_ruby_test/protocol_tester.hh" #include "cpu/testers/gpu_ruby_test/tester_thread.hh" @@ -101,7 +100,7 @@ Episode::initActions() int num_loads = numLoads; int num_stores = numStores; while ((num_loads + num_stores) > 0) { - switch (random_mt.random() % 2) { + switch (rng->random() % 2) { case 0: // Load if (num_loads > 0) { actions.push_back(new Action(Action::Type::LOAD, diff --git a/src/cpu/testers/gpu_ruby_test/episode.hh b/src/cpu/testers/gpu_ruby_test/episode.hh index a597b3a932..1d54e2e17b 100644 --- a/src/cpu/testers/gpu_ruby_test/episode.hh +++ b/src/cpu/testers/gpu_ruby_test/episode.hh @@ -34,6 +34,7 @@ #include +#include "base/random.hh" #include "cpu/testers/gpu_ruby_test/address_manager.hh" namespace gem5 @@ -112,6 +113,8 @@ class Episode typedef std::vector AtomicLocationList; AtomicLocationList atomicLocs; + Random::RandomPtr rng = Random::genRandom(); + // is a thread running this episode? bool isActive; // episode length = num_loads + num_stores diff --git a/src/cpu/testers/gpu_ruby_test/protocol_tester.cc b/src/cpu/testers/gpu_ruby_test/protocol_tester.cc index 6b3f9e19f1..f74872dc24 100644 --- a/src/cpu/testers/gpu_ruby_test/protocol_tester.cc +++ b/src/cpu/testers/gpu_ruby_test/protocol_tester.cc @@ -35,7 +35,6 @@ #include #include -#include "base/random.hh" #include "cpu/testers/gpu_ruby_test/cpu_thread.hh" #include "cpu/testers/gpu_ruby_test/dma_thread.hh" #include "cpu/testers/gpu_ruby_test/gpu_wavefront.hh" @@ -145,7 +144,7 @@ ProtocolTester::ProtocolTester(const Params &p) // Note: random_m5 will use a fixed key if random_seed is not set. // This ensures a reproducable. if (p.random_seed != 0) { - random_mt.init(p.random_seed); + rng->init(p.random_seed); } else { warn( "If `random_seed == 0` (or `random_seed` is unset) " diff --git a/src/cpu/testers/gpu_ruby_test/protocol_tester.hh b/src/cpu/testers/gpu_ruby_test/protocol_tester.hh index dcd5b35018..0752818779 100644 --- a/src/cpu/testers/gpu_ruby_test/protocol_tester.hh +++ b/src/cpu/testers/gpu_ruby_test/protocol_tester.hh @@ -52,6 +52,7 @@ #include #include +#include "base/random.hh" #include "base/types.hh" #include "cpu/testers/gpu_ruby_test/address_manager.hh" #include "mem/packet.hh" @@ -197,6 +198,8 @@ class ProtocolTester : public ClockedObject bool sentExitSignal; OutputStream* logFile; + + Random::RandomPtr rng = Random::genRandom(); }; } // namespace gem5 diff --git a/src/cpu/testers/gpu_ruby_test/tester_thread.cc b/src/cpu/testers/gpu_ruby_test/tester_thread.cc index dbcfba8c3c..84df0aa148 100644 --- a/src/cpu/testers/gpu_ruby_test/tester_thread.cc +++ b/src/cpu/testers/gpu_ruby_test/tester_thread.cc @@ -33,7 +33,6 @@ #include -#include "base/random.hh" #include "debug/ProtocolTest.hh" namespace gem5 @@ -147,7 +146,7 @@ void TesterThread::issueNewEpisode() { int num_reg_loads = \ - random_mt.random() % tester->getEpisodeLength(); + rng->random() % tester->getEpisodeLength(); int num_reg_stores = tester->getEpisodeLength() - num_reg_loads; // create a new episode diff --git a/src/cpu/testers/gpu_ruby_test/tester_thread.hh b/src/cpu/testers/gpu_ruby_test/tester_thread.hh index f31a5a3dea..ec6d21fa61 100644 --- a/src/cpu/testers/gpu_ruby_test/tester_thread.hh +++ b/src/cpu/testers/gpu_ruby_test/tester_thread.hh @@ -36,6 +36,7 @@ #ifndef CPU_TESTERS_PROTOCOL_TESTER_TESTER_THREAD_HH_ #define CPU_TESTERS_PROTOCOL_TESTER_TESTER_THREAD_HH_ +#include "base/random.hh" #include "cpu/testers/gpu_ruby_test/address_manager.hh" #include "cpu/testers/gpu_ruby_test/episode.hh" #include "cpu/testers/gpu_ruby_test/protocol_tester.hh" @@ -205,7 +206,11 @@ class TesterThread : public ClockedObject void printOutstandingReqs(const OutstandingReqTable& table, std::stringstream& ss) const; + std::string printAddress(Addr addr) const; + + private: + Random::RandomPtr rng = Random::genRandom(); }; } // namespace gem5 diff --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc index e3859ff44c..f1650af1f4 100644 --- a/src/cpu/testers/memtest/memtest.cc +++ b/src/cpu/testers/memtest/memtest.cc @@ -41,7 +41,6 @@ #include "cpu/testers/memtest/memtest.hh" #include "base/compiler.hh" -#include "base/random.hh" #include "base/statistics.hh" #include "base/trace.hh" #include "debug/MemTest.hh" @@ -241,12 +240,12 @@ MemTest::tick() assert(!waitResponse); // create a new request - unsigned cmd = random_mt.random(0, 100); - uint8_t data = random_mt.random(); - bool uncacheable = random_mt.random(0, 100) < percentUncacheable; - bool do_atomic = (random_mt.random(0, 100) < percentAtomic) && + unsigned cmd = rng->random(0, 100); + uint8_t data = rng->random(); + bool uncacheable = rng->random(0, 100) < percentUncacheable; + bool do_atomic = (rng->random(0, 100) < percentAtomic) && !uncacheable; - unsigned base = random_mt.random(0, 1); + unsigned base = rng->random(0, 1); Request::Flags flags; Addr paddr; @@ -259,7 +258,7 @@ MemTest::tick() // generate a unique address do { - unsigned offset = random_mt.random(0, size - 1); + unsigned offset = rng->random(0, size - 1); // use the tester id as offset within the block for false sharing offset = blockAlign(offset); @@ -273,7 +272,7 @@ MemTest::tick() } } while (outstandingAddrs.find(paddr) != outstandingAddrs.end()); - bool do_functional = (random_mt.random(0, 100) < percentFunctional) && + bool do_functional = (rng->random(0, 100) < percentFunctional) && !uncacheable; RequestPtr req = std::make_shared(paddr, 1, flags, requestorId); req->setContext(id); diff --git a/src/cpu/testers/memtest/memtest.hh b/src/cpu/testers/memtest/memtest.hh index 32ffd5cd6e..734bc26b2e 100644 --- a/src/cpu/testers/memtest/memtest.hh +++ b/src/cpu/testers/memtest/memtest.hh @@ -44,6 +44,7 @@ #include #include +#include "base/random.hh" #include "base/statistics.hh" #include "mem/port.hh" #include "params/MemTest.hh" @@ -198,6 +199,8 @@ class MemTest : public ClockedObject void recvRetry(); + private: + Random::RandomPtr rng = Random::genRandom(); }; } // namespace gem5 diff --git a/src/cpu/testers/rubytest/Check.cc b/src/cpu/testers/rubytest/Check.cc index b9c777526a..4c1a47e26d 100644 --- a/src/cpu/testers/rubytest/Check.cc +++ b/src/cpu/testers/rubytest/Check.cc @@ -29,7 +29,6 @@ #include "cpu/testers/rubytest/Check.hh" -#include "base/random.hh" #include "base/trace.hh" #include "debug/RubyTest.hh" #include "mem/ruby/common/SubBlock.hh" @@ -51,7 +50,7 @@ Check::Check(Addr address, Addr pc, int _num_writers, int _num_readers, changeAddress(address); m_pc = pc; m_access_mode = ruby::RubyAccessMode( - random_mt.random(0, ruby::RubyAccessMode_NUM - 1)); + rng->random(0, ruby::RubyAccessMode_NUM - 1)); m_store_count = 0; } @@ -62,11 +61,11 @@ Check::initiate() debugPrint(); // currently no protocols support prefetches - if (false && (random_mt.random(0, 0xf) == 0)) { + if (false && (rng->random(0, 0xf) == 0)) { initiatePrefetch(); // Prefetch from random processor } - if (m_tester_ptr->getCheckFlush() && (random_mt.random(0, 0xff) == 0)) { + if (m_tester_ptr->getCheckFlush() && (rng->random(0, 0xff) == 0)) { initiateFlush(); // issue a Flush request from random processor } @@ -86,7 +85,7 @@ Check::initiatePrefetch() { DPRINTF(RubyTest, "initiating prefetch\n"); - int index = random_mt.random(0, m_num_readers - 1); + int index = rng->random(0, m_num_readers - 1); RequestPort* port = m_tester_ptr->getReadableCpuPort(index); Request::Flags flags; @@ -95,13 +94,13 @@ Check::initiatePrefetch() Packet::Command cmd; // 1 in 8 chance this will be an exclusive prefetch - if (random_mt.random(0, 0x7) != 0) { + if (rng->random(0, 0x7) != 0) { cmd = MemCmd::ReadReq; // if necessary, make the request an instruction fetch if (m_tester_ptr->isInstOnlyCpuPort(index) || (m_tester_ptr->isInstDataCpuPort(index) && - (random_mt.random(0, 0x1)))) { + (rng->random(0, 0x1)))) { flags.set(Request::INST_FETCH); } } else { @@ -145,7 +144,7 @@ Check::initiateFlush() DPRINTF(RubyTest, "initiating Flush\n"); - int index = random_mt.random(0, m_num_writers - 1); + int index = rng->random(0, m_num_writers - 1); RequestPort* port = m_tester_ptr->getWritableCpuPort(index); Request::Flags flags; @@ -176,7 +175,7 @@ Check::initiateAction() DPRINTF(RubyTest, "initiating Action\n"); assert(m_status == ruby::TesterStatus_Idle); - int index = random_mt.random(0, m_num_writers - 1); + int index = rng->random(0, m_num_writers - 1); RequestPort* port = m_tester_ptr->getWritableCpuPort(index); Request::Flags flags; @@ -238,7 +237,7 @@ Check::initiateCheck() DPRINTF(RubyTest, "Initiating Check\n"); assert(m_status == ruby::TesterStatus_Ready); - int index = random_mt.random(0, m_num_readers - 1); + int index = rng->random(0, m_num_readers - 1); RequestPort* port = m_tester_ptr->getReadableCpuPort(index); Request::Flags flags; @@ -246,7 +245,7 @@ Check::initiateCheck() // If necessary, make the request an instruction fetch if (m_tester_ptr->isInstOnlyCpuPort(index) || (m_tester_ptr->isInstDataCpuPort(index) && - (random_mt.random(0, 0x1)))) { + (rng->random(0, 0x1)))) { flags.set(Request::INST_FETCH); } @@ -368,7 +367,7 @@ void Check::pickValue() { assert(m_status == ruby::TesterStatus_Idle); - m_value = random_mt.random(0, 0xff); // One byte + m_value = rng->random(0, 0xff); // One byte m_store_count = 0; } @@ -378,7 +377,7 @@ Check::pickInitiatingNode() assert(m_status == ruby::TesterStatus_Idle || m_status == ruby::TesterStatus_Ready); m_status = ruby::TesterStatus_Idle; - m_initiatingNode = (random_mt.random(0, m_num_writers - 1)); + m_initiatingNode = (rng->random(0, m_num_writers - 1)); DPRINTF(RubyTest, "Check %#x, State=Idle, picked initiating node %d\n", m_address, m_initiatingNode); m_store_count = 0; diff --git a/src/cpu/testers/rubytest/Check.hh b/src/cpu/testers/rubytest/Check.hh index 0270b800d7..2fdf4a51d2 100644 --- a/src/cpu/testers/rubytest/Check.hh +++ b/src/cpu/testers/rubytest/Check.hh @@ -32,6 +32,7 @@ #include +#include "base/random.hh" #include "cpu/testers/rubytest/RubyTester.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/protocol/RubyAccessMode.hh" @@ -84,6 +85,7 @@ class Check int m_num_writers; int m_num_readers; RubyTester* m_tester_ptr; + Random::RandomPtr rng = Random::genRandom(); }; inline std::ostream& diff --git a/src/cpu/testers/rubytest/CheckTable.cc b/src/cpu/testers/rubytest/CheckTable.cc index f5ba304ccb..1ab974a07f 100644 --- a/src/cpu/testers/rubytest/CheckTable.cc +++ b/src/cpu/testers/rubytest/CheckTable.cc @@ -30,7 +30,6 @@ #include "cpu/testers/rubytest/CheckTable.hh" #include "base/intmath.hh" -#include "base/random.hh" #include "base/trace.hh" #include "cpu/testers/rubytest/Check.hh" #include "debug/RubyTest.hh" @@ -114,7 +113,7 @@ Check* CheckTable::getRandomCheck() { assert(m_check_vector.size() > 0); - return m_check_vector[random_mt.random(0, m_check_vector.size() - 1)]; + return m_check_vector[rng->random(0, m_check_vector.size() - 1)]; } Check* diff --git a/src/cpu/testers/rubytest/CheckTable.hh b/src/cpu/testers/rubytest/CheckTable.hh index d832343539..54f1027b74 100644 --- a/src/cpu/testers/rubytest/CheckTable.hh +++ b/src/cpu/testers/rubytest/CheckTable.hh @@ -34,6 +34,7 @@ #include #include +#include "base/random.hh" #include "mem/ruby/common/Address.hh" namespace gem5 @@ -71,6 +72,7 @@ class CheckTable int m_num_writers; int m_num_readers; RubyTester* m_tester_ptr; + Random::RandomPtr rng = Random::genRandom(); }; inline std::ostream& diff --git a/src/cpu/testers/spatter_gen/utility_structs.hh b/src/cpu/testers/spatter_gen/utility_structs.hh index d64cd481c5..45a0f7e03d 100644 --- a/src/cpu/testers/spatter_gen/utility_structs.hh +++ b/src/cpu/testers/spatter_gen/utility_structs.hh @@ -148,11 +148,14 @@ struct SpatterAccess : public Packet::SenderState uint8_t* pkt_data = new uint8_t[req->getSize()]; // Randomly intialize pkt_data, for testing cache coherence. for (int i = 0; i < req->getSize(); i++) { - pkt_data[i] = random_mt.random(); + pkt_data[i] = rng->random(); } pkt->dataDynamic(pkt_data); return pkt; } + + private: + mutable Random::RandomPtr rng = Random::genRandom(); }; class SpatterKernel diff --git a/src/cpu/testers/traffic_gen/base_gen.hh b/src/cpu/testers/traffic_gen/base_gen.hh index 6c8c5eaeed..97462ed6b0 100644 --- a/src/cpu/testers/traffic_gen/base_gen.hh +++ b/src/cpu/testers/traffic_gen/base_gen.hh @@ -46,6 +46,7 @@ #include #include +#include "base/random.hh" #include "base/types.hh" #include "mem/packet.hh" #include "mem/request.hh" @@ -72,6 +73,8 @@ class BaseGen /** The RequestorID used for generating requests */ const RequestorID requestorId; + mutable Random::RandomPtr rng = Random::genRandom(); + /** * Generate a new request and associated packet * diff --git a/src/cpu/testers/traffic_gen/dram_gen.cc b/src/cpu/testers/traffic_gen/dram_gen.cc index 4511be4d18..c4a2786af7 100644 --- a/src/cpu/testers/traffic_gen/dram_gen.cc +++ b/src/cpu/testers/traffic_gen/dram_gen.cc @@ -39,7 +39,6 @@ #include -#include "base/random.hh" #include "base/trace.hh" #include "debug/TrafficGen.hh" #include "enums/AddrMap.hh" @@ -87,7 +86,7 @@ DramGen::getNextPacket() // choose if we generate a read or a write here isRead = readPercent != 0 && - (readPercent == 100 || random_mt.random(0, 100) < readPercent); + (readPercent == 100 || rng->random(0, 100) < readPercent); assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) || @@ -95,11 +94,11 @@ DramGen::getNextPacket() // pick a random bank unsigned int new_bank = - random_mt.random(0, nbrOfBanksUtil - 1); + rng->random(0, nbrOfBanksUtil - 1); // pick a random rank unsigned int new_rank = - random_mt.random(0, nbrOfRanks - 1); + rng->random(0, nbrOfRanks - 1); // Generate the start address of the command series // routine will update addr variable with bank, rank, and col @@ -146,7 +145,7 @@ void DramGen::genStartAddr(unsigned int new_bank, unsigned int new_rank) { // start by picking a random address in the range - addr = random_mt.random(startAddr, endAddr - 1); + addr = rng->random(startAddr, endAddr - 1); // round down to start address of a block, i.e. a DRAM burst addr -= addr % blocksize; @@ -167,7 +166,7 @@ DramGen::genStartAddr(unsigned int new_bank, unsigned int new_rank) // pick a random column, but ensure that there is room for // numSeqPkts sequential columns in the same page unsigned int new_col = - random_mt.random(0, columns_per_page - numSeqPkts); + rng->random(0, columns_per_page - numSeqPkts); if (addrMapping == enums::RoRaBaCoCh || addrMapping == enums::RoRaBaChCo) { diff --git a/src/cpu/testers/traffic_gen/dram_rot_gen.cc b/src/cpu/testers/traffic_gen/dram_rot_gen.cc index d238120645..401151bb1a 100644 --- a/src/cpu/testers/traffic_gen/dram_rot_gen.cc +++ b/src/cpu/testers/traffic_gen/dram_rot_gen.cc @@ -39,7 +39,6 @@ #include -#include "base/random.hh" #include "base/trace.hh" #include "debug/TrafficGen.hh" #include "enums/AddrMap.hh" diff --git a/src/cpu/testers/traffic_gen/gups_gen.cc b/src/cpu/testers/traffic_gen/gups_gen.cc index 3ed1fa4b65..84c727ae46 100644 --- a/src/cpu/testers/traffic_gen/gups_gen.cc +++ b/src/cpu/testers/traffic_gen/gups_gen.cc @@ -31,7 +31,6 @@ #include #include -#include "base/random.hh" #include "debug/GUPSGen.hh" #include "sim/sim_exit.hh" @@ -212,7 +211,7 @@ GUPSGen::createNextReq() assert (readRequests < numUpdates); uint64_t value = readRequests; - uint64_t index = random_mt.random((int64_t) 0, tableSize); + uint64_t index = rng->random((int64_t) 0, tableSize); Addr addr = indexToAddr(index); PacketPtr pkt = getReadPacket(addr, elementSize); updateTable[pkt->req] = value; diff --git a/src/cpu/testers/traffic_gen/gups_gen.hh b/src/cpu/testers/traffic_gen/gups_gen.hh index 38865b5480..9c2e1f5a87 100644 --- a/src/cpu/testers/traffic_gen/gups_gen.hh +++ b/src/cpu/testers/traffic_gen/gups_gen.hh @@ -41,6 +41,7 @@ #include #include +#include "base/random.hh" #include "base/statistics.hh" #include "mem/port.hh" #include "params/GUPSGen.hh" @@ -301,6 +302,8 @@ class GUPSGen : public ClockedObject */ int readRequests; + Random::RandomPtr rng = Random::genRandom(); + struct GUPSGenStat : public statistics::Group { GUPSGenStat(GUPSGen* parent); diff --git a/src/cpu/testers/traffic_gen/hybrid_gen.cc b/src/cpu/testers/traffic_gen/hybrid_gen.cc index f2ce9701aa..e17c5f066e 100644 --- a/src/cpu/testers/traffic_gen/hybrid_gen.cc +++ b/src/cpu/testers/traffic_gen/hybrid_gen.cc @@ -39,7 +39,6 @@ #include -#include "base/random.hh" #include "base/trace.hh" #include "debug/TrafficGen.hh" #include "enums/AddrMap.hh" @@ -142,11 +141,11 @@ HybridGen::getNextPacket() // start counting again if (countNumSeqPkts == 0) { isNvm = nvmPercent != 0 && - (nvmPercent == 100 || random_mt.random(0, 100) < nvmPercent); + (nvmPercent == 100 || rng->random(0, 100) < nvmPercent); // choose if we generate a read or a write here isRead = readPercent != 0 && - (readPercent == 100 || random_mt.random(0, 100) < readPercent); + (readPercent == 100 || rng->random(0, 100) < readPercent); assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) || @@ -186,11 +185,11 @@ HybridGen::getNextPacket() // pick a random bank unsigned int new_bank = - random_mt.random(0, nbrOfBanksUtil - 1); + rng->random(0, nbrOfBanksUtil - 1); // pick a random rank unsigned int new_rank = - random_mt.random(0, nbrOfRanks - 1); + rng->random(0, nbrOfRanks - 1); // Generate the start address of the command series // routine will update addr variable with bank, rank, and col @@ -238,7 +237,7 @@ void HybridGen::genStartAddr(unsigned int new_bank, unsigned int new_rank) { // start by picking a random address in the range - addr = random_mt.random(startAddr, endAddr - 1); + addr = rng->random(startAddr, endAddr - 1); // round down to start address of a block, i.e. a DRAM burst addr -= addr % blocksize; @@ -259,7 +258,7 @@ HybridGen::genStartAddr(unsigned int new_bank, unsigned int new_rank) // pick a random column, but ensure that there is room for // numSeqPkts sequential columns in the same page unsigned int new_col = - random_mt.random(0, burst_per_page - numSeqPkts); + rng->random(0, burst_per_page - numSeqPkts); if (addrMapping == enums::RoRaBaCoCh || addrMapping == enums::RoRaBaChCo) { @@ -296,7 +295,7 @@ HybridGen::nextPacketTick(bool elastic, Tick delay) const return MaxTick; } else { // return the time when the next request should take place - Tick wait = random_mt.random(minPeriod, maxPeriod); + Tick wait = rng->random(minPeriod, maxPeriod); // compensate for the delay experienced to not be elastic, by // default the value we generate is from the time we are diff --git a/src/cpu/testers/traffic_gen/idle_gen.cc b/src/cpu/testers/traffic_gen/idle_gen.cc index 1bebc8af03..b081e21ecd 100644 --- a/src/cpu/testers/traffic_gen/idle_gen.cc +++ b/src/cpu/testers/traffic_gen/idle_gen.cc @@ -39,7 +39,6 @@ #include -#include "base/random.hh" #include "base/trace.hh" #include "debug/TrafficGen.hh" diff --git a/src/cpu/testers/traffic_gen/linear_gen.cc b/src/cpu/testers/traffic_gen/linear_gen.cc index ac31254bea..b006791761 100644 --- a/src/cpu/testers/traffic_gen/linear_gen.cc +++ b/src/cpu/testers/traffic_gen/linear_gen.cc @@ -39,7 +39,6 @@ #include -#include "base/random.hh" #include "base/trace.hh" #include "debug/TrafficGen.hh" @@ -59,7 +58,7 @@ LinearGen::getNextPacket() { // choose if we generate a read or a write here bool isRead = readPercent != 0 && - (readPercent == 100 || random_mt.random(0, 100) < readPercent); + (readPercent == 100 || rng->random(0, 100) < readPercent); assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) || readPercent != 100); @@ -99,7 +98,7 @@ LinearGen::nextPacketTick(bool elastic, Tick delay) const return MaxTick; } else { // return the time when the next request should take place - Tick wait = random_mt.random(minPeriod, maxPeriod); + Tick wait = rng->random(minPeriod, maxPeriod); // compensate for the delay experienced to not be elastic, by // default the value we generate is from the time we are diff --git a/src/cpu/testers/traffic_gen/nvm_gen.cc b/src/cpu/testers/traffic_gen/nvm_gen.cc index 053ac8f6c4..cb78dab3b2 100644 --- a/src/cpu/testers/traffic_gen/nvm_gen.cc +++ b/src/cpu/testers/traffic_gen/nvm_gen.cc @@ -39,7 +39,6 @@ #include -#include "base/random.hh" #include "base/trace.hh" #include "debug/TrafficGen.hh" #include "enums/AddrMap.hh" @@ -87,7 +86,7 @@ NvmGen::getNextPacket() // choose if we generate a read or a write here isRead = readPercent != 0 && - (readPercent == 100 || random_mt.random(0, 100) < readPercent); + (readPercent == 100 || rng->random(0, 100) < readPercent); assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) || @@ -95,11 +94,11 @@ NvmGen::getNextPacket() // pick a random bank unsigned int new_bank = - random_mt.random(0, nbrOfBanksUtil - 1); + rng->random(0, nbrOfBanksUtil - 1); // pick a random rank unsigned int new_rank = - random_mt.random(0, nbrOfRanks - 1); + rng->random(0, nbrOfRanks - 1); // Generate the start address of the command series // routine will update addr variable with bank, rank, and col @@ -147,7 +146,7 @@ void NvmGen::genStartAddr(unsigned int new_bank, unsigned int new_rank) { // start by picking a random address in the range - addr = random_mt.random(startAddr, endAddr - 1); + addr = rng->random(startAddr, endAddr - 1); // round down to start address of a block, i.e. a NVM burst addr -= addr % blocksize; @@ -162,7 +161,7 @@ NvmGen::genStartAddr(unsigned int new_bank, unsigned int new_rank) // pick a random burst address, but ensure that there is room for // numSeqPkts sequential bursts in the same buffer unsigned int new_col = - random_mt.random(0, burst_per_buffer - numSeqPkts); + rng->random(0, burst_per_buffer - numSeqPkts); if (addrMapping == enums::RoRaBaCoCh || addrMapping == enums::RoRaBaChCo) { diff --git a/src/cpu/testers/traffic_gen/random_gen.cc b/src/cpu/testers/traffic_gen/random_gen.cc index c1e2ac1fd4..40e2fbd301 100644 --- a/src/cpu/testers/traffic_gen/random_gen.cc +++ b/src/cpu/testers/traffic_gen/random_gen.cc @@ -39,7 +39,6 @@ #include -#include "base/random.hh" #include "base/trace.hh" #include "debug/TrafficGen.hh" @@ -58,13 +57,13 @@ RandomGen::getNextPacket() { // choose if we generate a read or a write here bool isRead = readPercent != 0 && - (readPercent == 100 || random_mt.random(0, 100) < readPercent); + (readPercent == 100 || rng->random(0, 100) < readPercent); assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) || readPercent != 100); // address of the request - Addr addr = random_mt.random(startAddr, endAddr - 1); + Addr addr = rng->random(startAddr, endAddr - 1); // round down to start address of block addr -= addr % blocksize; @@ -93,7 +92,7 @@ RandomGen::nextPacketTick(bool elastic, Tick delay) const return MaxTick; } else { // return the time when the next request should take place - Tick wait = random_mt.random(minPeriod, maxPeriod); + Tick wait = rng->random(minPeriod, maxPeriod); // compensate for the delay experienced to not be elastic, by // default the value we generate is from the time we are diff --git a/src/cpu/testers/traffic_gen/stream_gen.cc b/src/cpu/testers/traffic_gen/stream_gen.cc index 4eb6ffe49d..2d4e8f1fcc 100644 --- a/src/cpu/testers/traffic_gen/stream_gen.cc +++ b/src/cpu/testers/traffic_gen/stream_gen.cc @@ -37,8 +37,6 @@ #include "stream_gen.hh" -#include "base/random.hh" - namespace gem5 { @@ -60,7 +58,7 @@ uint32_t RandomStreamGen::randomPick(const std::vector &svec) { // Pick a random entry in the vector of IDs - return svec[random_mt.random(0, svec.size()-1)]; + return svec[rng->random(0, svec.size()-1)]; } } // namespace gem5 diff --git a/src/cpu/testers/traffic_gen/stream_gen.hh b/src/cpu/testers/traffic_gen/stream_gen.hh index 92509c8c94..02f1290cd7 100644 --- a/src/cpu/testers/traffic_gen/stream_gen.hh +++ b/src/cpu/testers/traffic_gen/stream_gen.hh @@ -44,6 +44,7 @@ #ifndef __CPU_TRAFFIC_GEN_STREAM_GEN_HH__ #define __CPU_TRAFFIC_GEN_STREAM_GEN_HH__ +#include "base/random.hh" #include "params/BaseTrafficGen.hh" namespace gem5 @@ -137,6 +138,8 @@ class RandomStreamGen : public StreamGen protected: /** Function to pick one of the preset Stream or Substream ID */ uint32_t randomPick(const std::vector &svec); + + Random::RandomPtr rng = Random::genRandom(); }; } // namespace gem5 diff --git a/src/cpu/testers/traffic_gen/strided_gen.cc b/src/cpu/testers/traffic_gen/strided_gen.cc index a7c31256a6..06f6264c8d 100644 --- a/src/cpu/testers/traffic_gen/strided_gen.cc +++ b/src/cpu/testers/traffic_gen/strided_gen.cc @@ -39,7 +39,6 @@ #include -#include "base/random.hh" #include "base/trace.hh" #include "debug/TrafficGen.hh" @@ -76,7 +75,7 @@ StridedGen::getNextPacket() { // choose if we generate a read or a write here bool isRead = readPercent != 0 && - (readPercent == 100 || random_mt.random(0, 100) < readPercent); + (readPercent == 100 || rng->random(0, 100) < readPercent); assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) || readPercent != 100); @@ -122,7 +121,7 @@ StridedGen::nextPacketTick(bool elastic, Tick delay) const return MaxTick; } else { // return the time when the next request should take place - Tick wait = random_mt.random(minPeriod, maxPeriod); + Tick wait = rng->random(minPeriod, maxPeriod); // compensate for the delay experienced to not be elastic, by // default the value we generate is from the time we are diff --git a/src/cpu/testers/traffic_gen/trace_gen.cc b/src/cpu/testers/traffic_gen/trace_gen.cc index 7d8fed90e7..6367c3aa5e 100644 --- a/src/cpu/testers/traffic_gen/trace_gen.cc +++ b/src/cpu/testers/traffic_gen/trace_gen.cc @@ -39,7 +39,6 @@ #include -#include "base/random.hh" #include "base/trace.hh" #include "debug/TrafficGen.hh" #include "proto/packet.pb.h" diff --git a/src/cpu/testers/traffic_gen/traffic_gen.cc b/src/cpu/testers/traffic_gen/traffic_gen.cc index 51afd3c9fd..99e73bc826 100644 --- a/src/cpu/testers/traffic_gen/traffic_gen.cc +++ b/src/cpu/testers/traffic_gen/traffic_gen.cc @@ -377,7 +377,7 @@ TrafficGen::parseConfig() size_t TrafficGen::nextState() { - double p = random_mt.random(); + double p = rng->random(); assert(currState < transitionMatrix.size()); double cumulative = 0.0; size_t i = 0; diff --git a/src/cpu/testers/traffic_gen/traffic_gen.hh b/src/cpu/testers/traffic_gen/traffic_gen.hh index 8e695968b5..7a441e13e4 100644 --- a/src/cpu/testers/traffic_gen/traffic_gen.hh +++ b/src/cpu/testers/traffic_gen/traffic_gen.hh @@ -40,6 +40,7 @@ #include +#include "base/random.hh" #include "cpu/testers/traffic_gen/base.hh" namespace gem5 @@ -119,6 +120,8 @@ class TrafficGen : public BaseTrafficGen /** Map of generator states */ std::unordered_map> states; + Random::RandomPtr rng = Random::genRandom(); + protected: // BaseTrafficGen std::shared_ptr nextGenerator() override; diff --git a/src/dev/arm/smmu_v3_caches.cc b/src/dev/arm/smmu_v3_caches.cc index 1280499592..fecac77203 100644 --- a/src/dev/arm/smmu_v3_caches.cc +++ b/src/dev/arm/smmu_v3_caches.cc @@ -65,7 +65,7 @@ SMMUv3BaseCache::SMMUv3BaseCache(const std::string &policy_name, uint32_t seed, statistics::Group *parent, const std::string &name) : replacementPolicy(decodePolicyName(policy_name)), nextToReplace(0), - random(seed), + random(Random::genRandom(seed)), useStamp(0), baseCacheStats(parent, name) {} @@ -410,9 +410,9 @@ SMMUTLB::pickEntryIdxToReplace(const Set &set, AllocPolicy alloc) case SMMU_CACHE_REPL_RANDOM: switch (alloc) { case ALLOC_ANY_WAY: - return random.random(0, associativity-1); + return random->random(0, associativity-1); case ALLOC_ANY_BUT_LAST_WAY: - return random.random(0, associativity-2); + return random->random(0, associativity-2); default: panic("Unknown allocation mode %d\n", alloc); } @@ -615,7 +615,7 @@ ARMArchTLB::pickEntryIdxToReplace(const Set &set) return nextToReplace = ((nextToReplace+1) % associativity); case SMMU_CACHE_REPL_RANDOM: - return random.random(0, associativity-1); + return random->random(0, associativity-1); case SMMU_CACHE_REPL_LRU: return lru_idx; @@ -795,7 +795,7 @@ IPACache::pickEntryIdxToReplace(const Set &set) return nextToReplace = ((nextToReplace+1) % associativity); case SMMU_CACHE_REPL_RANDOM: - return random.random(0, associativity-1); + return random->random(0, associativity-1); case SMMU_CACHE_REPL_LRU: return lru_idx; @@ -959,7 +959,7 @@ ConfigCache::pickEntryIdxToReplace(const Set &set) return nextToReplace = ((nextToReplace+1) % associativity); case SMMU_CACHE_REPL_RANDOM: - return random.random(0, associativity-1); + return random->random(0, associativity-1); case SMMU_CACHE_REPL_LRU: return lru_idx; @@ -1218,7 +1218,7 @@ WalkCache::pickEntryIdxToReplace(const Set &set, return nextToReplace = ((nextToReplace+1) % associativity); case SMMU_CACHE_REPL_RANDOM: - return random.random(0, associativity-1); + return random->random(0, associativity-1); case SMMU_CACHE_REPL_LRU: return lru_idx; diff --git a/src/dev/arm/smmu_v3_caches.hh b/src/dev/arm/smmu_v3_caches.hh index 5a842635b5..d5af626259 100644 --- a/src/dev/arm/smmu_v3_caches.hh +++ b/src/dev/arm/smmu_v3_caches.hh @@ -66,7 +66,7 @@ class SMMUv3BaseCache protected: int replacementPolicy; size_t nextToReplace; - Random random; + Random::RandomPtr random; uint32_t useStamp; struct SMMUv3BaseCacheStats : public statistics::Group diff --git a/src/dev/net/dist_etherlink.cc b/src/dev/net/dist_etherlink.cc index 13deca42e4..56619403a6 100644 --- a/src/dev/net/dist_etherlink.cc +++ b/src/dev/net/dist_etherlink.cc @@ -50,7 +50,6 @@ #include #include -#include "base/random.hh" #include "base/trace.hh" #include "debug/DistEthernet.hh" #include "debug/DistEthernetPkt.hh" @@ -195,7 +194,7 @@ DistEtherLink::TxLink::transmit(EthPacketPtr pkt) packet = pkt; Tick delay = (Tick)ceil(((double)pkt->simLength * ticksPerByte) + 1.0); if (delayVar != 0) - delay += random_mt.random(0, delayVar); + delay += rng->random(0, delayVar); // send the packet to the peers assert(distIface); diff --git a/src/dev/net/dist_etherlink.hh b/src/dev/net/dist_etherlink.hh index 4551d829e5..1c27b88c13 100644 --- a/src/dev/net/dist_etherlink.hh +++ b/src/dev/net/dist_etherlink.hh @@ -51,6 +51,7 @@ #include #include +#include "base/random.hh" #include "base/types.hh" #include "dev/net/etherlink.hh" #include "params/DistEtherLink.hh" @@ -125,6 +126,8 @@ class DistEtherLink : public SimObject void txDone(); EventFunctionWrapper doneEvent; + Random::RandomPtr rng = Random::genRandom(); + public: TxLink(const std::string &name, DistEtherLink *p, double invBW, Tick delay_var, EtherDump *d) : diff --git a/src/dev/net/dist_iface.cc b/src/dev/net/dist_iface.cc index 824139bc31..63cef52557 100644 --- a/src/dev/net/dist_iface.cc +++ b/src/dev/net/dist_iface.cc @@ -44,7 +44,6 @@ #include #include -#include "base/random.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" #include "debug/DistEthernet.hh" @@ -806,7 +805,7 @@ DistIface::init(const Event *done_event, Tick link_delay) // in all gem5 peer processes assert(primary != nullptr); if (this == primary) - random_mt.init(5489 * (rank+1) + 257); + rng->init(5489 * (rank+1) + 257); } void diff --git a/src/dev/net/dist_iface.hh b/src/dev/net/dist_iface.hh index 3d6243e65f..962a1a4561 100644 --- a/src/dev/net/dist_iface.hh +++ b/src/dev/net/dist_iface.hh @@ -82,6 +82,7 @@ #include #include "base/logging.hh" +#include "base/random.hh" #include "dev/net/dist_packet.hh" #include "dev/net/etherpkt.hh" #include "sim/drain.hh" @@ -475,6 +476,8 @@ class DistIface : public Drainable, public Serializable */ bool syncStartOnPseudoOp; + Random::RandomPtr rng = Random::genRandom(); + protected: /** * The rank of this process among the gem5 peers. diff --git a/src/dev/net/etherlink.cc b/src/dev/net/etherlink.cc index 46608ac9a4..e15f44a41c 100644 --- a/src/dev/net/etherlink.cc +++ b/src/dev/net/etherlink.cc @@ -51,7 +51,6 @@ #include #include "base/logging.hh" -#include "base/random.hh" #include "base/trace.hh" #include "debug/Ethernet.hh" #include "debug/EthernetData.hh" @@ -189,7 +188,7 @@ EtherLink::Link::transmit(EthPacketPtr pkt) packet = pkt; Tick delay = (Tick)ceil(((double)pkt->simLength * ticksPerByte) + 1.0); if (delayVar != 0) - delay += random_mt.random(0, delayVar); + delay += rng->random(0, delayVar); DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", delay, ticksPerByte); diff --git a/src/dev/net/etherlink.hh b/src/dev/net/etherlink.hh index 435096de52..3696c6f6d8 100644 --- a/src/dev/net/etherlink.hh +++ b/src/dev/net/etherlink.hh @@ -48,6 +48,7 @@ #include #include +#include "base/random.hh" #include "base/types.hh" #include "dev/net/etherint.hh" #include "dev/net/etherpkt.hh" @@ -87,6 +88,8 @@ class EtherLink : public SimObject const Tick delayVar; EtherDump *const dump; + Random::RandomPtr rng = Random::genRandom(); + protected: /* * Transfer is complete diff --git a/src/dev/net/etherswitch.cc b/src/dev/net/etherswitch.cc index a148b756f6..bc1fb0c869 100644 --- a/src/dev/net/etherswitch.cc +++ b/src/dev/net/etherswitch.cc @@ -32,7 +32,6 @@ #include "dev/net/etherswitch.hh" -#include "base/random.hh" #include "base/trace.hh" #include "debug/EthernetAll.hh" #include "sim/core.hh" @@ -204,7 +203,7 @@ EtherSwitch::Interface::switchingDelay() Tick delay = (Tick)ceil(((double)outputFifo.front()->simLength * ticksPerByte) + 1.0); if (delayVar != 0) - delay += random_mt.random(0, delayVar); + delay += rng->random(0, delayVar); delay += switchDelay; return delay; } diff --git a/src/dev/net/etherswitch.hh b/src/dev/net/etherswitch.hh index 8aa56c5568..ef51e3142b 100644 --- a/src/dev/net/etherswitch.hh +++ b/src/dev/net/etherswitch.hh @@ -39,6 +39,7 @@ #include #include "base/inet.hh" +#include "base/random.hh" #include "dev/net/etherint.hh" #include "dev/net/etherlink.hh" #include "dev/net/etherpkt.hh" @@ -95,6 +96,7 @@ class EtherSwitch : public SimObject const Tick switchDelay; const Tick delayVar; const unsigned interfaceId; + Random::RandomPtr rng = Random::genRandom(); EtherSwitch *parent; protected: diff --git a/src/dev/virtio/rng.cc b/src/dev/virtio/rng.cc index c26568eb94..15b95079b2 100644 --- a/src/dev/virtio/rng.cc +++ b/src/dev/virtio/rng.cc @@ -38,7 +38,6 @@ #include "dev/virtio/rng.hh" -#include "base/random.hh" #include "debug/VIORng.hh" #include "params/VirtIORng.hh" #include "sim/system.hh" @@ -80,7 +79,7 @@ VirtIORng::RngQueue::trySend() DPRINTF(VIORng, "Got descriptor (len: %i)\n", d->size()); size_t len = 0; while (len < d->size()) { - uint8_t byte = gem5::random_mt.random(); + uint8_t byte = rng->random(); d->chainWrite(len, &byte, sizeof(uint8_t)); ++len; } diff --git a/src/dev/virtio/rng.hh b/src/dev/virtio/rng.hh index 7be235421a..ada1e2c266 100644 --- a/src/dev/virtio/rng.hh +++ b/src/dev/virtio/rng.hh @@ -40,6 +40,7 @@ #define __DEV_VIRTIO_RNG_HH__ #include "base/compiler.hh" +#include "base/random.hh" #include "dev/virtio/base.hh" namespace gem5 @@ -70,8 +71,7 @@ class VirtIORng : public VirtIODeviceBase /** * Virtqueue for data going from the host to the guest. */ - class RngQueue - : public VirtQueue + class RngQueue : public VirtQueue { public: RngQueue(PortProxy &proxy, ByteOrder bo, uint16_t size, @@ -87,6 +87,8 @@ class VirtIORng : public VirtIODeviceBase protected: VirtIORng &parent; + + Random::RandomPtr rng = Random::genRandom(); }; /** Receive queue for port 0 */ RngQueue qReq; diff --git a/src/kern/linux/linux.cc b/src/kern/linux/linux.cc index 11b9fe0ee4..78f54f2db9 100644 --- a/src/kern/linux/linux.cc +++ b/src/kern/linux/linux.cc @@ -45,7 +45,7 @@ namespace gem5 // The OS methods are called statically. Instantiate the random number // generator for access to /dev/urandom here. -Random Linux::random; +Random::RandomPtr Linux::random = Random::genRandom(); int Linux::openSpecialFile(std::string path, Process *process, @@ -128,7 +128,7 @@ Linux::devRandom(Process *process, ThreadContext *tc) std::stringstream line; int max = 1E5; for (int i = 0; i < max; i++) { - uint8_t rand_uint = random.random(0, 255); + uint8_t rand_uint = random->random(0, 255); line << rand_uint; } diff --git a/src/kern/linux/linux.hh b/src/kern/linux/linux.hh index 9d1d5392de..1d89694a31 100644 --- a/src/kern/linux/linux.hh +++ b/src/kern/linux/linux.hh @@ -256,7 +256,7 @@ class Linux : public OperatingSystem }; // For /dev/urandom accesses - static Random random; + static Random::RandomPtr random; static int openSpecialFile(std::string path, Process *process, ThreadContext *tc); diff --git a/src/learning_gem5/part2/simple_cache.cc b/src/learning_gem5/part2/simple_cache.cc index 3049bb0e3c..6f55485ba1 100644 --- a/src/learning_gem5/part2/simple_cache.cc +++ b/src/learning_gem5/part2/simple_cache.cc @@ -29,7 +29,6 @@ #include "learning_gem5/part2/simple_cache.hh" #include "base/compiler.hh" -#include "base/random.hh" #include "debug/SimpleCache.hh" #include "sim/system.hh" @@ -373,10 +372,10 @@ SimpleCache::insert(PacketPtr pkt) // are using a std::unordered_map. See http://bit.ly/2hrnLP2 int bucket, bucket_size; do { - bucket = random_mt.random(0, (int)cacheStore.bucket_count() - 1); + bucket = rng->random(0, (int)cacheStore.bucket_count() - 1); } while ( (bucket_size = cacheStore.bucket_size(bucket)) == 0 ); auto block = std::next(cacheStore.begin(bucket), - random_mt.random(0, bucket_size - 1)); + rng->random(0, bucket_size - 1)); DPRINTF(SimpleCache, "Removing addr %#x\n", block->first); diff --git a/src/learning_gem5/part2/simple_cache.hh b/src/learning_gem5/part2/simple_cache.hh index 1ca87dd126..23122c5e95 100644 --- a/src/learning_gem5/part2/simple_cache.hh +++ b/src/learning_gem5/part2/simple_cache.hh @@ -31,6 +31,7 @@ #include +#include "base/random.hh" #include "base/statistics.hh" #include "mem/port.hh" #include "params/SimpleCache.hh" @@ -49,7 +50,6 @@ namespace gem5 class SimpleCache : public ClockedObject { private: - /** * Port on the CPU-side that receives requests. * Mostly just forwards requests to the cache (owner) @@ -294,6 +294,8 @@ class SimpleCache : public ClockedObject /// An incredibly simple cache storage. Maps block addresses to data std::unordered_map cacheStore; + Random::RandomPtr rng = Random::genRandom(); + /// Cache statistics protected: struct SimpleCacheStats : public statistics::Group diff --git a/src/mem/cache/replacement_policies/bip_rp.cc b/src/mem/cache/replacement_policies/bip_rp.cc index 812c36bb71..560a06fe34 100644 --- a/src/mem/cache/replacement_policies/bip_rp.cc +++ b/src/mem/cache/replacement_policies/bip_rp.cc @@ -30,7 +30,6 @@ #include -#include "base/random.hh" #include "params/BIPRP.hh" #include "sim/cur_tick.hh" @@ -52,7 +51,7 @@ BIP::reset(const std::shared_ptr& replacement_data) const std::static_pointer_cast(replacement_data); // Entries are inserted as MRU if lower than btp, LRU otherwise - if (random_mt.random(1, 100) <= btp) { + if (rng->random(1, 100) <= btp) { casted_replacement_data->lastTouchTick = curTick(); } else { // Make their timestamps as old as possible, so that they become LRU diff --git a/src/mem/cache/replacement_policies/bip_rp.hh b/src/mem/cache/replacement_policies/bip_rp.hh index 0b830e0b79..8c7b3fbd33 100644 --- a/src/mem/cache/replacement_policies/bip_rp.hh +++ b/src/mem/cache/replacement_policies/bip_rp.hh @@ -42,6 +42,7 @@ #ifndef __MEM_CACHE_REPLACEMENT_POLICIES_BIP_RP_HH__ #define __MEM_CACHE_REPLACEMENT_POLICIES_BIP_RP_HH__ +#include "base/random.hh" #include "mem/cache/replacement_policies/lru_rp.hh" namespace gem5 @@ -61,6 +62,8 @@ class BIP : public LRU */ const unsigned btp; + mutable Random::RandomPtr rng = Random::genRandom(); + public: typedef BIPRPParams Params; BIP(const Params &p); diff --git a/src/mem/cache/replacement_policies/brrip_rp.cc b/src/mem/cache/replacement_policies/brrip_rp.cc index 06dad0d9fb..b4cf94405d 100644 --- a/src/mem/cache/replacement_policies/brrip_rp.cc +++ b/src/mem/cache/replacement_policies/brrip_rp.cc @@ -32,7 +32,6 @@ #include #include "base/logging.hh" // For fatal_if -#include "base/random.hh" #include "params/BRRIPRP.hh" namespace gem5 @@ -84,7 +83,7 @@ BRRIP::reset(const std::shared_ptr& replacement_data) const // Replacement data is inserted as "long re-reference" if lower than btp, // "distant re-reference" otherwise casted_replacement_data->rrpv.saturate(); - if (random_mt.random(1, 100) <= btp) { + if (rng->random(1, 100) <= btp) { casted_replacement_data->rrpv--; } diff --git a/src/mem/cache/replacement_policies/brrip_rp.hh b/src/mem/cache/replacement_policies/brrip_rp.hh index 5649a64070..d3c8c89633 100644 --- a/src/mem/cache/replacement_policies/brrip_rp.hh +++ b/src/mem/cache/replacement_policies/brrip_rp.hh @@ -52,6 +52,7 @@ #ifndef __MEM_CACHE_REPLACEMENT_POLICIES_BRRIP_RP_HH__ #define __MEM_CACHE_REPLACEMENT_POLICIES_BRRIP_RP_HH__ +#include "base/random.hh" #include "base/sat_counter.hh" #include "mem/cache/replacement_policies/base.hh" @@ -111,6 +112,8 @@ class BRRIP : public Base */ const unsigned btp; + mutable Random::RandomPtr rng = Random::genRandom(); + public: typedef BRRIPRPParams Params; BRRIP(const Params &p); diff --git a/src/mem/cache/replacement_policies/random_rp.cc b/src/mem/cache/replacement_policies/random_rp.cc index 8711c85ba3..2e3bd8a981 100644 --- a/src/mem/cache/replacement_policies/random_rp.cc +++ b/src/mem/cache/replacement_policies/random_rp.cc @@ -31,7 +31,6 @@ #include #include -#include "base/random.hh" #include "params/RandomRP.hh" namespace gem5 @@ -73,7 +72,7 @@ Random::getVictim(const ReplacementCandidates& candidates) const assert(candidates.size() > 0); // Choose one candidate at random - ReplaceableEntry* victim = candidates[random_mt.random(0, + ReplaceableEntry* victim = candidates[rng->random(0, candidates.size() - 1)]; // Visit all candidates to search for an invalid entry. If one is found, diff --git a/src/mem/cache/replacement_policies/random_rp.hh b/src/mem/cache/replacement_policies/random_rp.hh index a2b384563c..0f4059d3a1 100644 --- a/src/mem/cache/replacement_policies/random_rp.hh +++ b/src/mem/cache/replacement_policies/random_rp.hh @@ -35,6 +35,7 @@ #ifndef __MEM_CACHE_REPLACEMENT_POLICIES_RANDOM_RP_HH__ #define __MEM_CACHE_REPLACEMENT_POLICIES_RANDOM_RP_HH__ +#include "base/random.hh" #include "mem/cache/replacement_policies/base.hh" namespace gem5 @@ -48,6 +49,8 @@ namespace replacement_policy class Random : public Base { protected: + mutable gem5::Random::RandomPtr rng = gem5::Random::genRandom(); + /** Random-specific implementation of replacement data. */ struct RandomReplData : ReplacementData { diff --git a/src/mem/cfi_mem.cc b/src/mem/cfi_mem.cc index b5354ffcbd..54cf415da2 100644 --- a/src/mem/cfi_mem.cc +++ b/src/mem/cfi_mem.cc @@ -406,7 +406,7 @@ Tick CfiMemory::getLatency() const { return latency + - (latency_var ? random_mt.random(0, latency_var) : 0); + (latency_var ? rng->random(0, latency_var) : 0); } void diff --git a/src/mem/cfi_mem.hh b/src/mem/cfi_mem.hh index 4a0226736a..af21db8c31 100644 --- a/src/mem/cfi_mem.hh +++ b/src/mem/cfi_mem.hh @@ -41,6 +41,7 @@ #ifndef __MEM_FLASH_MEM_HH__ #define __MEM_FLASH_MEM_HH__ +#include "base/random.hh" #include "mem/abstract_mem.hh" #include "params/CfiMemory.hh" @@ -347,6 +348,8 @@ class CfiMemory : public AbstractMemory uint8_t cfiQueryTable[61]; + mutable Random::RandomPtr rng = Random::genRandom(); + public: CfiMemory(const CfiMemoryParams &p); diff --git a/src/mem/ruby/network/MessageBuffer.cc b/src/mem/ruby/network/MessageBuffer.cc index 8b3a724469..48d4ac17bb 100644 --- a/src/mem/ruby/network/MessageBuffer.cc +++ b/src/mem/ruby/network/MessageBuffer.cc @@ -205,10 +205,11 @@ MessageBuffer::peek() const Tick random_time() { + static Random::RandomPtr rng = Random::genRandom(); Tick time = 1; - time += random_mt.random(0, 3); // [0...3] - if (random_mt.random(0, 7) == 0) { // 1 in 8 chance - time += 100 + random_mt.random(1, 15); // 100 + [1...15] + time += rng->random(0, 3); // [0...3] + if (rng->random(0, 7) == 0) { // 1 in 8 chance + time += 100 + rng->random(1, 15); // 100 + [1...15] } return time; } diff --git a/src/mem/ruby/network/simple/routing/WeightBased.cc b/src/mem/ruby/network/simple/routing/WeightBased.cc index a63b0fab86..25b6c30392 100644 --- a/src/mem/ruby/network/simple/routing/WeightBased.cc +++ b/src/mem/ruby/network/simple/routing/WeightBased.cc @@ -42,7 +42,6 @@ #include -#include "base/random.hh" #include "mem/ruby/network/simple/Switch.hh" namespace gem5 @@ -95,7 +94,7 @@ WeightBased::route(const Message &msg, // improve load distribution by randomizing order of links // with the same queue length link->m_order = - (out_queue_length << 8) | random_mt.random(0, 0xff); + (out_queue_length << 8) | rng->random(0, 0xff); } } sortLinks(); diff --git a/src/mem/ruby/network/simple/routing/WeightBased.hh b/src/mem/ruby/network/simple/routing/WeightBased.hh index a723e9bdc9..5df0af9e09 100644 --- a/src/mem/ruby/network/simple/routing/WeightBased.hh +++ b/src/mem/ruby/network/simple/routing/WeightBased.hh @@ -41,6 +41,7 @@ #ifndef __MEM_RUBY_NETWORK_SIMPLE_WEIGHTBASEDROUTINGUNIT_HH__ #define __MEM_RUBY_NETWORK_SIMPLE_WEIGHTBASEDROUTINGUNIT_HH__ +#include "base/random.hh" #include "mem/ruby/network/simple/routing/BaseRoutingUnit.hh" #include "params/WeightBased.hh" @@ -80,6 +81,8 @@ class WeightBased : public BaseRoutingUnit std::vector> m_links; + Random::RandomPtr rng = Random::genRandom(); + void findRoute(const Message &msg, std::vector &out_links) const; diff --git a/src/mem/simple_mem.cc b/src/mem/simple_mem.cc index a3809c5379..62e8640f08 100644 --- a/src/mem/simple_mem.cc +++ b/src/mem/simple_mem.cc @@ -237,7 +237,7 @@ Tick SimpleMemory::getLatency() const { return latency + - (latency_var ? random_mt.random(0, latency_var) : 0); + (latency_var ? rng->random(0, latency_var) : 0); } void diff --git a/src/mem/simple_mem.hh b/src/mem/simple_mem.hh index 75a03fbe0e..bc40b5cd54 100644 --- a/src/mem/simple_mem.hh +++ b/src/mem/simple_mem.hh @@ -48,6 +48,7 @@ #include +#include "base/random.hh" #include "mem/abstract_mem.hh" #include "mem/port.hh" #include "params/SimpleMemory.hh" @@ -150,6 +151,8 @@ class SimpleMemory : public AbstractMemory */ bool retryResp; + mutable Random::RandomPtr rng = Random::genRandom(); + /** * Release the memory after being busy and send a retry if a * request was rejected in the meanwhile. diff --git a/src/python/pybind11/core.cc b/src/python/pybind11/core.cc index 0b03d5a13b..98208701de 100644 --- a/src/python/pybind11/core.cc +++ b/src/python/pybind11/core.cc @@ -310,7 +310,9 @@ pybind_init_core(py::module_ &m_native) .def("disableAllListeners", &ListenSocket::disableAll) .def("listenersDisabled", &ListenSocket::allDisabled) .def("listenersLoopbackOnly", &ListenSocket::loopbackOnly) - .def("seedRandom", [](uint64_t seed) { random_mt.init(seed); }) + .def("seedRandom", [](uint64_t seed) { + Random::reseedAll(seed); + }) .def("fixClockFrequency", &fixClockFrequency) diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index b72d12025b..986e394851 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -3218,11 +3218,12 @@ getrandomFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, typename OS::size_t count, unsigned int flags) { + static Random::RandomPtr se_prng = Random::genRandom(); SETranslatingPortProxy proxy(tc); TypedBufferArg buf(buf_ptr, count); for (int i = 0; i < count; ++i) { - buf[i] = gem5::random_mt.random(); + buf[i] = se_prng->random(); } buf.copyOut(proxy);